opencos-eda 0.2.56__tar.gz → 0.3.0__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.3.0}/PKG-INFO +2 -1
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/_version.py +6 -3
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/_waves_pkg.sv +34 -2
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/build.py +1 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/export.py +1 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/flist.py +1 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/lec.py +5 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/multi.py +4 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/proj.py +1 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/shell.py +4 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/sim.py +47 -1
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/synth.py +4 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/deps/defaults.py +15 -7
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/deps/deps_commands.py +84 -74
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/deps_schema.py +3 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/eda.py +15 -2
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/eda_base.py +61 -16
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/eda_config.py +35 -1
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/eda_config_defaults.yml +3 -1
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/export_helper.py +5 -1
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/deps_files/command_order/DEPS.yml +11 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/helpers.py +57 -19
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/test_deps_helpers.py +37 -25
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/test_eda.py +26 -60
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/cocotb.py +25 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/modelsim_ase.py +65 -16
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/riviera.py +31 -6
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/slang_yosys.py +4 -1
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/verilator.py +28 -38
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/yosys.py +50 -20
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/util.py +63 -12
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/utils/vscode_helper.py +1 -1
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/utils/vsim_helper.py +2 -3
- {opencos_eda-0.2.56 → opencos_eda-0.3.0/opencos_eda.egg-info}/PKG-INFO +2 -1
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos_eda.egg-info/requires.txt +1 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/pyproject.toml +2 -1
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/LICENSE +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/LICENSE.spdx +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/README.md +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/__init__.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/__init__.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/deps_help.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/elab.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/lint.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/open.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/sweep.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/targets.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/upload.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/commands/waves.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/deps/__init__.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/deps/deps_file.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/deps/deps_processor.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/eda_config_max_verilator_waivers.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/eda_config_reduced.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/eda_deps_bash_completion.bash +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/eda_deps_sanitize.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/eda_extract_targets.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/eda_tool_helper.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/export_json_convert.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/files.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/hw/__init__.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/hw/oc_cli.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/hw/pcie.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/names.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/peakrdl_cleanup.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/seed.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/__init__.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/custom_config.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/deps_files/error_msgs/DEPS.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/deps_files/iverilog_test/DEPS.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/deps_files/no_deps_here/DEPS.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/deps_files/non_sv_reqs/DEPS.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/deps_files/tags_with_tools/DEPS.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/deps_files/test_err_fatal/DEPS.yml +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/test_build.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/test_deps_schema.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/test_eda_elab.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/test_eda_synth.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/test_oc_cli.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tests/test_tools.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/__init__.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/invio.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/invio_helpers.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/invio_yosys.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/iverilog.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/quartus.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/questa.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/questa_fse.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/slang.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/surelog.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/tabbycad_yosys.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/tools/vivado.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/utils/__init__.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/utils/markup_helpers.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/utils/status_constants.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/utils/str_helpers.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos/utils/subprocess_helpers.py +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos_eda.egg-info/SOURCES.txt +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos_eda.egg-info/dependency_links.txt +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos_eda.egg-info/entry_points.txt +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/opencos_eda.egg-info/top_level.txt +0 -0
- {opencos_eda-0.2.56 → opencos_eda-0.3.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opencos-eda
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
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
|
|
@@ -11,6 +11,7 @@ Requires-Dist: mergedeep>=1.3.4
|
|
|
11
11
|
Requires-Dist: peakrdl>=1.1.0
|
|
12
12
|
Requires-Dist: pyyaml>=6.0.2
|
|
13
13
|
Requires-Dist: pytest>=8.3.5
|
|
14
|
+
Requires-Dist: python-dotenv>=1.0.1
|
|
14
15
|
Requires-Dist: schema>=0.7.7
|
|
15
16
|
Requires-Dist: toml>=0.10.2
|
|
16
17
|
Requires-Dist: yamllint>=1.35.1
|
|
@@ -9,11 +9,14 @@ if sys.version_info >= (3, 8):
|
|
|
9
9
|
|
|
10
10
|
from importlib import metadata
|
|
11
11
|
try:
|
|
12
|
-
|
|
12
|
+
ver = metadata.version(NAME)
|
|
13
13
|
except metadata.PackageNotFoundError:
|
|
14
14
|
# Handle case where the package is not installed (e.g., running from source checkout)
|
|
15
|
-
|
|
15
|
+
ver = "0.0.0"
|
|
16
16
|
|
|
17
17
|
else:
|
|
18
18
|
# This package only supports >= 3.8, so not doing the importlib_metadata method.
|
|
19
|
-
|
|
19
|
+
ver = "unknown" # Or raise an error, or handle differently
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
VERSION = ver # pylint: disable=invalid-name
|
|
@@ -15,7 +15,7 @@ package _waves_pkg;
|
|
|
15
15
|
bit trace_en_init = 0;
|
|
16
16
|
bit trace_en = init_trace();
|
|
17
17
|
|
|
18
|
-
function
|
|
18
|
+
function bit init_trace();
|
|
19
19
|
|
|
20
20
|
if (trace_en_init) // only do this once.
|
|
21
21
|
return trace_en;
|
|
@@ -41,7 +41,39 @@ package _waves_pkg;
|
|
|
41
41
|
|
|
42
42
|
endfunction : init_trace
|
|
43
43
|
|
|
44
|
-
`
|
|
44
|
+
`elsif RIVIERA
|
|
45
|
+
|
|
46
|
+
bit trace_en_init = 0;
|
|
47
|
+
bit trace_en = init_trace();
|
|
48
|
+
|
|
49
|
+
// Note: must be non-automatic function for --tool=riviera
|
|
50
|
+
function bit init_trace();
|
|
51
|
+
|
|
52
|
+
if (trace_en_init) // only do this once.
|
|
53
|
+
return trace_en;
|
|
54
|
+
|
|
55
|
+
trace_en_init = 1;
|
|
56
|
+
|
|
57
|
+
if ($test$plusargs("trace") != 0) begin
|
|
58
|
+
automatic string trace_str_value = "";
|
|
59
|
+
void'($value$plusargs("trace=%s", trace_str_value));
|
|
60
|
+
if (trace_str_value.tolower() == "vcd") begin
|
|
61
|
+
$display("%t %m: Starting tracing to ./dump.vcd, plusarg +trace=%s",
|
|
62
|
+
$realtime, trace_str_value);
|
|
63
|
+
$dumpfile("dump.vcd");
|
|
64
|
+
$dumpvars();
|
|
65
|
+
return 1;
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
$display("%t %m: Starting tracing to ./dump.fst", $realtime);
|
|
70
|
+
$dumpfile("dump.fst");
|
|
71
|
+
$dumpvars();
|
|
72
|
+
return 1;
|
|
73
|
+
|
|
74
|
+
endfunction : init_trace
|
|
75
|
+
|
|
76
|
+
`endif
|
|
45
77
|
`endif
|
|
46
78
|
`endif
|
|
47
79
|
|
|
@@ -50,6 +50,7 @@ class CommandExport(CommandDesign):
|
|
|
50
50
|
self.create_work_dir()
|
|
51
51
|
self.run_dep_commands()
|
|
52
52
|
self.do_it()
|
|
53
|
+
self.run_post_tool_dep_commands()
|
|
53
54
|
else:
|
|
54
55
|
util.warning(f'CommandExport: {self.command_name=} not run due to lack of',
|
|
55
56
|
f'{self.args["top"]=} value')
|
|
@@ -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 = ['', '']
|
|
@@ -96,6 +100,7 @@ class CommandLec(CommandDesign):
|
|
|
96
100
|
self.create_work_dir()
|
|
97
101
|
self.run_dep_commands()
|
|
98
102
|
self.do_it()
|
|
103
|
+
self.run_post_tool_dep_commands()
|
|
99
104
|
return unparsed
|
|
100
105
|
|
|
101
106
|
|
|
@@ -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):
|
|
@@ -58,6 +58,10 @@ class CommandShell(CommandDesign):
|
|
|
58
58
|
self.create_work_dir()
|
|
59
59
|
self.run_dep_commands()
|
|
60
60
|
self.do_it()
|
|
61
|
+
self.run_post_tool_dep_commands()
|
|
62
|
+
else:
|
|
63
|
+
util.warning(f'CommandShell: {self.command_name=} not run due to lack of',
|
|
64
|
+
f'{self.args["top"]=} value')
|
|
61
65
|
return unparsed
|
|
62
66
|
|
|
63
67
|
|
|
@@ -63,6 +63,8 @@ class CommandSim(CommandDesign):
|
|
|
63
63
|
'sim-args': [],
|
|
64
64
|
'sim-plusargs': [], # lists are handled by 'set_arg(k,v)' so they append.
|
|
65
65
|
'sim-library': [],
|
|
66
|
+
'compile-waivers': [],
|
|
67
|
+
'sim-waivers': [],
|
|
66
68
|
'coverage': False,
|
|
67
69
|
'waves': False,
|
|
68
70
|
'waves-start': 0,
|
|
@@ -142,6 +144,7 @@ class CommandSim(CommandDesign):
|
|
|
142
144
|
self.create_work_dir()
|
|
143
145
|
self.run_dep_commands()
|
|
144
146
|
self.do_it()
|
|
147
|
+
self.run_post_tool_dep_commands()
|
|
145
148
|
return unparsed
|
|
146
149
|
|
|
147
150
|
|
|
@@ -400,7 +403,7 @@ class CommandSim(CommandDesign):
|
|
|
400
403
|
'''
|
|
401
404
|
|
|
402
405
|
all_lists = [] # list - of - (command-list)
|
|
403
|
-
if self.
|
|
406
|
+
if self.has_pre_compile_dep_shell_commands:
|
|
404
407
|
all_lists = [
|
|
405
408
|
['./pre_compile_dep_shell_commands.sh']
|
|
406
409
|
]
|
|
@@ -423,6 +426,11 @@ class CommandSim(CommandDesign):
|
|
|
423
426
|
line_breaks=simulate_line_breaks)
|
|
424
427
|
all_lists.append(['./' + simulate_sh_fname])
|
|
425
428
|
|
|
429
|
+
if self.has_post_tool_dep_shell_commands:
|
|
430
|
+
all_lists = [
|
|
431
|
+
['./post_tool_dep_shell_commands.sh']
|
|
432
|
+
]
|
|
433
|
+
|
|
426
434
|
util.write_shell_command_file(dirpath=self.args['work-dir'], filename='all.sh',
|
|
427
435
|
command_lists=all_lists)
|
|
428
436
|
|
|
@@ -459,3 +467,41 @@ class CommandSim(CommandDesign):
|
|
|
459
467
|
def get_post_simulate_command_lists(self, **kwargs) -> list:
|
|
460
468
|
''' Returns a list of lists (list of command lists).'''
|
|
461
469
|
raise NotImplementedError
|
|
470
|
+
|
|
471
|
+
def add_waves_pkg_file(self) -> None:
|
|
472
|
+
'''If --waves is present, and one of --waves-fst or --waves-vcd or --dump-vcd, and
|
|
473
|
+
|
|
474
|
+
the user is missing any $dumpfile(), then adds a pre-written
|
|
475
|
+
SystemVerilog package to their source code. Note that individual tools have
|
|
476
|
+
to call this prior to their compile step, CommandSim does not run this method for
|
|
477
|
+
you.
|
|
478
|
+
'''
|
|
479
|
+
if not self.args['waves']:
|
|
480
|
+
return
|
|
481
|
+
if not any(self.args.get(x, False) for x in ('waves-fst', 'waves-vcd', 'dump-vcd')):
|
|
482
|
+
return
|
|
483
|
+
found_dumpfile = False
|
|
484
|
+
for fname in self.files_v + self.files_sv:
|
|
485
|
+
if found_dumpfile:
|
|
486
|
+
break
|
|
487
|
+
with open(fname, encoding='utf-8') as f:
|
|
488
|
+
for line in f.readlines():
|
|
489
|
+
if '$dumpfile' in line:
|
|
490
|
+
found_dumpfile = True
|
|
491
|
+
break
|
|
492
|
+
|
|
493
|
+
if not found_dumpfile:
|
|
494
|
+
thispath = os.path.dirname(__file__)
|
|
495
|
+
file_to_add = os.path.join(thispath, '..', '_waves_pkg.sv')
|
|
496
|
+
util.info(f'--waves arg present, no $dumpfile found, adding SV file: {file_to_add}')
|
|
497
|
+
self.add_file(file_to_add)
|
|
498
|
+
|
|
499
|
+
# register .vcd or .fst artifacts:
|
|
500
|
+
util.artifacts.add_extension(
|
|
501
|
+
search_paths=self.args['work-dir'], file_extension='fst',
|
|
502
|
+
typ='waveform', description='Simulation Waveform FST (Fast Signal Trace) file'
|
|
503
|
+
)
|
|
504
|
+
util.artifacts.add_extension(
|
|
505
|
+
search_paths=self.args['work-dir'], file_extension='vcd',
|
|
506
|
+
typ='waveform', description='Simulation Waveform VCD (Value Change Dump) file'
|
|
507
|
+
)
|
|
@@ -73,6 +73,10 @@ class CommandSynth(CommandDesign):
|
|
|
73
73
|
self.create_work_dir()
|
|
74
74
|
self.run_dep_commands()
|
|
75
75
|
self.do_it()
|
|
76
|
+
self.run_post_tool_dep_commands()
|
|
77
|
+
else:
|
|
78
|
+
util.warning(f'CommandSynth: {self.command_name=} not run due to lack of',
|
|
79
|
+
f'{self.args["top"]=} value')
|
|
76
80
|
return unparsed
|
|
77
81
|
|
|
78
82
|
def do_export(self):
|
|
@@ -59,14 +59,22 @@ SUPPORTED_TAG_KEYS = set([
|
|
|
59
59
|
'additive-config-tools',
|
|
60
60
|
])
|
|
61
61
|
|
|
62
|
+
COMMAND_ATTRIBUTES = {
|
|
63
|
+
# with default values
|
|
64
|
+
'run-from-work-dir': True,
|
|
65
|
+
'filepath-subst-target-dir': True,
|
|
66
|
+
|
|
67
|
+
'run-after-tool': False, # default is to run before any tool compile step.
|
|
68
|
+
'dirpath-subst-target-dir': False,
|
|
69
|
+
'var-subst-args': False,
|
|
70
|
+
'var-subst-os-env': False,
|
|
71
|
+
'tee': None,
|
|
72
|
+
}
|
|
73
|
+
|
|
62
74
|
SUPPORTED_COMMAND_KEYS = set([
|
|
63
75
|
'shell',
|
|
64
|
-
'work-dir-add-srcs', 'work-dir-add-sources',
|
|
65
76
|
'peakrdl',
|
|
66
|
-
'
|
|
67
|
-
'filepath-subst-target-dir', # default True
|
|
68
|
-
'dirpath-subst-target-dir', # default False
|
|
69
|
-
'var-subst-args',
|
|
70
|
-
'var-subst-os-env',
|
|
71
|
-
'tee',
|
|
77
|
+
'work-dir-add-srcs', 'work-dir-add-sources'
|
|
72
78
|
])
|
|
79
|
+
for key in COMMAND_ATTRIBUTES:
|
|
80
|
+
SUPPORTED_COMMAND_KEYS.add(key)
|
|
@@ -16,14 +16,14 @@ import re
|
|
|
16
16
|
import shutil
|
|
17
17
|
|
|
18
18
|
from opencos.util import debug, error, warning, ShellCommandList
|
|
19
|
-
from opencos.deps.defaults import SUPPORTED_COMMAND_KEYS
|
|
19
|
+
from opencos.deps.defaults import SUPPORTED_COMMAND_KEYS, COMMAND_ATTRIBUTES
|
|
20
20
|
|
|
21
21
|
THISPATH = os.path.dirname(__file__)
|
|
22
22
|
PEAKRDL_CLEANUP_PY = os.path.join(THISPATH, '..', 'peakrdl_cleanup.py')
|
|
23
23
|
|
|
24
24
|
def path_substitutions_relative_to_work_dir(
|
|
25
25
|
exec_list: list, info_str: str, target_path: str,
|
|
26
|
-
|
|
26
|
+
attributes: dict
|
|
27
27
|
) -> list:
|
|
28
28
|
'''For shell commands, since eda.py Command objects operate out of a "work-dir", it can
|
|
29
29
|
make shell commands confusing with additional ../.. to get to the calling directory, and
|
|
@@ -38,7 +38,8 @@ def path_substitutions_relative_to_work_dir(
|
|
|
38
38
|
dirpath-subst-target-dir: True)
|
|
39
39
|
'''
|
|
40
40
|
|
|
41
|
-
if not
|
|
41
|
+
if not attributes.get('filepath-subst-target-dir', True) and \
|
|
42
|
+
not attributes.get('dirpath-subst-target-dir', False):
|
|
42
43
|
return exec_list
|
|
43
44
|
|
|
44
45
|
# Look for path substitutions, b/c we later "work" in self.args['work-dir'], but
|
|
@@ -53,13 +54,15 @@ def path_substitutions_relative_to_work_dir(
|
|
|
53
54
|
# self.args['work-dir'] don't need this, and we can't assume dir levels in the work-dir.
|
|
54
55
|
try:
|
|
55
56
|
try_path = os.path.abspath(os.path.join(os.path.abspath(target_path), m.group(1)))
|
|
56
|
-
if
|
|
57
|
+
if attributes.get('filepath-subst-target-dir', True) and \
|
|
58
|
+
os.path.isfile(try_path):
|
|
57
59
|
# make the substitution
|
|
58
60
|
exec_list[i] = word.replace(m.group(1), try_path)
|
|
59
61
|
debug(f'file path substitution {info_str=} {target_path=}: replaced - {word=}'
|
|
60
62
|
f'is now ={exec_list[i]}. This can be disabled in DEPS with:',
|
|
61
63
|
'"filepath-subst-targetdir: false"')
|
|
62
|
-
elif
|
|
64
|
+
elif attributes.get('dirpath-subst-target-dir', False) and \
|
|
65
|
+
os.path.isdir(try_path):
|
|
63
66
|
# make the substitution
|
|
64
67
|
exec_list[i] = word.replace(m.group(1), try_path)
|
|
65
68
|
debug(f'dir path substitution {info_str=} {target_path=}: replaced - {word=}'
|
|
@@ -84,12 +87,7 @@ def line_with_var_subst( # pylint: disable=dangerous-default-value
|
|
|
84
87
|
if '{' not in line:
|
|
85
88
|
return line
|
|
86
89
|
|
|
87
|
-
|
|
88
|
-
replace_dict = {}
|
|
89
|
-
replace_dict.update(os.environ)
|
|
90
|
-
replace_dict.update(replace_vars_dict)
|
|
91
|
-
else:
|
|
92
|
-
replace_dict = replace_vars_dict
|
|
90
|
+
replace_dict = replace_vars_dict
|
|
93
91
|
|
|
94
92
|
words = line.split()
|
|
95
93
|
for i,word in enumerate(words):
|
|
@@ -100,6 +98,13 @@ def line_with_var_subst( # pylint: disable=dangerous-default-value
|
|
|
100
98
|
pass
|
|
101
99
|
|
|
102
100
|
new_line = ' '.join(words)
|
|
101
|
+
|
|
102
|
+
if replace_vars_os_env:
|
|
103
|
+
try:
|
|
104
|
+
new_line = os.path.expandvars(new_line)
|
|
105
|
+
except Exception as e:
|
|
106
|
+
warning(f'{e}: trying to apply env vars to line: {new_line}')
|
|
107
|
+
|
|
103
108
|
if new_line != line:
|
|
104
109
|
debug(f'{target_node=} {target_path=} performed string format replacement,',
|
|
105
110
|
f'{line=} {new_line=}')
|
|
@@ -112,8 +117,7 @@ def line_with_var_subst( # pylint: disable=dangerous-default-value
|
|
|
112
117
|
|
|
113
118
|
def parse_deps_shell_str(
|
|
114
119
|
line: str, target_path: str, target_node: str,
|
|
115
|
-
|
|
116
|
-
enable_dirpath_subst_target_dir: bool = False,
|
|
120
|
+
attributes: dict,
|
|
117
121
|
enable: bool = True
|
|
118
122
|
) -> dict:
|
|
119
123
|
'''Returns None or a dict of a possible shell command from line (str)
|
|
@@ -146,20 +150,21 @@ def parse_deps_shell_str(
|
|
|
146
150
|
# Note this can be disable in DEPS via path-subst-target-dir=False
|
|
147
151
|
exec_list = path_substitutions_relative_to_work_dir(
|
|
148
152
|
exec_list=exec_list, info_str='shell@', target_path=target_path,
|
|
149
|
-
|
|
150
|
-
enable_dirpath_subst=enable_dirpath_subst_target_dir
|
|
153
|
+
attributes=attributes
|
|
151
154
|
)
|
|
152
155
|
|
|
153
156
|
return {
|
|
154
157
|
'target_path': os.path.abspath(target_path),
|
|
155
158
|
'target_node': target_node,
|
|
156
|
-
'run_from_work_dir': True, # may be overriden later.
|
|
157
159
|
'exec_list': exec_list,
|
|
160
|
+
'attributes': attributes
|
|
158
161
|
}
|
|
159
162
|
|
|
160
163
|
|
|
161
164
|
def parse_deps_work_dir_add_srcs(
|
|
162
|
-
line : str, target_path : str, target_node : str,
|
|
165
|
+
line : str, target_path : str, target_node : str,
|
|
166
|
+
attributes: dict,
|
|
167
|
+
enable : bool = True
|
|
163
168
|
) -> dict:
|
|
164
169
|
'''Returns None or a dict describing source files to add from the work-dir path
|
|
165
170
|
|
|
@@ -182,17 +187,19 @@ def parse_deps_work_dir_add_srcs(
|
|
|
182
187
|
files_str = m.group(1)
|
|
183
188
|
file_list = files_str.split()
|
|
184
189
|
|
|
185
|
-
d = {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
190
|
+
d = {
|
|
191
|
+
'target_path': os.path.abspath(target_path),
|
|
192
|
+
'target_node': target_node,
|
|
193
|
+
'file_list': file_list,
|
|
194
|
+
'attributes': attributes
|
|
195
|
+
}
|
|
189
196
|
return d
|
|
190
197
|
|
|
191
198
|
|
|
192
199
|
def parse_deps_peakrdl( # pylint: disable=too-many-locals
|
|
193
|
-
line: str, target_path: str, target_node: str,
|
|
194
|
-
|
|
195
|
-
|
|
200
|
+
line: str, target_path: str, target_node: str,
|
|
201
|
+
attributes: dict,
|
|
202
|
+
enable: bool = True
|
|
196
203
|
) -> dict:
|
|
197
204
|
'''Returns None or a dict describing a PeakRDL CSR register generator dependency
|
|
198
205
|
|
|
@@ -268,16 +275,16 @@ def parse_deps_peakrdl( # pylint: disable=too-many-locals
|
|
|
268
275
|
line=(' shell@ ' + ' '.join(one_cmd_as_list)),
|
|
269
276
|
target_path=target_path,
|
|
270
277
|
target_node=target_node,
|
|
271
|
-
|
|
272
|
-
enable_dirpath_subst_target_dir=enable_dirpath_subst_target_dir
|
|
278
|
+
attributes=attributes
|
|
273
279
|
)
|
|
274
280
|
)
|
|
275
281
|
|
|
276
282
|
# Make the work_dir_add_srcs dict:
|
|
277
283
|
ret_dict['work_dir_add_srcs'] = parse_deps_work_dir_add_srcs(
|
|
278
|
-
line
|
|
279
|
-
target_path
|
|
280
|
-
target_node
|
|
284
|
+
line=' work_dir_add_srcs@ ' + ' '.join(sv_files),
|
|
285
|
+
target_path=target_path,
|
|
286
|
+
target_node=target_node,
|
|
287
|
+
attributes=attributes
|
|
281
288
|
)
|
|
282
289
|
|
|
283
290
|
return ret_dict
|
|
@@ -329,65 +336,69 @@ def deps_commands_handler( #pylint: disable=too-many-locals,too-many-branches
|
|
|
329
336
|
error(f'deps_commands.process_commands - command {key=} not in',
|
|
330
337
|
f'{SUPPORTED_COMMAND_KEYS=}')
|
|
331
338
|
|
|
339
|
+
# collect attributes for this command:
|
|
340
|
+
attributes = {}
|
|
341
|
+
for key, default_value in COMMAND_ATTRIBUTES.items():
|
|
342
|
+
attributes[key] = command.get(key, default_value)
|
|
343
|
+
|
|
332
344
|
var_subst_dict = {} # this is per-command.
|
|
333
|
-
if config['dep_command_enables'].get('var_subst_os_env', False) and \
|
|
334
|
-
command.get('var-subst-os-env', False):
|
|
335
|
-
var_subst_dict.update(dict(os.environ))
|
|
336
345
|
if config['dep_command_enables'].get('var_subst_args', False) and \
|
|
337
|
-
|
|
346
|
+
attributes['var-subst-args']:
|
|
338
347
|
var_subst_dict = eda_args
|
|
339
348
|
|
|
340
|
-
tee_fpath = command.get('tee', None)
|
|
341
|
-
|
|
342
|
-
# These are both optional bools, default True, would have to explicitly be set to False
|
|
343
|
-
# to take effect:
|
|
344
|
-
run_from_work_dir = command.get('run-from-work-dir', True)
|
|
345
|
-
filepath_subst_target_dir = command.get('filepath-subst-target-dir', True)
|
|
346
|
-
dirpath_subst_target_dir = command.get('dirpath-subst-target-dir', False)
|
|
347
|
-
|
|
348
349
|
for key,item in command.items():
|
|
349
350
|
|
|
350
351
|
# skip the tee and var-subst-* keys, since these types are bools and not commands.
|
|
351
|
-
if key in
|
|
352
|
-
'var-subst-os-env',
|
|
353
|
-
'var-subst-args',
|
|
354
|
-
'run-from-work-dir',
|
|
355
|
-
'filepath-subst-target-dir',
|
|
356
|
-
'dirpath-subst-target-dir']:
|
|
352
|
+
if key in COMMAND_ATTRIBUTES:
|
|
357
353
|
continue
|
|
358
354
|
|
|
359
355
|
# Optional variable substituion in commands
|
|
360
356
|
if isinstance(item, str):
|
|
361
|
-
item = line_with_var_subst(
|
|
362
|
-
|
|
357
|
+
item = line_with_var_subst(
|
|
358
|
+
line=item,
|
|
359
|
+
replace_vars_dict=var_subst_dict,
|
|
360
|
+
replace_vars_os_env=attributes['var-subst-os-env'],
|
|
361
|
+
target_node=target_node,
|
|
362
|
+
target_path=deps_file
|
|
363
|
+
)
|
|
363
364
|
|
|
364
365
|
if key == 'shell':
|
|
365
366
|
# For now, piggyback on parse_deps_shell_str:
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
367
|
+
|
|
368
|
+
# If our shell commands have \n in them, split the commands.
|
|
369
|
+
item = item.replace('\\\n', ' ') # but not \ + newline
|
|
370
|
+
|
|
371
|
+
for shell_line in item.split('\n'):
|
|
372
|
+
|
|
373
|
+
shell_line = shell_line.strip()
|
|
374
|
+
if not shell_line:
|
|
375
|
+
continue
|
|
376
|
+
|
|
377
|
+
ret_dict = parse_deps_shell_str(
|
|
378
|
+
line=('shell@ ' + shell_line),
|
|
379
|
+
target_path=target_path,
|
|
380
|
+
target_node=target_node,
|
|
381
|
+
attributes=attributes,
|
|
382
|
+
enable=config['dep_command_enables']['shell'],
|
|
379
383
|
)
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
384
|
+
# To support 'tee: <some-file>' need to append it to last
|
|
385
|
+
# list item in ret_dict['exec_list'], and make it a util.ShellCommandList.
|
|
386
|
+
if attributes['tee']:
|
|
387
|
+
ret_dict['exec_list'] = ShellCommandList(
|
|
388
|
+
ret_dict['exec_list'], tee_fpath=attributes['tee']
|
|
389
|
+
)
|
|
390
|
+
assert ret_dict, \
|
|
391
|
+
f'shell command failed in {dep=} {target_node=} in {deps_file=}'
|
|
392
|
+
shell_commands_list.append(ret_dict) # process this later, append to ret tuple
|
|
383
393
|
|
|
384
394
|
elif key in ['work-dir-add-srcs', 'work-dir-add-sources']:
|
|
385
395
|
# For now, piggyback on parse_deps_work_dir_add_srcs:
|
|
386
396
|
ret_dict = parse_deps_work_dir_add_srcs(
|
|
387
|
-
line
|
|
388
|
-
target_path
|
|
389
|
-
target_node
|
|
397
|
+
line='work_dir_add_srcs@ ' + item,
|
|
398
|
+
target_path=target_path,
|
|
399
|
+
target_node=target_node,
|
|
390
400
|
enable=config['dep_command_enables']['work_dir_add_srcs'],
|
|
401
|
+
attributes=attributes,
|
|
391
402
|
)
|
|
392
403
|
assert ret_dict, \
|
|
393
404
|
f'work-dir-add-srcs command failed in {dep=} {target_node=} in {deps_file=}'
|
|
@@ -397,12 +408,11 @@ def deps_commands_handler( #pylint: disable=too-many-locals,too-many-branches
|
|
|
397
408
|
elif key == 'peakrdl':
|
|
398
409
|
# for now, piggyback on parse_deps_peakrdl:
|
|
399
410
|
ret_dict = parse_deps_peakrdl(
|
|
400
|
-
line
|
|
401
|
-
target_path
|
|
402
|
-
target_node
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
enable=config['dep_command_enables']['peakrdl']
|
|
411
|
+
line='peakrdl@ ' + item,
|
|
412
|
+
target_path=target_path,
|
|
413
|
+
target_node=target_node,
|
|
414
|
+
enable=config['dep_command_enables']['peakrdl'],
|
|
415
|
+
attributes=attributes
|
|
406
416
|
)
|
|
407
417
|
assert ret_dict, f'peakrdl command failed in {dep=} {target_node=} in {deps_file=}'
|
|
408
418
|
|
|
@@ -85,6 +85,8 @@ my_target_name:
|
|
|
85
85
|
directory path substitution relative to target dir
|
|
86
86
|
(if substituted directory exists).
|
|
87
87
|
tee: <---- string, filename to write logs to
|
|
88
|
+
run-after-tool: <---- bool, default false. Set to true to run after any
|
|
89
|
+
EDA tools, or any command handlers have completed.
|
|
88
90
|
- work-dir-add-sources: <---- work-dir-add-sources, optional list (or string)
|
|
89
91
|
- some_file_gen_from_sh.sv <---- string filename that we created with sh command
|
|
90
92
|
- peakrdl: <---- string peakrdl command for CSR generation
|
|
@@ -171,6 +173,7 @@ DEPS_COMMANDS_LIST = [
|
|
|
171
173
|
Optional('var-subst-args'): bool,
|
|
172
174
|
Optional('var-subst-os-env'): bool,
|
|
173
175
|
Optional('run-from-work-dir'): bool,
|
|
176
|
+
Optional('run-after-tool'): bool,
|
|
174
177
|
Optional('filepath-subst-target-dir'): bool,
|
|
175
178
|
Optional('dirpath-subst-target-dir'): bool,
|
|
176
179
|
Optional('tee'): Or(str, type(None)),
|
|
@@ -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)=}')
|
|
@@ -508,7 +520,8 @@ def main(*args):
|
|
|
508
520
|
|
|
509
521
|
original_args = args.copy() # save before any parsing.
|
|
510
522
|
|
|
511
|
-
# Set global --debug, --quiet, --color
|
|
523
|
+
# Set global --debug, --quiet, --color, -f/--iput-file, --envfile
|
|
524
|
+
# early before parsing other args:
|
|
512
525
|
util_parsed, unparsed = util.process_tokens(args)
|
|
513
526
|
|
|
514
527
|
util.debug(f"main: file: {os.path.realpath(__file__)}")
|