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.
- opencos/commands/flist.py +222 -39
- opencos/commands/multi.py +5 -3
- opencos/commands/sim.py +121 -7
- opencos/commands/sweep.py +1 -1
- opencos/commands/upload.py +4 -4
- opencos/commands/waves.py +44 -0
- opencos/deps/deps_file.py +4 -1
- opencos/deps_schema.py +2 -2
- opencos/eda.py +284 -175
- opencos/eda_base.py +54 -22
- opencos/eda_config.py +51 -24
- opencos/eda_config_defaults.yml +326 -195
- opencos/eda_config_reduced.yml +19 -39
- opencos/eda_tool_helper.py +193 -24
- opencos/tools/cocotb.py +6 -29
- opencos/tools/invio.py +0 -6
- opencos/tools/iverilog.py +16 -16
- opencos/tools/modelsim_ase.py +1 -13
- opencos/tools/quartus.py +81 -24
- opencos/tools/questa.py +0 -14
- opencos/tools/questa_common.py +95 -30
- opencos/tools/questa_fe.py +0 -14
- opencos/tools/questa_fse.py +0 -14
- opencos/tools/riviera.py +56 -25
- opencos/tools/slang.py +15 -12
- opencos/tools/slang_yosys.py +0 -6
- opencos/tools/surelog.py +14 -11
- opencos/tools/tabbycad_yosys.py +1 -7
- opencos/tools/verilator.py +18 -14
- opencos/tools/vivado.py +57 -22
- opencos/tools/yosys.py +2 -4
- opencos/util.py +14 -5
- opencos/utils/str_helpers.py +42 -1
- {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/METADATA +1 -2
- {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/RECORD +40 -41
- opencos/eda_config_max_verilator_waivers.yml +0 -39
- {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/WHEEL +0 -0
- {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/entry_points.txt +0 -0
- {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/licenses/LICENSE +0 -0
- {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/licenses/LICENSE.spdx +0 -0
- {opencos_eda-0.3.11.dist-info → opencos_eda-0.3.13.dist-info}/top_level.txt +0 -0
opencos/tools/questa_common.py
CHANGED
|
@@ -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
|
-
|
|
55
|
-
if
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
|
|
225
|
-
#
|
|
226
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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{
|
|
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
|
+
})
|
opencos/tools/questa_fe.py
CHANGED
|
@@ -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
|
|
opencos/tools/questa_fse.py
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if
|
|
205
|
-
|
|
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
|
-
#
|
|
209
|
-
# +define+
|
|
210
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
61
|
-
|
|
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
|
-
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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(
|
opencos/tools/slang_yosys.py
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
46
|
-
|
|
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
|
-
|
|
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
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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:
|
opencos/tools/tabbycad_yosys.py
CHANGED
|
@@ -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
|
|
opencos/tools/verilator.py
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
64
|
-
|
|
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(
|
|
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
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
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(
|