opencos-eda 0.2.56__tar.gz → 0.2.57__tar.gz
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_eda-0.2.56/opencos_eda.egg-info → opencos_eda-0.2.57}/PKG-INFO +1 -1
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/lec.py +4 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/multi.py +4 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/eda.py +13 -1
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/eda_config.py +35 -1
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/eda_config_defaults.yml +1 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/export_helper.py +5 -1
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/helpers.py +9 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/cocotb.py +25 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/modelsim_ase.py +49 -8
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/slang_yosys.py +4 -1
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/yosys.py +50 -20
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/utils/vsim_helper.py +1 -2
- {opencos_eda-0.2.56 → opencos_eda-0.2.57/opencos_eda.egg-info}/PKG-INFO +1 -1
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/pyproject.toml +1 -1
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/LICENSE +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/LICENSE.spdx +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/README.md +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/__init__.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/_version.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/_waves_pkg.sv +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/__init__.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/build.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/deps_help.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/elab.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/export.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/flist.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/lint.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/open.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/proj.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/shell.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/sim.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/sweep.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/synth.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/targets.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/upload.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/commands/waves.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/deps/__init__.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/deps/defaults.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/deps/deps_commands.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/deps/deps_file.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/deps/deps_processor.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/deps_schema.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/eda_base.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/eda_config_max_verilator_waivers.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/eda_config_reduced.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/eda_deps_bash_completion.bash +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/eda_deps_sanitize.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/eda_extract_targets.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/eda_tool_helper.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/export_json_convert.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/files.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/hw/__init__.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/hw/oc_cli.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/hw/pcie.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/names.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/peakrdl_cleanup.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/seed.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/__init__.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/custom_config.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/deps_files/command_order/DEPS.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/deps_files/error_msgs/DEPS.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/deps_files/iverilog_test/DEPS.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/deps_files/no_deps_here/DEPS.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/deps_files/non_sv_reqs/DEPS.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/deps_files/tags_with_tools/DEPS.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/deps_files/test_err_fatal/DEPS.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/test_build.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/test_deps_helpers.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/test_deps_schema.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/test_eda.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/test_eda_elab.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/test_eda_synth.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/test_oc_cli.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tests/test_tools.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/__init__.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/invio.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/invio_helpers.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/invio_yosys.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/iverilog.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/quartus.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/questa.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/questa_fse.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/riviera.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/slang.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/surelog.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/tabbycad_yosys.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/verilator.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/tools/vivado.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/util.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/utils/__init__.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/utils/markup_helpers.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/utils/status_constants.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/utils/str_helpers.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/utils/subprocess_helpers.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos/utils/vscode_helper.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos_eda.egg-info/SOURCES.txt +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos_eda.egg-info/dependency_links.txt +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos_eda.egg-info/entry_points.txt +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos_eda.egg-info/requires.txt +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/opencos_eda.egg-info/top_level.txt +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.2.57}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opencos-eda
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.57
|
|
4
4
|
Summary: A simple Python package for wrapping RTL simuliatons and synthesis
|
|
5
5
|
Author-email: Simon Sabato <simon@cognichip.ai>, Drew Ranck <drew@cognichip.ai>
|
|
6
6
|
Project-URL: Homepage, https://github.com/cognichip/opencos
|
|
@@ -27,6 +27,7 @@ class CommandLec(CommandDesign):
|
|
|
27
27
|
self.args.update({
|
|
28
28
|
'designs': [],
|
|
29
29
|
'synth': True,
|
|
30
|
+
'flatten-all': True,
|
|
30
31
|
})
|
|
31
32
|
self.args_help.update({
|
|
32
33
|
'designs': (
|
|
@@ -34,6 +35,9 @@ class CommandLec(CommandDesign):
|
|
|
34
35
|
' use this arg twice'
|
|
35
36
|
),
|
|
36
37
|
'synth': 'run synthesis on the two designs prior to running LEC',
|
|
38
|
+
'flatten-all': (
|
|
39
|
+
'arg passed to "synth" if run with --synth, to disable use --no-flatten-all'
|
|
40
|
+
),
|
|
37
41
|
})
|
|
38
42
|
|
|
39
43
|
self.synth_design_verilog_fpaths = ['', '']
|
|
@@ -327,6 +327,10 @@ class CommandMulti(CommandParallel):
|
|
|
327
327
|
|
|
328
328
|
if parsed.fail_if_no_targets and len(self.targets) == 0:
|
|
329
329
|
self.error(f'Multi: --fail-if-no-targets set, and {self.targets=}')
|
|
330
|
+
if not all_multi_tools:
|
|
331
|
+
possible_tools = self.all_handler_commands.get(command, [])
|
|
332
|
+
self.error(f'Multi: no tools to run for {command=}, available tools: {possible_tools}')
|
|
333
|
+
|
|
330
334
|
util.info("Multi: About to run: ", end="")
|
|
331
335
|
|
|
332
336
|
def get_pretty_targets_tuple_as_list(l:list):
|
|
@@ -49,6 +49,9 @@ def init_config(
|
|
|
49
49
|
|
|
50
50
|
# For key DEFAULT_HANDLERS, we'll update config['command_handler'] with
|
|
51
51
|
# the actual class using importlib (via opencos.util)
|
|
52
|
+
|
|
53
|
+
eda_config.tool_try_add_to_path(tool)
|
|
54
|
+
|
|
52
55
|
config['command_handler'] = {}
|
|
53
56
|
for _cmd, str_class in config['DEFAULT_HANDLERS'].items():
|
|
54
57
|
cls = util.import_class_from_string(str_class)
|
|
@@ -329,7 +332,7 @@ def tool_setup(tool: str, config: dict, quiet: bool = False, auto_setup: bool =
|
|
|
329
332
|
config['tools_loaded'].add(tool)
|
|
330
333
|
|
|
331
334
|
|
|
332
|
-
def process_tokens( # pylint: disable=too-many-branches,too-many-statements,too-many-locals
|
|
335
|
+
def process_tokens( # pylint: disable=too-many-branches,too-many-statements,too-many-locals,too-many-return-statements
|
|
333
336
|
tokens: list, original_args: list, config: dict, is_interactive=False
|
|
334
337
|
) -> int:
|
|
335
338
|
'''Returns bash/sh style return code int (0 pass, non-zero fail).
|
|
@@ -416,6 +419,15 @@ def process_tokens( # pylint: disable=too-many-branches,too-many-statements,too-
|
|
|
416
419
|
return 2
|
|
417
420
|
|
|
418
421
|
sco = config['command_handler'][command](config=config) # sub command object
|
|
422
|
+
if not parsed.tool:
|
|
423
|
+
# then what was the auto selected tool?
|
|
424
|
+
sco_tool = getattr(sco, '_TOOL', '')
|
|
425
|
+
if sco_tool in config['auto_tools_order'][0] and \
|
|
426
|
+
config['auto_tools_order'][0][sco_tool].get('disable-auto', False):
|
|
427
|
+
util.error(f'Cannot use tool={sco_tool} without arg --tool, it cannot be selected',
|
|
428
|
+
'automatically')
|
|
429
|
+
return status_constants.EDA_COMMAND_OR_ARGS_ERROR
|
|
430
|
+
|
|
419
431
|
util.debug(f'{command=}')
|
|
420
432
|
util.debug(f'{sco.config=}')
|
|
421
433
|
util.debug(f'{type(sco)=}')
|
|
@@ -47,7 +47,7 @@ class Defaults:
|
|
|
47
47
|
'exe', 'handlers',
|
|
48
48
|
'requires_env', 'requires_py', 'requires_cmd', 'requires_in_exe_path',
|
|
49
49
|
'requires_vsim_helper', 'requires_vscode_extension',
|
|
50
|
-
'disable-tools-multi',
|
|
50
|
+
'disable-tools-multi', 'disable-auto',
|
|
51
51
|
])
|
|
52
52
|
supported_config_tool_keys = set([
|
|
53
53
|
'defines',
|
|
@@ -158,6 +158,9 @@ def update_config_auto_tool_order_for_tool(tool: str, config: dict) -> str:
|
|
|
158
158
|
|
|
159
159
|
user_exe = shutil.which(user_exe)
|
|
160
160
|
|
|
161
|
+
# try adding to $PATH if in form --tool=/path/to/exe
|
|
162
|
+
tool_try_add_to_path(tool)
|
|
163
|
+
|
|
161
164
|
if tool not in config['auto_tools_order'][0]:
|
|
162
165
|
return tool
|
|
163
166
|
if not user_exe:
|
|
@@ -322,3 +325,34 @@ def write_eda_config_and_args(
|
|
|
322
325
|
data['config'][k] = str(v)
|
|
323
326
|
|
|
324
327
|
yaml_safe_writer(data=data, filepath=fullpath)
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def tool_try_add_to_path(tool: str) -> None:
|
|
331
|
+
'''Since we support --tool=<name>=/path/to/bin/exe, attempt to prepend $PATH
|
|
332
|
+
|
|
333
|
+
with this information for this tool (which will nicely affect all subprocesses,
|
|
334
|
+
but not wreck our original shell).'''
|
|
335
|
+
|
|
336
|
+
if not tool or '=' not in tool:
|
|
337
|
+
return
|
|
338
|
+
|
|
339
|
+
name, exe = tool.split('=')
|
|
340
|
+
if os.path.isdir(name):
|
|
341
|
+
# Someone passes us --tool=<name>=/path/to/bin/ (did not have exe)
|
|
342
|
+
path = name
|
|
343
|
+
else:
|
|
344
|
+
# Someone passes us --tool=<name>=/path/to/bin/exe, remove the exe.
|
|
345
|
+
path, _ = os.path.split(exe)
|
|
346
|
+
if not path:
|
|
347
|
+
return
|
|
348
|
+
|
|
349
|
+
path = os.path.abspath(path)
|
|
350
|
+
if os.path.isdir(path):
|
|
351
|
+
paths = os.environ['PATH'].split(':')
|
|
352
|
+
if path not in paths:
|
|
353
|
+
os.environ['PATH'] = path + ':' + os.environ['PATH']
|
|
354
|
+
util.info(f'--tool={tool} has path information, prepending PATH with: {path}')
|
|
355
|
+
else:
|
|
356
|
+
util.info(f'--tool={tool} has path information, but {path} already in $PATH')
|
|
357
|
+
if exe and os.path.isfile(exe):
|
|
358
|
+
util.info(f'--tool={tool} has path information, using exe {shutil.which(exe)}')
|
|
@@ -516,6 +516,7 @@ auto_tools_order:
|
|
|
516
516
|
sim: opencos.tools.iverilog.CommandSimIverilog
|
|
517
517
|
|
|
518
518
|
cocotb:
|
|
519
|
+
disable-auto: True # do not allow this to run `eda sim` with --tool not set
|
|
519
520
|
exe: python
|
|
520
521
|
requires_cmd:
|
|
521
522
|
- python -c "import cocotb; print(cocotb.__version__)"
|
|
@@ -286,7 +286,11 @@ def get_list_sv_included_files(
|
|
|
286
286
|
# If we have more than N levels of `include hunting, then rethink this.
|
|
287
287
|
# For example, some codebases would do their file dependencies as `include
|
|
288
288
|
# as part of their header guards, which could be ~100 levels of nesting.
|
|
289
|
-
|
|
289
|
+
|
|
290
|
+
# make a copy of keys so we don't alter during traversal of the dict:
|
|
291
|
+
fnames = list(sv_included_files_dict.keys())
|
|
292
|
+
for fname in fnames:
|
|
293
|
+
traversed = sv_included_files_dict[fname]
|
|
290
294
|
if not traversed:
|
|
291
295
|
included_files_list = find_sv_included_files_within_file(
|
|
292
296
|
filename=fname,
|
|
@@ -39,6 +39,15 @@ def can_run_eda_command(*commands, config: dict) -> bool:
|
|
|
39
39
|
if handler and getattr(handler, 'CHECK_REQUIRES', []):
|
|
40
40
|
if not all(issubclass(handler, x) for x in getattr(handler, 'CHECK_REQUIRES', [])):
|
|
41
41
|
return False
|
|
42
|
+
|
|
43
|
+
# We cannot run tools that have disable-auto set:
|
|
44
|
+
tool = getattr(handler, '_TOOL', '')
|
|
45
|
+
if handler and tool:
|
|
46
|
+
entry = config['auto_tools_order'][0].get(tool, {})
|
|
47
|
+
if entry and entry.get('disable-auto', False):
|
|
48
|
+
# This tool cannot automatically run our command.
|
|
49
|
+
return False
|
|
50
|
+
|
|
42
51
|
runnable.append(True)
|
|
43
52
|
return runnable and all(runnable)
|
|
44
53
|
|
|
@@ -100,9 +100,34 @@ class CommandSimCocotb(CommandSim, ToolCocotb):
|
|
|
100
100
|
def set_tool_defines(self):
|
|
101
101
|
ToolCocotb.set_tool_defines(self)
|
|
102
102
|
|
|
103
|
+
def help( # pylint: disable=dangerous-default-value
|
|
104
|
+
self, tokens: list = [], no_targets: bool = False
|
|
105
|
+
) -> None:
|
|
106
|
+
'''Override for Command.help(...)'''
|
|
107
|
+
|
|
108
|
+
super().help(tokens=tokens, no_targets=no_targets)
|
|
109
|
+
self._warn_if_simulator_not_present()
|
|
110
|
+
|
|
111
|
+
def _warn_if_simulator_not_present(self) -> None:
|
|
112
|
+
'''Warn if --cocotb-simulator is not set, or if the exe is not in PATH'''
|
|
113
|
+
|
|
114
|
+
simulator = self.args['cocotb-simulator']
|
|
115
|
+
if not simulator:
|
|
116
|
+
util.warning('--cocotb-simulator is not set, a simulation cannot be run with'
|
|
117
|
+
'this arg value')
|
|
118
|
+
return
|
|
119
|
+
exe = shutil.which(simulator)
|
|
120
|
+
if not exe:
|
|
121
|
+
util.warning(f'--cocotb-simulator={simulator}, {simulator} is not present in PATH',
|
|
122
|
+
'a simulation cannot be run with this arg value')
|
|
123
|
+
|
|
124
|
+
|
|
103
125
|
def prepare_compile(self):
|
|
104
126
|
self.set_tool_defines()
|
|
105
127
|
|
|
128
|
+
# Check existence of cocotb-simulator:
|
|
129
|
+
self._warn_if_simulator_not_present()
|
|
130
|
+
|
|
106
131
|
# Fix iverilog -> icarus
|
|
107
132
|
if self.args['cocotb-simulator'] == 'iverilog':
|
|
108
133
|
self.args['cocotb-simulator'] = 'icarus'
|
|
@@ -10,7 +10,7 @@ Note that this is for 32-bit Modelsim Student Edition. Consider using --tool=que
|
|
|
10
10
|
import os
|
|
11
11
|
|
|
12
12
|
from opencos import util
|
|
13
|
-
from opencos.commands import CommandSim
|
|
13
|
+
from opencos.commands import sim, CommandSim
|
|
14
14
|
from opencos.tools.questa import ToolQuesta
|
|
15
15
|
from opencos.utils.str_helpers import sanitize_defines_for_sh
|
|
16
16
|
|
|
@@ -201,6 +201,44 @@ class CommandSimModelsimAse(CommandSim, ToolModelsimAse):
|
|
|
201
201
|
with open(vlog_dot_f_fpath, 'w', encoding='utf-8') as f:
|
|
202
202
|
f.writelines(line + "\n" for line in vlog_dot_f_lines)
|
|
203
203
|
|
|
204
|
+
def vopt_handle_parameters(self) -> (str, list):
|
|
205
|
+
'''Returns str for vopt or voptargs, and list of vopt tcl
|
|
206
|
+
|
|
207
|
+
Note this is used for self.use_vopt = True or False.
|
|
208
|
+
'''
|
|
209
|
+
|
|
210
|
+
voptargs_str = ''
|
|
211
|
+
vopt_do_lines = []
|
|
212
|
+
|
|
213
|
+
# Note that if self.use_vopt=True, we have to do some workarounds for how
|
|
214
|
+
# some questa-like tools behave for: tcl/.do + vopt arg processing
|
|
215
|
+
# This affects string based parameters that have spaces (vopt treats spaces unique args,
|
|
216
|
+
# vsim does not). Since we'd like to keep the vopt/vsim split into separate steps, we can
|
|
217
|
+
# work around this by setting tcl varaibles for each parameter.
|
|
218
|
+
if self.parameters:
|
|
219
|
+
if not self.use_vopt:
|
|
220
|
+
voptargs_str += ' ' + ' '.join(self.process_parameters_get_list(arg_prefix='-G'))
|
|
221
|
+
else:
|
|
222
|
+
for k,v in self.parameters.items():
|
|
223
|
+
s = sim.parameters_dict_get_command_list(params={k: v}, arg_prefix='')[0]
|
|
224
|
+
# At this point, s should be a str in form {k}={v}
|
|
225
|
+
if not s or '=' not in s:
|
|
226
|
+
continue
|
|
227
|
+
if ' ' in s:
|
|
228
|
+
# Instead of:
|
|
229
|
+
# vopt -GMyParam="hi bye"
|
|
230
|
+
# we'll do:
|
|
231
|
+
# set PARAMETERS(MyParam) "hi bye"
|
|
232
|
+
# vopt -GMyParam=$PARAMETERS(MyParam)
|
|
233
|
+
s = s.replace(f'{k}=', f'set PARAMETERS({k}) ')
|
|
234
|
+
vopt_do_lines.append(s)
|
|
235
|
+
voptargs_str += f' -G{k}=$PARAMETERS({k}) '
|
|
236
|
+
else:
|
|
237
|
+
voptargs_str += f' -G{s} '
|
|
238
|
+
|
|
239
|
+
return voptargs_str, vopt_do_lines
|
|
240
|
+
|
|
241
|
+
|
|
204
242
|
def write_vsim_dot_do( # pylint: disable=too-many-locals
|
|
205
243
|
self, dot_do_to_write: list
|
|
206
244
|
) -> None:
|
|
@@ -223,9 +261,13 @@ class CommandSimModelsimAse(CommandSim, ToolModelsimAse):
|
|
|
223
261
|
typ='waveform', description='Modelsim/Questa Waveform WLF (Wave Log Format) file'
|
|
224
262
|
)
|
|
225
263
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
264
|
+
vlog_do_lines = []
|
|
265
|
+
vsim_do_lines = []
|
|
266
|
+
|
|
267
|
+
# parameters, use helper method to get voptargs_str and vopt_do_lines
|
|
268
|
+
more_voptargs_str, vopt_do_lines = self.vopt_handle_parameters()
|
|
269
|
+
voptargs_str += more_voptargs_str
|
|
270
|
+
|
|
229
271
|
|
|
230
272
|
# TODO(drew): support self.args['sim_libary', 'elab-args', sim-args'] (3 lists)
|
|
231
273
|
# to add to vsim_one_liner.
|
|
@@ -251,7 +293,7 @@ class CommandSimModelsimAse(CommandSim, ToolModelsimAse):
|
|
|
251
293
|
|
|
252
294
|
vsim_one_liner = vsim_one_liner.replace('\n', ' ')
|
|
253
295
|
|
|
254
|
-
vlog_do_lines
|
|
296
|
+
vlog_do_lines += [
|
|
255
297
|
"if {[file exists work]} { vdel -all work; }",
|
|
256
298
|
"vlib work;",
|
|
257
299
|
"quietly set qc 30;",
|
|
@@ -263,9 +305,8 @@ class CommandSimModelsimAse(CommandSim, ToolModelsimAse):
|
|
|
263
305
|
"}",
|
|
264
306
|
]
|
|
265
307
|
|
|
266
|
-
vopt_do_lines = []
|
|
267
308
|
if self.use_vopt:
|
|
268
|
-
vopt_do_lines
|
|
309
|
+
vopt_do_lines += [
|
|
269
310
|
"if {[catch { " + vopt_one_liner + " } result] } {",
|
|
270
311
|
" echo \"Caught $result\";",
|
|
271
312
|
" if {[batch_mode]} {",
|
|
@@ -274,7 +315,7 @@ class CommandSimModelsimAse(CommandSim, ToolModelsimAse):
|
|
|
274
315
|
"}",
|
|
275
316
|
]
|
|
276
317
|
|
|
277
|
-
vsim_do_lines
|
|
318
|
+
vsim_do_lines += [
|
|
278
319
|
"if {[catch { " + vsim_one_liner + " } result] } {",
|
|
279
320
|
" echo \"Caught $result\";",
|
|
280
321
|
" if {[batch_mode]} {",
|
|
@@ -118,7 +118,10 @@ class CommandSynthSlangYosys(CommonSynthYosys, ToolSlangYosys):
|
|
|
118
118
|
params=self.parameters, arg_prefix='-G '
|
|
119
119
|
)
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
# In case --top was not set:
|
|
122
|
+
if not any(x.startswith('--top') for x in read_slang_cmd):
|
|
123
|
+
read_slang_cmd.append(f'--top {self.args["top"]}')
|
|
124
|
+
|
|
122
125
|
return ' '.join(read_slang_cmd)
|
|
123
126
|
|
|
124
127
|
|
|
@@ -536,7 +536,6 @@ class CommandLecYosys(CommandLec, ToolYosys):
|
|
|
536
536
|
|
|
537
537
|
self.synth_designs_tops = [None, None]
|
|
538
538
|
self.synth_designs_fpaths = [None, None]
|
|
539
|
-
self.synth_design_top_module_names = [None, None]
|
|
540
539
|
|
|
541
540
|
def get_synth_result_fpath(self, target: str) -> str:
|
|
542
541
|
'''Overridden from CommandLec'''
|
|
@@ -547,7 +546,7 @@ class CommandLecYosys(CommandLec, ToolYosys):
|
|
|
547
546
|
def get_synth_command_list(self, design_num: int) -> list:
|
|
548
547
|
'''Returns one of the synthesis command lists, for design_num=0 or 1'''
|
|
549
548
|
|
|
550
|
-
if not design_num in
|
|
549
|
+
if not design_num in (0, 1):
|
|
551
550
|
self.error(f'{design_num=} we only support LEC on designs 0 and 1')
|
|
552
551
|
|
|
553
552
|
synth_cmd_list = [
|
|
@@ -561,31 +560,43 @@ class CommandLecYosys(CommandLec, ToolYosys):
|
|
|
561
560
|
synth_cmd_list += [
|
|
562
561
|
'--work-dir=' + self.synth_work_dirs[design_num],
|
|
563
562
|
self.args['designs'][design_num],
|
|
564
|
-
f'--rename-module=Design{design_num + 1}'
|
|
563
|
+
f'--rename-module=Design{design_num + 1}',
|
|
565
564
|
]
|
|
566
565
|
|
|
567
|
-
self.
|
|
566
|
+
if self.args['flatten-all']:
|
|
567
|
+
# We have to do this or may get conflicts on black-boxed modules, but can
|
|
568
|
+
# be avoided with --no-flatten-all.
|
|
569
|
+
synth_cmd_list.append(
|
|
570
|
+
'--flatten-all'
|
|
571
|
+
)
|
|
572
|
+
|
|
573
|
+
self.synth_designs_tops[design_num] = f'Design{design_num + 1}'
|
|
568
574
|
|
|
569
575
|
return synth_cmd_list
|
|
570
576
|
|
|
571
577
|
|
|
572
|
-
def get_synth_top_from_output_config(self, design_num: int) -> str:
|
|
573
|
-
'''Returns the top name given the design number
|
|
578
|
+
def get_synth_top_from_output_config(self, design_num: int) -> (str, str):
|
|
579
|
+
'''Returns the (orignal top name, module name) tuple given the design number
|
|
580
|
+
|
|
581
|
+
that we synthesized'''
|
|
574
582
|
|
|
575
583
|
work_dir = self.synth_work_dirs[design_num]
|
|
576
584
|
output_cfg_fpath = os.path.join(work_dir, eda_config.EDA_OUTPUT_CONFIG_FNAME)
|
|
577
585
|
data = yaml_safe_load(output_cfg_fpath)
|
|
578
586
|
top = data.get('args', {}).get('top', '')
|
|
579
|
-
|
|
587
|
+
rename_module = data.get('args', {}).get('rename-module', '')
|
|
588
|
+
if not top and not rename_module:
|
|
580
589
|
self.error(f'"top" not found in synth run from {work_dir=} in',
|
|
581
590
|
f'config {output_cfg_fpath}')
|
|
582
|
-
|
|
591
|
+
if not rename_module:
|
|
592
|
+
return top, top
|
|
593
|
+
return top, rename_module
|
|
583
594
|
|
|
584
595
|
|
|
585
596
|
def get_synth_results_fpath(self, design_num: int, top: str) -> str:
|
|
586
|
-
'''Returns the synthesized .v file fpath'''
|
|
597
|
+
'''Returns the synthesized .v file fpath, using orignal top (not renamed)'''
|
|
587
598
|
if not top:
|
|
588
|
-
top = self.get_synth_top_from_output_config(design_num=design_num)
|
|
599
|
+
top, _ = self.get_synth_top_from_output_config(design_num=design_num)
|
|
589
600
|
|
|
590
601
|
work_dir = self.synth_work_dirs[design_num]
|
|
591
602
|
fpath = os.path.join(work_dir, 'yosys', f'{top}.v')
|
|
@@ -594,7 +605,7 @@ class CommandLecYosys(CommandLec, ToolYosys):
|
|
|
594
605
|
return fpath
|
|
595
606
|
|
|
596
607
|
|
|
597
|
-
def do_it(self) -> None:
|
|
608
|
+
def do_it(self) -> None: # pylint: disable=too-many-locals,too-many-statements,too-many-branches
|
|
598
609
|
self.set_tool_defines()
|
|
599
610
|
self.write_eda_config_and_args()
|
|
600
611
|
|
|
@@ -622,6 +633,9 @@ class CommandLecYosys(CommandLec, ToolYosys):
|
|
|
622
633
|
self.exec(work_dir=self.args['work-dir'], command_list=x,
|
|
623
634
|
tee_fpath=x.tee_fpath)
|
|
624
635
|
|
|
636
|
+
util.info(f'LEC ran via --yosys-scriptfile: {self.args["yosys-scriptfile"]}')
|
|
637
|
+
return
|
|
638
|
+
|
|
625
639
|
|
|
626
640
|
if self.args['synth']:
|
|
627
641
|
synth1_cmd_list = self.get_synth_command_list(design_num=0)
|
|
@@ -636,23 +650,23 @@ class CommandLecYosys(CommandLec, ToolYosys):
|
|
|
636
650
|
self.exec(pwd, synth2_cmd_list, background=True)
|
|
637
651
|
util.info(f'Finished with 2nd LEC synthesis {self.args["designs"][1]}')
|
|
638
652
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
]
|
|
653
|
+
|
|
654
|
+
top0, module0 = self.get_synth_top_from_output_config(design_num=0)
|
|
655
|
+
top1, module1 = self.get_synth_top_from_output_config(design_num=1)
|
|
656
|
+
self.synth_designs_tops = [module0, module1]
|
|
643
657
|
util.info(f'Design tops: {self.synth_designs_tops}')
|
|
644
658
|
|
|
645
659
|
# read the output config
|
|
646
660
|
self.synth_designs_fpaths = [
|
|
647
661
|
os.path.abspath(
|
|
648
|
-
self.get_synth_results_fpath(design_num=0, top=
|
|
662
|
+
self.get_synth_results_fpath(design_num=0, top=top0)),
|
|
649
663
|
os.path.abspath(
|
|
650
|
-
self.get_synth_results_fpath(design_num=1, top=
|
|
664
|
+
self.get_synth_results_fpath(design_num=1, top=top1))
|
|
651
665
|
]
|
|
652
666
|
util.info(f'Design tops: {self.synth_designs_fpaths}')
|
|
653
667
|
|
|
654
668
|
else:
|
|
655
|
-
# don't run synthesis, need the two top level .v files in
|
|
669
|
+
# don't run synthesis, need the two top level .v|.sv files in
|
|
656
670
|
# self.synth_designs_fpaths, and need the two top module names in
|
|
657
671
|
# self.synth_designs_tops
|
|
658
672
|
self.synth_designs_fpaths = [
|
|
@@ -660,11 +674,19 @@ class CommandLecYosys(CommandLec, ToolYosys):
|
|
|
660
674
|
os.path.abspath(self.args['designs'][1])
|
|
661
675
|
]
|
|
662
676
|
|
|
677
|
+
for i in (0, 1):
|
|
678
|
+
if not os.path.isfile(self.args['designs'][i]):
|
|
679
|
+
self.error(
|
|
680
|
+
'Using synth=False (--no-synth) --designs=<value> must be a single',
|
|
681
|
+
f'filename, however {self.args["designs"][i]} does not exist'
|
|
682
|
+
)
|
|
683
|
+
|
|
663
684
|
path, fname = os.path.split(self.synth_designs_fpaths[0])
|
|
664
685
|
module_guess, _ = os.path.splitext(fname)
|
|
665
686
|
top1 = util.get_inferred_top_module_name(
|
|
666
687
|
module_guess=module_guess, module_fpath=self.synth_designs_fpaths[0]
|
|
667
688
|
)
|
|
689
|
+
util.debug(f'design1 {module_guess=} {fname=} {path=}')
|
|
668
690
|
util.info(f'design1 top module name = {top1} (from {path} / {fname})')
|
|
669
691
|
|
|
670
692
|
path, fname = os.path.split(self.synth_designs_fpaths[1])
|
|
@@ -672,6 +694,7 @@ class CommandLecYosys(CommandLec, ToolYosys):
|
|
|
672
694
|
top2 = util.get_inferred_top_module_name(
|
|
673
695
|
module_guess=module_guess, module_fpath=self.synth_designs_fpaths[1]
|
|
674
696
|
)
|
|
697
|
+
util.debug(f'design2 {module_guess=} {fname=} {path=}')
|
|
675
698
|
util.info(f'design2 top module name = {top2} (from {path} / {fname})')
|
|
676
699
|
|
|
677
700
|
self.synth_designs_tops = [top1, top2]
|
|
@@ -691,13 +714,20 @@ class CommandLecYosys(CommandLec, ToolYosys):
|
|
|
691
714
|
]
|
|
692
715
|
else:
|
|
693
716
|
self.error(f' --pre-read-verilog file {x} does not exist')
|
|
717
|
+
|
|
718
|
+
nooverwrite = ''
|
|
719
|
+
if self.args['synth'] and not self.args['flatten-all']:
|
|
720
|
+
# If we don't flatten-all from synthesis, and we had to run synthesis,
|
|
721
|
+
# then read the 2nd file with -overwrite
|
|
722
|
+
nooverwrite = '-nooverwrite'
|
|
723
|
+
|
|
694
724
|
lec_cmd_f_list += [
|
|
695
725
|
'# Design1 (module):',
|
|
696
726
|
f'read_verilog -sv -icells {self.synth_designs_fpaths[0]}',
|
|
697
727
|
'# Design2 (module):',
|
|
698
|
-
f'read_verilog -sv -icells {self.synth_designs_fpaths[1]}',
|
|
728
|
+
f'read_verilog -sv -icells {self.synth_designs_fpaths[1]} {nooverwrite}',
|
|
699
729
|
'clk2fflogic;',
|
|
700
|
-
f'miter -equiv -flatten {" ".join(self.
|
|
730
|
+
f'miter -equiv -flatten {" ".join(self.synth_designs_tops)} miter',
|
|
701
731
|
('sat -seq 50 -verify -prove trigger 0 -show-all -show-inputs -show-outputs'
|
|
702
732
|
' -set-init-zero miter'),
|
|
703
733
|
]
|
|
@@ -10,8 +10,6 @@ import subprocess
|
|
|
10
10
|
|
|
11
11
|
from opencos.util import debug
|
|
12
12
|
|
|
13
|
-
vsim_path = shutil.which('vsim')
|
|
14
|
-
|
|
15
13
|
INIT_HAS_RUN = False
|
|
16
14
|
TOOL_IS = {
|
|
17
15
|
'riviera': False,
|
|
@@ -29,6 +27,7 @@ def init() -> None:
|
|
|
29
27
|
return
|
|
30
28
|
|
|
31
29
|
INIT_HAS_RUN = True
|
|
30
|
+
vsim_path = shutil.which('vsim')
|
|
32
31
|
|
|
33
32
|
if not vsim_path:
|
|
34
33
|
return
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opencos-eda
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.57
|
|
4
4
|
Summary: A simple Python package for wrapping RTL simuliatons and synthesis
|
|
5
5
|
Author-email: Simon Sabato <simon@cognichip.ai>, Drew Ranck <drew@cognichip.ai>
|
|
6
6
|
Project-URL: Homepage, https://github.com/cognichip/opencos
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|