opencos-eda 0.3.11__py3-none-any.whl → 0.3.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. opencos/commands/flist.py +222 -39
  2. opencos/commands/multi.py +5 -3
  3. opencos/commands/sim.py +121 -7
  4. opencos/commands/sweep.py +1 -1
  5. opencos/commands/upload.py +4 -4
  6. opencos/commands/waves.py +44 -0
  7. opencos/deps/deps_file.py +4 -1
  8. opencos/deps_schema.py +2 -2
  9. opencos/eda.py +284 -175
  10. opencos/eda_base.py +54 -22
  11. opencos/eda_config.py +51 -24
  12. opencos/eda_config_defaults.yml +326 -195
  13. opencos/eda_config_reduced.yml +19 -39
  14. opencos/eda_tool_helper.py +193 -24
  15. opencos/tools/cocotb.py +6 -29
  16. opencos/tools/invio.py +0 -6
  17. opencos/tools/iverilog.py +16 -16
  18. opencos/tools/modelsim_ase.py +1 -13
  19. opencos/tools/quartus.py +81 -24
  20. opencos/tools/questa.py +0 -14
  21. opencos/tools/questa_common.py +95 -30
  22. opencos/tools/questa_fe.py +0 -14
  23. opencos/tools/questa_fse.py +0 -14
  24. opencos/tools/riviera.py +56 -25
  25. opencos/tools/slang.py +15 -12
  26. opencos/tools/slang_yosys.py +0 -6
  27. opencos/tools/surelog.py +14 -11
  28. opencos/tools/tabbycad_yosys.py +1 -7
  29. opencos/tools/verilator.py +18 -14
  30. opencos/tools/vivado.py +57 -22
  31. opencos/tools/yosys.py +2 -4
  32. opencos/util.py +14 -5
  33. opencos/utils/str_helpers.py +42 -1
  34. {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/METADATA +1 -2
  35. {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/RECORD +40 -41
  36. opencos/eda_config_max_verilator_waivers.yml +0 -39
  37. {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/WHEEL +0 -0
  38. {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/entry_points.txt +0 -0
  39. {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/licenses/LICENSE +0 -0
  40. {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/licenses/LICENSE.spdx +0 -0
  41. {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/top_level.txt +0 -0
@@ -34,6 +34,47 @@ class ToolQuesta(Tool):
34
34
  def __init__(self, config: dict):
35
35
  super().__init__(config=config)
36
36
 
37
+
38
+ def _try_set_version_from_release_notes(self) -> None:
39
+ '''Attempts to use a RELEASE_NOTES.txt file to get version info
40
+
41
+ Return None, may set self._VERSION
42
+
43
+ {path}/../docs/rlsnotes/RELEASE_NOTES.txt, where first line
44
+ '''
45
+ release_notes_txt_filepath = os.path.join(
46
+ self.sim_exe_base_path, '..', 'docs', 'rlsnotes', 'RELEASE_NOTES.txt'
47
+ )
48
+ if not os.path.isfile(release_notes_txt_filepath):
49
+ return
50
+
51
+ with open(release_notes_txt_filepath, encoding='utf-8') as f:
52
+ for line in f.readlines():
53
+ if line.strip().startswith('Release Notes For'):
54
+ m = re.search(r'(\d+)\.(\d+)', line)
55
+ if m:
56
+ if self._TOOL.startswith('questa'):
57
+ # don't set these for ModelsimASE:
58
+ self.questa_major = int(m.group(1))
59
+ self.questa_minor = int(m.group(2))
60
+ self._VERSION = str(self.questa_major) + '.' + str(self.questa_minor)
61
+ util.debug(f'version {self._VERSION} ({release_notes_txt_filepath})')
62
+ break
63
+
64
+ def _try_set_version_from_path(self) -> None:
65
+ '''Attempts to use portions of exe path to get version info
66
+
67
+ Return None, may set self._VERSION
68
+ '''
69
+ m = re.search(r'(\d+)\.(\d+)', self.sim_exe_base_path)
70
+ if m:
71
+ self.questa_major = int(m.group(1))
72
+ self.questa_minor = int(m.group(2))
73
+ self._VERSION = str(self.questa_major) + '.' + str(self.questa_minor)
74
+ else:
75
+ util.warning("Questa path doesn't specificy version, expecting (d+.d+)")
76
+
77
+
37
78
  def get_versions(self) -> str:
38
79
  if self._VERSION:
39
80
  return self._VERSION
@@ -51,20 +92,25 @@ class ToolQuesta(Tool):
51
92
  self.sim_exe = path
52
93
  self.sim_exe_base_path, _ = os.path.split(path)
53
94
 
54
- m = re.search(r'(\d+)\.(\d+)', path)
55
- if m:
56
- self.questa_major = int(m.group(1))
57
- self.questa_minor = int(m.group(2))
58
- self._VERSION = str(self.questa_major) + '.' + str(self.questa_minor)
59
- else:
60
- self.error("Questa path doesn't specificy version, expecting (d+.d+)")
95
+ # For Questa family, we will get the version from the path.
96
+ # 1. (if present): {path}/../docs/rlsnotes/RELEASE_NOTES.txt, where first line
97
+ # shows the full version.
98
+ # 2. else, use the path
99
+ self._try_set_version_from_release_notes()
100
+
101
+ if not self._VERSION:
102
+ self._try_set_version_from_path()
103
+
61
104
  return self._VERSION
62
105
 
63
- def set_tool_defines(self):
64
- # Will only be called from an object which also inherits from CommandDesign,
65
- # i.e. has self.defines
66
- self.defines['OC_TOOL_QUESTA'] = None
67
- self.defines[f'OC_TOOL_QUESTA_{self.questa_major:d}_{self.questa_minor:d}'] = None
106
+ def set_tool_defines(self) -> None:
107
+ '''Override from class Tool, which handles picking up config['tools'][self._TOOL]
108
+
109
+ defines. We also set the OC_TOOL_QUESTA_[major]_[minor] if those exist
110
+ '''
111
+ super().set_tool_defines() # Tool, set from config.
112
+ if self.questa_major and self.questa_minor:
113
+ self.defines[f'OC_TOOL_QUESTA_{self.questa_major:d}_{self.questa_minor:d}'] = None
68
114
 
69
115
 
70
116
 
@@ -209,21 +255,24 @@ class CommonSimQuesta(CommandSim, ToolQuesta):
209
255
  for value in self.incdirs:
210
256
  vlog_dot_f_lines += [ f"+incdir+{value}" ]
211
257
 
212
- for k,v in self.defines.items():
213
- if v is None:
214
- vlog_dot_f_lines += [ f'+define+{k}' ]
215
- else:
216
-
217
- # if the value v is a double-quoted string, such as v='"hi"', the
218
- # entire +define+NAME="hi" needs to wrapped in double quotes with the
219
- # value v double-quotes escaped: "+define+NAME=\"hi\""
220
- if isinstance(v, str) and v.startswith('"') and v.endswith('"'):
221
- str_v = v.replace('"', '\\"')
222
- vlog_dot_f_lines += [ f'"+define+{k}={str_v}"' ]
258
+ if self.args['ext-defines-sv-fname']:
259
+ self.create_ext_defines_sv()
260
+ else:
261
+ for k,v in self.defines.items():
262
+ if v is None:
263
+ vlog_dot_f_lines += [ f'+define+{k}' ]
223
264
  else:
224
- # Generally we should only support int and str python types passed as
225
- # +define+{k}={v}, but also for SystemVerilog plusargs
226
- vlog_dot_f_lines += [ f'+define+{k}={sanitize_defines_for_sh(v)}' ]
265
+
266
+ # if the value v is a double-quoted string, such as v='"hi"', the
267
+ # entire +define+NAME="hi" needs to wrapped in double quotes with the
268
+ # value v double-quotes escaped: "+define+NAME=\"hi\""
269
+ if isinstance(v, str) and v.startswith('"') and v.endswith('"'):
270
+ str_v = v.replace('"', '\\"')
271
+ vlog_dot_f_lines += [ f'"+define+{k}={str_v}"' ]
272
+ else:
273
+ # Generally we should only support int and str python types passed as
274
+ # +define+{k}={v}, but also for SystemVerilog plusargs
275
+ vlog_dot_f_lines += [ f'+define+{k}={sanitize_defines_for_sh(v)}' ]
227
276
 
228
277
 
229
278
  vlog_dot_f_lines += self.args['compile-args']
@@ -256,10 +305,17 @@ class CommonSimQuesta(CommandSim, ToolQuesta):
256
305
  # work around this by setting tcl varaibles for each parameter.
257
306
  if self.parameters:
258
307
  if not self.use_vopt:
259
- voptargs_str += ' ' + ' '.join(self.process_parameters_get_list(arg_prefix='-G'))
308
+ voptargs_str += ' ' + ' '.join(
309
+ self.process_parameters_get_list(
310
+ arg_prefix='-G', hier_delimiter='/', top_hier_str=f'/{self.args["top"]}/'
311
+ )
312
+ )
260
313
  else:
261
314
  for k,v in self.parameters.items():
262
- s = sim.parameters_dict_get_command_list(params={k: v}, arg_prefix='')[0]
315
+ s = sim.parameters_dict_get_command_list(
316
+ params={k: v}, arg_prefix='', hier_delimiter='/',
317
+ top_hier_str=f'/{self.args["top"]}/'
318
+ )[0]
263
319
  # At this point, s should be a str in form {k}={v}
264
320
  if not s or '=' not in s:
265
321
  continue
@@ -269,9 +325,12 @@ class CommonSimQuesta(CommandSim, ToolQuesta):
269
325
  # we'll do:
270
326
  # set PARAMETERS(MyParam) "hi bye"
271
327
  # vopt -GMyParam=$PARAMETERS(MyParam)
272
- s = s.replace(f'{k}=', f'set PARAMETERS({k}) ')
328
+ parts = s.split('=')
329
+ _name = parts[0]
330
+ _value = '='.join(parts[1:])
331
+ s = f'set PARAMETERS({_name}) {_value}'
273
332
  vopt_do_lines.append(s)
274
- voptargs_str += f' -G{k}=$PARAMETERS({k}) '
333
+ voptargs_str += f' -G{_name}=$PARAMETERS({_name}) '
275
334
  else:
276
335
  voptargs_str += f' -G{s} '
277
336
 
@@ -478,3 +537,9 @@ class CommonFListQuesta(CommandFList, ToolQuesta):
478
537
  def __init__(self, config: dict):
479
538
  CommandFList.__init__(self, config=config)
480
539
  ToolQuesta.__init__(self, config=self.config)
540
+ self.args.update({
541
+ # an Flist, like vlog.f, cannot support parameters or sim-plusargs, so warn
542
+ # if they are present b/c they will not be emitted.
543
+ 'emit-parameter': False,
544
+ 'emit-plusargs': False,
545
+ })
@@ -41,20 +41,6 @@ class CommandSimQuestaFe(CommonSimQuesta):
41
41
  })
42
42
 
43
43
 
44
- def set_tool_defines(self):
45
- '''Override from questa.ToolQuesta'''
46
- # Update any defines from config.tools.questa_fse:
47
- self.defines.update(
48
- self.tool_config.get(
49
- 'defines',
50
- # defaults, if not set:
51
- {
52
- 'OC_TOOL_QUESTA_FE': 1
53
- }
54
- )
55
- )
56
-
57
-
58
44
  class CommandElabQuestaFe(CommandSimQuestaFe):
59
45
  '''CommandElabQuesta is a command handler for: eda elab --tool=questa_fe'''
60
46
 
@@ -38,20 +38,6 @@ class CommandSimQuestaFse(CommonSimQuesta):
38
38
  })
39
39
 
40
40
 
41
- def set_tool_defines(self):
42
- '''Override from questa.ToolQuesta'''
43
- # Update any defines from config.tools.questa_fse:
44
- self.defines.update(
45
- self.tool_config.get(
46
- 'defines',
47
- # defaults, if not set:
48
- {
49
- 'OC_TOOL_QUESTA_FSE': 1
50
- }
51
- )
52
- )
53
-
54
-
55
41
  class CommandElabQuestaFse(CommandSimQuestaFse):
56
42
  '''CommandElabQuestaFse is a command handler for: eda elab --tool=questa_fse'''
57
43
 
opencos/tools/riviera.py CHANGED
@@ -35,6 +35,7 @@ class ToolRiviera(ToolQuesta):
35
35
  self.sim_exe = path
36
36
  self.sim_exe_base_path, _ = os.path.split(path)
37
37
 
38
+ # vsim -version is very fast and does not require a license:
38
39
  version_ret = subprocess.run(
39
40
  [self.sim_exe, '-version'],
40
41
  capture_output=True,
@@ -56,7 +57,7 @@ class ToolRiviera(ToolQuesta):
56
57
  # Aldec, Inc. Riviera-PRO version 2025.04.139.9738 built for Linux64 on May 30, 2025
57
58
  left, right = stdout.split('version')
58
59
  if 'Riviera' not in left:
59
- self.error(f'{stdout}: does not show Riviera')
60
+ util.warning(f'riviera version parsing: {stdout}: does not show "Riviera"')
60
61
  self._VERSION = right.split()[0]
61
62
  return self._VERSION
62
63
 
@@ -81,6 +82,7 @@ class CommandSimRiviera(CommonSimQuesta, ToolRiviera):
81
82
  'waves-fst': True,
82
83
  'waves-vcd': False,
83
84
  'coverage-tcl': '',
85
+ 'ext-defines-sv-fname': '_ext_defines.sv',
84
86
  })
85
87
  self.args_help.update({
86
88
  'waves-fst': (
@@ -98,6 +100,12 @@ class CommandSimRiviera(CommonSimQuesta, ToolRiviera):
98
100
  'Attempts to support UVM. Adds to vlog: -l uvm +incdir+PATH for the PATH to'
99
101
  ' uvm_macros.svh for the installed version of Riviera used.'
100
102
  ),
103
+ 'license-queue': (
104
+ 'Set to enable env vars (if unset) LICENSE_QUEUE=1, ALDEC_LICENSE_QUEUE=1,'
105
+ ' FLEXLM_TIMEOUT=3000000 (3us), which should set Riviera to wait for licenses'
106
+ ' instead of immediately exiting with error. You may wish to also set your own'
107
+ ' env vars for ALDEC_LICENSE_FILE instead of LM_LICENSE_FILE.'
108
+ ),
101
109
  })
102
110
 
103
111
  if self.uvm_versions:
@@ -108,15 +116,6 @@ class CommandSimRiviera(CommonSimQuesta, ToolRiviera):
108
116
  'uvm-version': { 'choices': list(self.uvm_versions) }
109
117
  })
110
118
 
111
- def set_tool_defines(self):
112
- # Update any defines from config.tools.modelsim_ase:
113
- self.defines.update(
114
- self.tool_config.get(
115
- 'defines',
116
- # defaults, if not set:
117
- {'OC_TOOL_RIVIERA': 1}
118
- )
119
- )
120
119
 
121
120
  # Note: many of these we follow the same flow as CommandSimModelsimAse:
122
121
  # do_it, prepare_compile, compile, elaborate, simulate
@@ -194,20 +193,27 @@ class CommandSimRiviera(CommonSimQuesta, ToolRiviera):
194
193
  for value in self.incdirs:
195
194
  vlog_dot_f_lines += [ f"+incdir+{value}" ]
196
195
 
197
- for k,v in self.defines.items():
198
- if v is None:
199
- vlog_dot_f_lines += [ f'+define+{k}' ]
200
- else:
201
- # if the value v is a double-quoted string, such as v='"hi"', the
202
- # entire +define+NAME="hi" needs to wrapped in double quotes with the
203
- # value v double-quotes escaped: "+define+NAME=\"hi\""
204
- if isinstance(v, str) and v.startswith('"') and v.endswith('"'):
205
- str_v = v.replace('"', '\\"')
206
- vlog_dot_f_lines += [ f'"+define+{k}={str_v}"' ]
196
+ # For external defines, we will create a file in the work-dir named
197
+ # _ext_defines.sv, it will be the first file in the file list, and it
198
+ # will be valid Verilog/SV, not a list of +define+Name[=Value]
199
+ if self.args['ext-defines-sv-fname']:
200
+ self.create_ext_defines_sv()
201
+ else:
202
+ for k,v in self.defines.items():
203
+ if v is None:
204
+ vlog_dot_f_lines += [ f'+define+{k}' ]
207
205
  else:
208
- # Generally we should only support int and str python types passed as
209
- # +define+{k}={v}, but also for SystemVerilog plusargs
210
- vlog_dot_f_lines += [ f'+define+{k}={sanitize_defines_for_sh(v)}' ]
206
+ # if the value v is a double-quoted string, such as v='"hi"', the
207
+ # entire +define+NAME="hi" needs to wrapped in double quotes with the
208
+ # value v double-quotes escaped: "+define+NAME=\"hi\""
209
+ if isinstance(v, str) and v.startswith('"') and v.endswith('"'):
210
+ str_v = v.replace('"', '\\"')
211
+ vlog_dot_f_lines += [ f'"+define+{k}={str_v}"' ]
212
+ else:
213
+ # Generally we should only support int and str python types passed as
214
+ # +define+{k}={v}, but also for SystemVerilog plusargs
215
+ vlog_dot_f_lines += [ f'+define+{k}={sanitize_defines_for_sh(v)}' ]
216
+
211
217
 
212
218
 
213
219
  vlog_dot_f_lines += self.args['compile-args']
@@ -260,9 +266,17 @@ class CommandSimRiviera(CommonSimQuesta, ToolRiviera):
260
266
  if all(x not in voptargs_str for x in ('+access +r', '+access +w+r')):
261
267
  voptargs_str += ' +access +r'
262
268
 
263
- # parameters
269
+ # parameters, for Riviera we need to use the leading forward slash option
270
+ # aka -G/Name=Value, if our parameter name doesn't already have path information.
271
+ # If you do -GName=Value, all parameters in the hierachy with Name will be set,
272
+ # so to only do top level parameters, if hierarchy isn't mentioned in the Name,
273
+ # would need to do -G/{self.args['top']}/Name=Value.
264
274
  if self.parameters:
265
- voptargs_str += ' ' + ' '.join(self.process_parameters_get_list(arg_prefix='-G'))
275
+ voptargs_str += ' ' + ' '.join(
276
+ self.process_parameters_get_list(
277
+ arg_prefix='-G', hier_delimiter='/', top_hier_str=f'/{self.args["top"]}/'
278
+ )
279
+ )
266
280
 
267
281
  vsim_libs = ' '.join([f'-l {x}' for x in self.args['sim-library']])
268
282
 
@@ -364,6 +378,23 @@ class CommandSimRiviera(CommonSimQuesta, ToolRiviera):
364
378
  f.writelines(line + "\n" for line in vsim_vlogonly_dot_do_lines)
365
379
 
366
380
 
381
+ def handle_arg_license_queue(self) -> None:
382
+ '''Handles self.args['license-queue'] (bool) to set env vars
383
+
384
+ Overriden from opencos.command.sim::CommandSim.
385
+ '''
386
+ if not self.args['license-queue']:
387
+ return
388
+
389
+ if 'LICENSE_QUEUE' not in os.environ:
390
+ os.environ['LICENSE_QUEUE'] = '1'
391
+ if 'ALDEC_LICENSE_QUEUE' not in os.environ:
392
+ os.environ['ALDEC_LICENSE_QUEUE'] = '1'
393
+
394
+ # Anecdotal evidence, set this which may help
395
+ if 'FLEXLM_TIMEOUT' not in os.environ:
396
+ os.environ['FLEXLM_TIMEOUT'] = '3000000' # 3e6 us = 3 sec
397
+
367
398
 
368
399
  def _get_vsim_suppress_list_str(self) -> str:
369
400
  vsim_suppress_list = []
opencos/tools/slang.py CHANGED
@@ -52,18 +52,18 @@ class ToolSlang(Tool):
52
52
  util.debug(f'{path=} {version_ret=}')
53
53
  words = stdout.split() # slang version 8.0.6+b4a74b00
54
54
  if len(words) < 3:
55
- self.error(f'{self.slang_exe} --version: returned unexpected string {version_ret=}')
55
+ util.warning(f'{self.slang_exe} --version: returned unexpected string {version_ret=}')
56
56
  version = words[2]
57
57
  left, _ = version.split('+')
58
58
  ver_list = left.split('.')
59
59
  if len(ver_list) != 3:
60
- self.error(f'{self.slang_exe} --version: returned unexpected string',
61
- f'{version_ret=} {version=}')
60
+ util.warning(f'{self.slang_exe} --version: returned unexpected string',
61
+ f'{version_ret=} {version=}')
62
62
  self._VERSION = left
63
63
  return self._VERSION
64
64
 
65
65
  def set_tool_defines(self):
66
- self.defines['OC_TOOL_SLANG'] = None # add define
66
+ super().set_tool_defines()
67
67
  if 'SYNTHESIS' not in self.defines:
68
68
  self.defines['SIMULATION'] = None # add define
69
69
  # Expected to manually add SYNTHESIS command line or target, otherwise.
@@ -139,14 +139,17 @@ class CommandElabSlang(CommandElab, ToolSlang):
139
139
  command_list += [ '--include-directory', value ]
140
140
 
141
141
  # defines:
142
- for k,v in self.defines.items():
143
- command_list.append( '--define-macro' )
144
- if v is None:
145
- command_list.append( k )
146
- else:
147
- # Generally we should only support int and str python types passed as
148
- # --define-macro {k}={v}
149
- command_list.append( f'{k}={sanitize_defines_for_sh(v)}' )
142
+ if self.args['ext-defines-sv-fname']:
143
+ self.create_ext_defines_sv()
144
+ else:
145
+ for k,v in self.defines.items():
146
+ command_list.append( '--define-macro' )
147
+ if v is None:
148
+ command_list.append( k )
149
+ else:
150
+ # Generally we should only support int and str python types passed as
151
+ # --define-macro {k}={v}
152
+ command_list.append( f'{k}={sanitize_defines_for_sh(v)}' )
150
153
 
151
154
  # parameters
152
155
  command_list.extend(
@@ -22,12 +22,6 @@ class ToolSlangYosys(ToolYosys):
22
22
  'https://github.com/MikePopoloski/slang',
23
23
  ]
24
24
 
25
- def set_tool_defines(self):
26
- super().set_tool_defines()
27
- self.defines.update({
28
- 'OC_TOOL_SLANG': None,
29
- })
30
-
31
25
 
32
26
  class CommandSynthSlangYosys(CommonSynthYosys, ToolSlangYosys):
33
27
  '''CommandSynthSlangYosys is a command handler for: eda synth --tool=slang_yosys'''
opencos/tools/surelog.py CHANGED
@@ -38,17 +38,17 @@ class ToolSurelog(Tool):
38
38
  util.debug(f'{path=} {version_ret=}')
39
39
  words = stdout.split() # VERSION: 1.84 (first line)
40
40
  if len(words) < 2:
41
- self.error(f'{self.surelog_exe} --version: returned unexpected string {version_ret=}')
41
+ util.warning(f'{self.surelog_exe} --version: returned unexpected string {version_ret=}')
42
42
  version = words[1]
43
43
  ver_list = version.split('.')
44
44
  if len(ver_list) < 2:
45
- self.error(f'{self.surelog_exe} --version: returned unexpected string',
46
- f'{version_ret=} {version=}')
45
+ util.warning(f'{self.surelog_exe} --version: returned unexpected string',
46
+ f'{version_ret=} {version=}')
47
47
  self._VERSION = version
48
48
  return self._VERSION
49
49
 
50
50
  def set_tool_defines(self):
51
- self.defines['OC_TOOL_SURELOG'] = None # add define
51
+ super().set_tool_defines()
52
52
  if 'SYNTHESIS' not in self.defines:
53
53
  self.defines['SIMULATION'] = None # add define
54
54
  # Expected to manually add SYNTHESIS command line or target, otherwise.
@@ -116,13 +116,16 @@ class CommandElabSurelog(CommandElab, ToolSurelog):
116
116
  )
117
117
 
118
118
  # defines:
119
- for k,v in self.defines.items():
120
- if v is None:
121
- command_list.append( f'+define+{k}' )
122
- else:
123
- # Generally we should only support int and str python types passed as
124
- # +define+{k}={v}
125
- command_list.append( f'+define+{k}={sanitize_defines_for_sh(v)}' )
119
+ if self.args['ext-defines-sv-fname']:
120
+ self.create_ext_defines_sv()
121
+ else:
122
+ for k,v in self.defines.items():
123
+ if v is None:
124
+ command_list.append( f'+define+{k}' )
125
+ else:
126
+ # Generally we should only support int and str python types passed as
127
+ # +define+{k}={v}
128
+ command_list.append( f'+define+{k}={sanitize_defines_for_sh(v)}' )
126
129
 
127
130
  # Because many elab target-name won't match the --top needed for
128
131
  # slang, we'll leave this to arg --surelog-top:
@@ -21,17 +21,11 @@ class ToolTabbyCadYosys(ToolYosys):
21
21
  _TOOL = 'tabbycad_yosys'
22
22
  _URL = 'https://www.yosyshq.com/tabby-cad-datasheet'
23
23
 
24
- def set_tool_defines(self):
25
- super().set_tool_defines()
26
- self.defines.update({
27
- 'OC_TOOL_TABBYCAD': None,
28
- })
29
-
30
24
 
31
25
  class CommandSynthTabbyCadYosys(CommonSynthYosys, ToolTabbyCadYosys):
32
26
  '''Command handler for: eda synth --tool tabbycad_yosys.'''
33
27
 
34
- def __init__(self, config:dict):
28
+ def __init__(self, config: dict):
35
29
  CommonSynthYosys.__init__(self, config)
36
30
  ToolTabbyCadYosys.__init__(self, config=self.config)
37
31
 
@@ -56,18 +56,17 @@ class ToolVerilator(Tool):
56
56
  util.debug(f'{path=} {version_ret=}')
57
57
  words = stdout.split() # 'Verilator 5.027 devel rev v5.026-92-g403a197e2
58
58
  if len(words) < 1:
59
- self.error(f'{self.verilator_exe} --version: returned unexpected string {version_ret=}')
59
+ util.warning(
60
+ f'{self.verilator_exe} --version: returned unexpected string {version_ret=}'
61
+ )
60
62
  version = words[1]
61
63
  ver_list = version.split('.')
62
64
  if len(ver_list) != 2:
63
- self.error(f'{self.verilator_exe} --version: returned unexpected',
64
- f'string {version_ret=} {version=}')
65
+ util.warning(f'{self.verilator_exe} --version: returned unexpected',
66
+ f'string {version_ret=} {version=}')
65
67
  self._VERSION = version
66
68
  return self._VERSION
67
69
 
68
- def set_tool_defines(self):
69
- # We don't need to define VERILATOR, the verilated exe does that itself.
70
- pass
71
70
 
72
71
  class VerilatorSim(CommandSim, ToolVerilator):
73
72
  '''VerilatorSim is a command handler for: eda sim --tool=verilator'''
@@ -220,7 +219,9 @@ class VerilatorSim(CommandSim, ToolVerilator):
220
219
  check_logs=False
221
220
  )
222
221
 
223
- def get_compile_command_lists(self, **kwargs) -> list:
222
+ def get_compile_command_lists( # pylint: disable=too-many-branches
223
+ self, **kwargs
224
+ ) -> list:
224
225
 
225
226
  # Support for lint_only (bool) in kwargs:
226
227
  lint_only = kwargs.get('lint_only', False)
@@ -266,13 +267,16 @@ class VerilatorSim(CommandSim, ToolVerilator):
266
267
  verilate_command_list += [ f"+incdir+{value}" ]
267
268
 
268
269
  # defines
269
- for k,v in self.defines.items():
270
- if v is None:
271
- verilate_command_list += [ f'+define+{k}' ]
272
- else:
273
- # Generally we should only support int and str python types passed as
274
- # +define+{k}={v}, but also for SystemVerilog plusargs
275
- verilate_command_list += [ f'+define+{k}={sanitize_defines_for_sh(v)}' ]
270
+ if self.args['ext-defines-sv-fname']:
271
+ self.create_ext_defines_sv()
272
+ else:
273
+ for k,v in self.defines.items():
274
+ if v is None:
275
+ verilate_command_list += [ f'+define+{k}' ]
276
+ else:
277
+ # Generally we should only support int and str python types passed as
278
+ # +define+{k}={v}, but also for SystemVerilog plusargs
279
+ verilate_command_list += [ f'+define+{k}={sanitize_defines_for_sh(v)}' ]
276
280
 
277
281
  # parameters
278
282
  verilate_command_list.extend(