opencos-eda 0.2.54__tar.gz → 0.2.56__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.54/opencos_eda.egg-info → opencos_eda-0.2.56}/PKG-INFO +2 -2
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/commands/__init__.py +2 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/commands/flist.py +10 -0
- opencos_eda-0.2.56/opencos/commands/lint.py +51 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/commands/sim.py +31 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/deps/defaults.py +2 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/deps/deps_file.py +3 -1
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/deps/deps_processor.py +39 -1
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/deps_schema.py +22 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/eda.py +16 -5
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/eda_base.py +108 -10
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/eda_config.py +2 -1
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/eda_config_defaults.yml +13 -1
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/export_helper.py +15 -5
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/hw/oc_cli.py +1 -1
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/names.py +4 -1
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/helpers.py +5 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/test_eda_elab.py +26 -5
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/test_eda_synth.py +12 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/invio.py +8 -1
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/invio_helpers.py +47 -8
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/invio_yosys.py +3 -2
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/iverilog.py +18 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/modelsim_ase.py +19 -1
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/quartus.py +93 -12
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/questa.py +14 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/questa_fse.py +13 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/riviera.py +30 -3
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/slang.py +17 -1
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/slang_yosys.py +9 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/surelog.py +18 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/verilator.py +19 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/vivado.py +26 -2
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/yosys.py +15 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/util.py +7 -1
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/utils/str_helpers.py +8 -4
- {opencos_eda-0.2.54 → opencos_eda-0.2.56/opencos_eda.egg-info}/PKG-INFO +2 -2
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos_eda.egg-info/SOURCES.txt +1 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos_eda.egg-info/requires.txt +1 -1
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/pyproject.toml +2 -2
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/LICENSE +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/LICENSE.spdx +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/README.md +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/__init__.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/_version.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/_waves_pkg.sv +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/commands/build.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/commands/deps_help.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/commands/elab.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/commands/export.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/commands/lec.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/commands/multi.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/commands/open.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/commands/proj.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/commands/shell.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/commands/sweep.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/commands/synth.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/commands/targets.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/commands/upload.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/commands/waves.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/deps/__init__.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/deps/deps_commands.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/eda_config_max_verilator_waivers.yml +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/eda_config_reduced.yml +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/eda_deps_bash_completion.bash +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/eda_deps_sanitize.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/eda_extract_targets.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/eda_tool_helper.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/export_json_convert.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/files.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/hw/__init__.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/hw/pcie.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/peakrdl_cleanup.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/seed.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/__init__.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/custom_config.yml +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/deps_files/command_order/DEPS.yml +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/deps_files/error_msgs/DEPS.yml +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/deps_files/iverilog_test/DEPS.yml +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/deps_files/no_deps_here/DEPS.yml +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/deps_files/non_sv_reqs/DEPS.yml +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/deps_files/tags_with_tools/DEPS.yml +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/deps_files/test_err_fatal/DEPS.yml +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/test_build.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/test_deps_helpers.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/test_deps_schema.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/test_eda.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/test_oc_cli.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tests/test_tools.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/__init__.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/cocotb.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/tools/tabbycad_yosys.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/utils/__init__.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/utils/markup_helpers.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/utils/status_constants.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/utils/subprocess_helpers.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/utils/vscode_helper.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos/utils/vsim_helper.py +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos_eda.egg-info/dependency_links.txt +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos_eda.egg-info/entry_points.txt +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/opencos_eda.egg-info/top_level.txt +0 -0
- {opencos_eda-0.2.54 → opencos_eda-0.2.56}/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.56
|
|
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
|
|
@@ -15,5 +15,5 @@ Requires-Dist: schema>=0.7.7
|
|
|
15
15
|
Requires-Dist: toml>=0.10.2
|
|
16
16
|
Requires-Dist: yamllint>=1.35.1
|
|
17
17
|
Requires-Dist: PySerial>=3.5
|
|
18
|
-
Requires-Dist: cocotb>=2.0
|
|
18
|
+
Requires-Dist: cocotb>=2.0
|
|
19
19
|
Dynamic: license-file
|
|
@@ -10,6 +10,7 @@ from .elab import CommandElab
|
|
|
10
10
|
from .export import CommandExport
|
|
11
11
|
from .flist import CommandFList
|
|
12
12
|
from .multi import CommandMulti, CommandToolsMulti
|
|
13
|
+
from .lint import CommandLint
|
|
13
14
|
from .open import CommandOpen
|
|
14
15
|
from .proj import CommandProj
|
|
15
16
|
from .sim import CommandSim
|
|
@@ -28,6 +29,7 @@ __all__ = [
|
|
|
28
29
|
'CommandExport',
|
|
29
30
|
'CommandFList',
|
|
30
31
|
'CommandMulti',
|
|
32
|
+
'CommandLint',
|
|
31
33
|
'CommandOpen',
|
|
32
34
|
'CommandProj',
|
|
33
35
|
'CommandSim',
|
|
@@ -10,6 +10,7 @@ import os
|
|
|
10
10
|
from opencos import util
|
|
11
11
|
from opencos.eda_base import CommandDesign
|
|
12
12
|
from opencos.utils.str_helpers import strip_all_quotes
|
|
13
|
+
from opencos.commands.sim import parameters_dict_get_command_list
|
|
13
14
|
|
|
14
15
|
class CommandFList(CommandDesign):
|
|
15
16
|
'''Base class command handler for: eda flist ...'''
|
|
@@ -22,6 +23,7 @@ class CommandFList(CommandDesign):
|
|
|
22
23
|
'eda-dir' : 'eda.flist', # user can specify eda-dir if files are generated.
|
|
23
24
|
'out' : "flist.out",
|
|
24
25
|
'emit-define' : True,
|
|
26
|
+
'emit-parameter' : True,
|
|
25
27
|
'emit-incdir' : True,
|
|
26
28
|
'emit-v' : True,
|
|
27
29
|
'emit-sv' : True,
|
|
@@ -29,6 +31,7 @@ class CommandFList(CommandDesign):
|
|
|
29
31
|
'emit-cpp' : True,
|
|
30
32
|
'emit-non-sources' : True, # as comments, from DEPS 'reqs'
|
|
31
33
|
'prefix-define' : "+define+",
|
|
34
|
+
'prefix-parameter' : "-G",
|
|
32
35
|
'prefix-incdir' : "+incdir+",
|
|
33
36
|
'prefix-v' : "",
|
|
34
37
|
'prefix-sv' : "",
|
|
@@ -179,6 +182,13 @@ class CommandFList(CommandDesign):
|
|
|
179
182
|
newline = prefix + qd1 + f"{d}{ed1}{value}" + qd2
|
|
180
183
|
print(newline, file=fo)
|
|
181
184
|
|
|
185
|
+
if self.args['emit-parameter']:
|
|
186
|
+
prefix = strip_all_quotes(self.args['prefix-parameter'])
|
|
187
|
+
for item in parameters_dict_get_command_list(
|
|
188
|
+
params=self.parameters, arg_prefix=prefix
|
|
189
|
+
):
|
|
190
|
+
print(item, file=fo)
|
|
191
|
+
|
|
182
192
|
if self.args['emit-incdir']:
|
|
183
193
|
prefix = strip_all_quotes(self.args['prefix-incdir'])
|
|
184
194
|
for i in self.incdirs:
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'''opencos.commands.lint - Base class command handler for: eda lint ...
|
|
2
|
+
|
|
3
|
+
Intended to be overriden by Tool based classes (such as CommandLintVivado, etc)
|
|
4
|
+
|
|
5
|
+
Note that many 'lint' command handlers that also can perform simulations, such
|
|
6
|
+
as VerilatorLint, will instead inherit from VerilatorSim and simply perform a
|
|
7
|
+
shortened sim as the lint, instead of inheriting CommandLint.
|
|
8
|
+
|
|
9
|
+
Tools that don't support a 'sim' command will generally use CommandLint, such
|
|
10
|
+
as CommandLintSlang.'''
|
|
11
|
+
|
|
12
|
+
from opencos.commands.sim import CommandSim
|
|
13
|
+
|
|
14
|
+
class CommandLint(CommandSim):
|
|
15
|
+
'''Base class command handler for: eda lint ...'''
|
|
16
|
+
|
|
17
|
+
command_name = 'lint'
|
|
18
|
+
|
|
19
|
+
def __init__(self, config: dict):
|
|
20
|
+
CommandSim.__init__(self, config=config)
|
|
21
|
+
# add args specific to this simulator
|
|
22
|
+
self.args['stop-after-compile'] = True
|
|
23
|
+
self.args['lint'] = True
|
|
24
|
+
self.args['verilate-args'] = []
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def compile(self) -> None:
|
|
29
|
+
raise NotImplementedError
|
|
30
|
+
|
|
31
|
+
def elaborate(self) -> None:
|
|
32
|
+
raise NotImplementedError
|
|
33
|
+
|
|
34
|
+
def get_compile_command_lists(self, **kwargs) -> list:
|
|
35
|
+
''' Returns a list of lists (list of command lists).'''
|
|
36
|
+
raise NotImplementedError
|
|
37
|
+
|
|
38
|
+
def get_elaborate_command_lists(self, **kwargs) -> list:
|
|
39
|
+
''' Returns a list of lists (list of command lists).'''
|
|
40
|
+
raise NotImplementedError
|
|
41
|
+
|
|
42
|
+
# CommandSim methods that elab does not use:
|
|
43
|
+
|
|
44
|
+
def simulate(self):
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
def get_simulate_command_lists(self, **kwargs) -> list:
|
|
48
|
+
return []
|
|
49
|
+
|
|
50
|
+
def get_post_simulate_command_lists(self, **kwargs) -> list:
|
|
51
|
+
return []
|
|
@@ -17,6 +17,33 @@ from opencos import util, export_helper
|
|
|
17
17
|
from opencos.eda_base import CommandDesign, Tool
|
|
18
18
|
from opencos.utils import status_constants
|
|
19
19
|
|
|
20
|
+
from opencos.utils.str_helpers import sanitize_defines_for_sh, strip_outer_quotes
|
|
21
|
+
|
|
22
|
+
def parameters_dict_get_command_list(params: dict, arg_prefix: str = '-G') -> list:
|
|
23
|
+
'''Given dict of parameters, returns a command list'''
|
|
24
|
+
|
|
25
|
+
ret_list = []
|
|
26
|
+
if ' ' in arg_prefix:
|
|
27
|
+
arg_list_prefix = arg_prefix.split()
|
|
28
|
+
arg_str_prefix = ''
|
|
29
|
+
else:
|
|
30
|
+
arg_list_prefix = []
|
|
31
|
+
arg_str_prefix = arg_prefix
|
|
32
|
+
|
|
33
|
+
for k,v in params.items():
|
|
34
|
+
if not isinstance(v, (int, str)):
|
|
35
|
+
util.warning(f'parameter {k} has value: {v}, parameters must be int/string types')
|
|
36
|
+
|
|
37
|
+
ret_list.extend(arg_list_prefix)
|
|
38
|
+
if isinstance(v, int):
|
|
39
|
+
ret_list.append(f'{arg_str_prefix}{k}={v}')
|
|
40
|
+
else: # string
|
|
41
|
+
v = strip_outer_quotes(v.strip('\n'))
|
|
42
|
+
v = '"' + v + '"'
|
|
43
|
+
ret_list.append(f'{arg_str_prefix}{k}={sanitize_defines_for_sh(v)}')
|
|
44
|
+
return ret_list
|
|
45
|
+
|
|
46
|
+
|
|
20
47
|
class CommandSim(CommandDesign):
|
|
21
48
|
'''Base class command handler for: eda sim ...'''
|
|
22
49
|
|
|
@@ -80,6 +107,10 @@ class CommandSim(CommandDesign):
|
|
|
80
107
|
|
|
81
108
|
self.args['verilate-args'] = []
|
|
82
109
|
|
|
110
|
+
def process_parameters_get_list(self, arg_prefix: str = '-G') -> list:
|
|
111
|
+
'''Returns list (suitable command list for shell or for tool) from self.parameters'''
|
|
112
|
+
return parameters_dict_get_command_list(params=self.parameters, arg_prefix=arg_prefix)
|
|
113
|
+
|
|
83
114
|
def process_plusarg(self, plusarg: str, pwd: str = os.getcwd()) -> None:
|
|
84
115
|
'''Override for CommandDesign.process_plusarg(..)'''
|
|
85
116
|
maybe_plusarg = CommandDesign.process_plusarg(self, plusarg, pwd)
|
|
@@ -31,6 +31,7 @@ KNOWN_EDA_COMMANDS = set([
|
|
|
31
31
|
SUPPORTED_TARGET_TABLE_KEYS = set([
|
|
32
32
|
'args',
|
|
33
33
|
'defines',
|
|
34
|
+
'parameters',
|
|
34
35
|
'incdirs',
|
|
35
36
|
'top',
|
|
36
37
|
'deps',
|
|
@@ -52,6 +53,7 @@ SUPPORTED_TAG_KEYS = set([
|
|
|
52
53
|
'deps',
|
|
53
54
|
'reqs',
|
|
54
55
|
'defines',
|
|
56
|
+
'parameters',
|
|
55
57
|
'incdirs',
|
|
56
58
|
'replace-config-tools',
|
|
57
59
|
'additive-config-tools',
|
|
@@ -306,7 +306,9 @@ class DepsFile:
|
|
|
306
306
|
return False
|
|
307
307
|
|
|
308
308
|
if not is_valid_target_name(target_node):
|
|
309
|
-
util.warning(
|
|
309
|
+
util.warning(
|
|
310
|
+
f"In file {self.rel_deps_file}, {target_node} {VALID_TARGET_INFO_STR}"
|
|
311
|
+
)
|
|
310
312
|
|
|
311
313
|
if not caller_info:
|
|
312
314
|
# If we don't have caller_info, likely came from command line (or DEPS JSON data):
|
|
@@ -91,6 +91,22 @@ class DepsProcessor: # pylint: disable=too-many-instance-attributes
|
|
|
91
91
|
v = v.replace('%SEED%', str(self.args.get('seed', 1)))
|
|
92
92
|
self.command_design_ref.process_plusarg(f'+define+{k}={v}')
|
|
93
93
|
|
|
94
|
+
|
|
95
|
+
def apply_parameters(self, parameters_dict: dict):
|
|
96
|
+
'''Given parameters_dict, applies them to our self.command_design_ref obj'''
|
|
97
|
+
if not isinstance(parameters_dict, dict):
|
|
98
|
+
self.error(f"{parameters_dict=} is not type dict, can't apply defines,",
|
|
99
|
+
f"in {self.caller_info}")
|
|
100
|
+
for k,v in parameters_dict.items():
|
|
101
|
+
if v is None or v == '' or not isinstance(v, (int, str, bool)):
|
|
102
|
+
warning(f'parameter {k} has value: {v}, parameters must be bool/int/string types',
|
|
103
|
+
f'from {self.caller_info}')
|
|
104
|
+
else:
|
|
105
|
+
self.command_design_ref.set_parameter(
|
|
106
|
+
name=k, value=v, caller_info=self.caller_info
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
94
110
|
def apply_incdirs(self, incdirs_list:list):
|
|
95
111
|
'''Given incdirs_list, applies them to our self.command_design_ref obj'''
|
|
96
112
|
if not isinstance(incdirs_list, (str, list)):
|
|
@@ -252,6 +268,8 @@ class DepsProcessor: # pylint: disable=too-many-instance-attributes
|
|
|
252
268
|
remaining_deps_list += self.process_tags()
|
|
253
269
|
elif key == 'defines':
|
|
254
270
|
self.process_defines()
|
|
271
|
+
elif key == 'parameters':
|
|
272
|
+
self.process_parameters()
|
|
255
273
|
elif key == 'incdirs':
|
|
256
274
|
self.process_incdirs()
|
|
257
275
|
elif key == 'top':
|
|
@@ -426,6 +444,9 @@ class DepsProcessor: # pylint: disable=too-many-instance-attributes
|
|
|
426
444
|
# apply defines:
|
|
427
445
|
self.apply_defines(value.get('defines', {}))
|
|
428
446
|
|
|
447
|
+
elif key == 'parameters':
|
|
448
|
+
self.apply_parameters(value.get('parameters', {}))
|
|
449
|
+
|
|
429
450
|
elif key == 'incdirs':
|
|
430
451
|
# apply incdirs:
|
|
431
452
|
self.apply_incdirs(value.get('incdirs', []))
|
|
@@ -517,6 +538,22 @@ class DepsProcessor: # pylint: disable=too-many-instance-attributes
|
|
|
517
538
|
|
|
518
539
|
self.apply_defines(entry_defines)
|
|
519
540
|
|
|
541
|
+
def process_parameters(self):
|
|
542
|
+
'''Returns None, applies parameters (dict, if any) from self.deps_entry to
|
|
543
|
+
self.command_design_ref.'''
|
|
544
|
+
|
|
545
|
+
# Parameters:
|
|
546
|
+
# apply command specific parameters, with higher priority than the a
|
|
547
|
+
# deps_entry['sim']['parameters'] entry,
|
|
548
|
+
# do this with dict1.update(dict2):
|
|
549
|
+
entry_parameters = {}
|
|
550
|
+
entry_parameters.update(self.deps_entry.get('parameters', {}))
|
|
551
|
+
entry_parameters.update(self.entry_eda_command.get('parameters', {}))
|
|
552
|
+
assert isinstance(entry_parameters, dict), \
|
|
553
|
+
f'{entry_parameters=} for in {self.caller_info} must be a dict'
|
|
554
|
+
|
|
555
|
+
self.apply_parameters(entry_parameters)
|
|
556
|
+
|
|
520
557
|
def process_incdirs(self) -> None:
|
|
521
558
|
'''Returns None, applies incdirs (dict, if any) from self.deps_entry to
|
|
522
559
|
self.command_design_ref.'''
|
|
@@ -700,7 +737,8 @@ class DepsProcessor: # pylint: disable=too-many-instance-attributes
|
|
|
700
737
|
deps_targets_to_resolve.append(command_tuple)
|
|
701
738
|
|
|
702
739
|
|
|
703
|
-
elif isinstance(dep, str) and
|
|
740
|
+
elif isinstance(dep, str) and \
|
|
741
|
+
any(dep.startswith(x) for x in ['+define+', '+incdir+']):
|
|
704
742
|
# Note: we still support +define+ and +incdir in the deps list.
|
|
705
743
|
# check for compile-time Verilog style plusarg, which are supported under targets
|
|
706
744
|
# These are not run-time Verilog style plusargs comsumable from within the .sv:
|
|
@@ -11,6 +11,9 @@ my_target_name:
|
|
|
11
11
|
defines: <---- defines, optional table
|
|
12
12
|
USER_DEFINE_VALUE: 12
|
|
13
13
|
|
|
14
|
+
parameters: <---- parameters, optional table
|
|
15
|
+
USER_PARAM_VALUE: 12
|
|
16
|
+
|
|
14
17
|
incdirs: <---- incdirs, optional array (or string)
|
|
15
18
|
- ./
|
|
16
19
|
|
|
@@ -32,6 +35,9 @@ my_target_name:
|
|
|
32
35
|
defines: <---- defines, optional table of (key: str Or null)
|
|
33
36
|
USER_DEFINE_VALUE: 12
|
|
34
37
|
|
|
38
|
+
parameters: <---- parameters, optional table
|
|
39
|
+
USER_PARAM_VALUE: 12
|
|
40
|
+
|
|
35
41
|
incdirs: <---- incdirs, optional array of strings
|
|
36
42
|
- ./
|
|
37
43
|
|
|
@@ -55,6 +61,7 @@ METADATA: <---- (optional) unstructured table
|
|
|
55
61
|
|
|
56
62
|
my_target_name:
|
|
57
63
|
defines: <---- defines, optional table
|
|
64
|
+
parameters: <---- parameters, optional table
|
|
58
65
|
incdirs: <---- incdirs, optional array (or string)
|
|
59
66
|
top: tb <---- top, optional string
|
|
60
67
|
deps: <---- TARGET_DEPS_CONTENTS schema
|
|
@@ -105,6 +112,8 @@ my_target_name:
|
|
|
105
112
|
to the current target for this named eda command.
|
|
106
113
|
defines: <---- optional table, defines to be applied to the current
|
|
107
114
|
target for this named eda command.
|
|
115
|
+
parameters: <---- optional table, parameters to be applied to the current
|
|
116
|
+
target to for this named eda command.
|
|
108
117
|
incdirs: <---- optional array (or string) incdirs to be applied to
|
|
109
118
|
the current target for this named eda command.
|
|
110
119
|
tags: <---- tags, optional table using TARGET_TAGS_TABLE schema.
|
|
@@ -204,6 +213,9 @@ TARGET_EDA_COMMAND_ENTRY_TABLE = {
|
|
|
204
213
|
Optional('defines'): {
|
|
205
214
|
Optional(str): Or(str, int, type(None)),
|
|
206
215
|
},
|
|
216
|
+
Optional('parameters'): {
|
|
217
|
+
Optional(str): Or(str, int),
|
|
218
|
+
},
|
|
207
219
|
Optional('incdirs'): ARRAY_OR_SPACE_SEPARATED_STRING,
|
|
208
220
|
}
|
|
209
221
|
|
|
@@ -226,6 +238,9 @@ TARGET_TAGS_TABLE = {
|
|
|
226
238
|
Optional('defines'): {
|
|
227
239
|
Optional(str): Or(str, int, type(None)),
|
|
228
240
|
},
|
|
241
|
+
Optional('parameters'): {
|
|
242
|
+
Optional(str): Or(str, int),
|
|
243
|
+
},
|
|
229
244
|
Optional('incdirs'): ARRAY_OR_SPACE_SEPARATED_STRING,
|
|
230
245
|
Optional('replace-config-tools'): dict,
|
|
231
246
|
Optional('additive-config-tools'): dict,
|
|
@@ -244,6 +259,10 @@ TARGET_CONTENTS = Or(
|
|
|
244
259
|
Optional('defines'): {
|
|
245
260
|
Optional(str): Or(str, int, type(None)),
|
|
246
261
|
},
|
|
262
|
+
# parameters: table of key-value
|
|
263
|
+
Optional('parameters'): {
|
|
264
|
+
Optional(str): Or(str, int),
|
|
265
|
+
},
|
|
247
266
|
# incdirs: array
|
|
248
267
|
Optional('incdirs'): ARRAY_OR_SPACE_SEPARATED_STRING,
|
|
249
268
|
# top: string
|
|
@@ -302,6 +321,9 @@ FILE_SIMPLIFIED = Schema(
|
|
|
302
321
|
Optional('defines'): {
|
|
303
322
|
Optional(str): Or(type(None), str),
|
|
304
323
|
},
|
|
324
|
+
Optional('parameters'): {
|
|
325
|
+
Optional(str): str,
|
|
326
|
+
},
|
|
305
327
|
Optional('incdirs'): [str],
|
|
306
328
|
Optional('top'): str,
|
|
307
329
|
Optional('deps'): [str],
|
|
@@ -23,7 +23,7 @@ from opencos import util, eda_config, eda_base
|
|
|
23
23
|
from opencos.eda_base import Tool, which_tool, get_eda_exec
|
|
24
24
|
from opencos.utils import vsim_helper, vscode_helper
|
|
25
25
|
from opencos.utils.subprocess_helpers import subprocess_run_background
|
|
26
|
-
from opencos.utils import status_constants
|
|
26
|
+
from opencos.utils import status_constants, str_helpers
|
|
27
27
|
|
|
28
28
|
# Configure util:
|
|
29
29
|
util.progname = "EDA"
|
|
@@ -78,7 +78,7 @@ def get_all_commands_help_str(config: dict) -> str:
|
|
|
78
78
|
return '\n'.join(all_commands_help)
|
|
79
79
|
|
|
80
80
|
|
|
81
|
-
def usage(tokens: list, config: dict, command="") -> int:
|
|
81
|
+
def usage(tokens: list, config: dict, command: str = "", tool: str = "") -> int:
|
|
82
82
|
'''Returns an int shell return code, given remaining args (tokens list) and eda command.
|
|
83
83
|
|
|
84
84
|
config is the config dict. Used to check valid commands in config['command_handler']
|
|
@@ -112,6 +112,9 @@ And <files|targets, ...> is one or more source file or DEPS markup file target,
|
|
|
112
112
|
|
|
113
113
|
if command in config['command_handler'].keys():
|
|
114
114
|
sco = config['command_handler'][command](config=config) # sub command object
|
|
115
|
+
sco_tool = getattr(sco, '_TOOL', '')
|
|
116
|
+
if tool and tool != sco_tool:
|
|
117
|
+
util.warning(f'{tool=} does not support {command=}')
|
|
115
118
|
sco.help(tokens=tokens)
|
|
116
119
|
return util.exit(0)
|
|
117
120
|
|
|
@@ -282,9 +285,15 @@ def tool_setup(tool: str, config: dict, quiet: bool = False, auto_setup: bool =
|
|
|
282
285
|
if tool not in config['auto_tools_order'][0]:
|
|
283
286
|
tools = list(config.get('auto_tools_order', [{}])[0].keys())
|
|
284
287
|
cfg_yaml_fname = config.get('config-yml', None)
|
|
288
|
+
util.warning(f'Unknown tool: {tool}')
|
|
289
|
+
if tools:
|
|
290
|
+
util.info('Known tools:')
|
|
291
|
+
pretty_tools = str_helpers.pretty_list_columns_manual(data=tools)
|
|
292
|
+
for row in pretty_tools:
|
|
293
|
+
if row:
|
|
294
|
+
util.info(row)
|
|
285
295
|
util.error(f"Don't know how to run tool_setup({tool=}), is not in",
|
|
286
|
-
f"config['auto_tools_order']
|
|
287
|
-
f"from {cfg_yaml_fname}")
|
|
296
|
+
f"config['auto_tools_order'] from {cfg_yaml_fname}")
|
|
288
297
|
return
|
|
289
298
|
|
|
290
299
|
if tool not in config['auto_tools_found']:
|
|
@@ -394,7 +403,9 @@ def process_tokens( # pylint: disable=too-many-branches,too-many-statements,too-
|
|
|
394
403
|
for arg in unparsed:
|
|
395
404
|
if not arg.startswith('-'):
|
|
396
405
|
command = arg
|
|
397
|
-
|
|
406
|
+
if parsed.tool:
|
|
407
|
+
tool_setup(parsed.tool, config=config)
|
|
408
|
+
return usage(tokens=unparsed, config=config, command=command, tool=parsed.tool)
|
|
398
409
|
|
|
399
410
|
if parsed.tool:
|
|
400
411
|
tool_setup(parsed.tool, config=config)
|
|
@@ -831,7 +831,33 @@ class Command: # pylint: disable=too-many-public-methods
|
|
|
831
831
|
lines.append(indent_me(f" --{k:20} : string : {vstr:12}{khelp}"))
|
|
832
832
|
else:
|
|
833
833
|
lines.append(indent_me(f" --{k:20} : <unknown> : {vstr:12}{khelp}"))
|
|
834
|
+
|
|
835
|
+
lines.append('')
|
|
836
|
+
lines.append(indent_me((
|
|
837
|
+
" -G<parameterName>=<value> "
|
|
838
|
+
" Add parameter to top level, support bit/int/string types only."
|
|
839
|
+
" Example: -GDEPTH=8 (DEPTH treated as SV int/integer)."
|
|
840
|
+
" -GENABLE=1 (ENABLED treated as SV bit/int/integer)."
|
|
841
|
+
" -GName=eda (Name treated as SV string \"eda\")."
|
|
842
|
+
)))
|
|
843
|
+
lines.append(indent_me((
|
|
844
|
+
" +define+<defineName> "
|
|
845
|
+
" Add define w/out value to tool ahead of SV sources"
|
|
846
|
+
" Example: +define+SIM_SPEEDUP"
|
|
847
|
+
)))
|
|
848
|
+
lines.append(indent_me((
|
|
849
|
+
" +define+<defineName>=<value> "
|
|
850
|
+
" Add define w/ value to tool ahead of SV sources"
|
|
851
|
+
" Example: +define+TECH_LIB=2 +define+FULL_NAME=\"E D A\""
|
|
852
|
+
)))
|
|
853
|
+
lines.append(indent_me((
|
|
854
|
+
" +incdir+<path> "
|
|
855
|
+
" Add path (absolute or relative) for include directories"
|
|
856
|
+
" for SystemVerilog `include \"<some-file>.svh\""
|
|
857
|
+
" Example: +incdir+../lib"
|
|
858
|
+
)))
|
|
834
859
|
lines.append('')
|
|
860
|
+
|
|
835
861
|
for line in lines:
|
|
836
862
|
print(line)
|
|
837
863
|
|
|
@@ -922,6 +948,7 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
922
948
|
),
|
|
923
949
|
})
|
|
924
950
|
self.defines = {}
|
|
951
|
+
self.parameters = {}
|
|
925
952
|
self.incdirs = []
|
|
926
953
|
self.files = {}
|
|
927
954
|
self.files_v = []
|
|
@@ -1086,10 +1113,72 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1086
1113
|
# TODO(drew): Use the helper method in util for this instead to peek in file contents?
|
|
1087
1114
|
return os.path.splitext(os.path.basename(name))[0]
|
|
1088
1115
|
|
|
1116
|
+
def set_parameter(
|
|
1117
|
+
self, name: str, value, caller_info: str = '(CLI)',
|
|
1118
|
+
wrap_str_double_quotes: bool = True
|
|
1119
|
+
) -> None:
|
|
1120
|
+
'''Safe wrapper for setting a parameter (can only set once, from CLI or DEPS)'''
|
|
1121
|
+
|
|
1122
|
+
if name in self.parameters:
|
|
1123
|
+
util.debug("Parameter not set because it is already modified",
|
|
1124
|
+
f"(via -G<Name>=<Value>): {name}={value}; orig value",
|
|
1125
|
+
f'{self.parameters[name]} from {caller_info}')
|
|
1126
|
+
else:
|
|
1127
|
+
if isinstance(value, bool):
|
|
1128
|
+
value = int(value)
|
|
1129
|
+
elif isinstance(value, str):
|
|
1130
|
+
value = strip_outer_quotes(value.strip('\n'))
|
|
1131
|
+
if wrap_str_double_quotes:
|
|
1132
|
+
value = '"' + value + '"'
|
|
1133
|
+
self.parameters[name] = value
|
|
1134
|
+
util.debug(f"Parameter (via -G<Name>=<Value>): {name}={value}",
|
|
1135
|
+
f'from {caller_info}')
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
def process_parameter_arg(
|
|
1139
|
+
self, text: str, pwd: str = os.getcwd()
|
|
1140
|
+
) -> None:
|
|
1141
|
+
'''Retuns None, parses -G<Name>=<Value> adds to internal self.parameters.'''
|
|
1142
|
+
|
|
1143
|
+
# Deal with raw CLI/bash/powershell argparser, strip all outer quotes.
|
|
1144
|
+
text = strip_outer_quotes(text)
|
|
1145
|
+
if not pwd:
|
|
1146
|
+
pwd = ''
|
|
1147
|
+
|
|
1148
|
+
if not text.startswith('-G'):
|
|
1149
|
+
self.error(f"Didn't understand -G parameter arg: '{text}'",
|
|
1150
|
+
error_code=status_constants.EDA_COMMAND_OR_ARGS_ERROR)
|
|
1151
|
+
return
|
|
1152
|
+
|
|
1153
|
+
text = text[2:] # strip leading -G
|
|
1154
|
+
m = re.match(r'^(\w+)$', text)
|
|
1155
|
+
if m:
|
|
1156
|
+
k = m.group(1)
|
|
1157
|
+
util.warning(f"Parameter {k} has no value and will not be applied")
|
|
1158
|
+
return
|
|
1159
|
+
m = re.match(r'^(\w+)\=(\S+)$', text)
|
|
1160
|
+
if not m:
|
|
1161
|
+
m = re.match(r'^(\w+)\=(\"[^\"]*\")$', text)
|
|
1162
|
+
if m:
|
|
1163
|
+
k = m.group(1)
|
|
1164
|
+
v = m.group(2)
|
|
1165
|
+
# since this is coming from a CLI string, we have to guess at types,
|
|
1166
|
+
# for int or bool (not str) and convert bool to int:
|
|
1167
|
+
if not isinstance(v, (int, str)):
|
|
1168
|
+
self.error(f"Didn't understand -G parameter arg: name={k} value={v}",
|
|
1169
|
+
f"value must be int/str type, from: '{text}'",
|
|
1170
|
+
error_code=status_constants.EDA_COMMAND_OR_ARGS_ERROR)
|
|
1171
|
+
return
|
|
1172
|
+
try:
|
|
1173
|
+
v = int(v)
|
|
1174
|
+
except ValueError:
|
|
1175
|
+
pass
|
|
1176
|
+
self.set_parameter(k, v)
|
|
1177
|
+
|
|
1089
1178
|
|
|
1090
1179
|
def process_plusarg( # pylint: disable=too-many-branches
|
|
1091
1180
|
self, plusarg: str, pwd: str = os.getcwd()
|
|
1092
|
-
) ->
|
|
1181
|
+
) -> str:
|
|
1093
1182
|
'''Retuns str, parses a +define+, +incdir+, +key=value str; adds to internal.
|
|
1094
1183
|
|
|
1095
1184
|
Adds to self.defines, self.incdirs,
|
|
@@ -1112,7 +1201,7 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1112
1201
|
k = m.group(1)
|
|
1113
1202
|
self.defines[k] = None
|
|
1114
1203
|
util.debug(f"Defined {k}")
|
|
1115
|
-
return
|
|
1204
|
+
return ''
|
|
1116
1205
|
m = re.match(r'^(\w+)\=(\S+)$', plusarg)
|
|
1117
1206
|
if not m:
|
|
1118
1207
|
m = re.match(r'^(\w+)\=(\"[^\"]*\")$', plusarg)
|
|
@@ -1126,10 +1215,10 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1126
1215
|
v = v.replace('%SEED%', str(self.args.get('seed', 1)))
|
|
1127
1216
|
self.defines[k] = v
|
|
1128
1217
|
util.debug(f"Defined {k}={v}")
|
|
1129
|
-
return
|
|
1218
|
+
return ''
|
|
1130
1219
|
self.error(f"Didn't understand +define+: '{plusarg}'",
|
|
1131
1220
|
error_code=status_constants.EDA_COMMAND_OR_ARGS_ERROR)
|
|
1132
|
-
return
|
|
1221
|
+
return ''
|
|
1133
1222
|
|
|
1134
1223
|
if plusarg.startswith('+incdir+'):
|
|
1135
1224
|
plusarg = plusarg[len('+incdir+'):]
|
|
@@ -1139,16 +1228,16 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1139
1228
|
if incdir not in self.incdirs:
|
|
1140
1229
|
self.incdirs.append(os.path.abspath(incdir))
|
|
1141
1230
|
util.debug(f"Added include dir '{os.path.abspath(incdir)}'")
|
|
1142
|
-
return
|
|
1231
|
+
return ''
|
|
1143
1232
|
self.error(f"Didn't understand +incdir+: '{plusarg}'",
|
|
1144
1233
|
error_code=status_constants.EDA_COMMAND_OR_ARGS_ERROR)
|
|
1145
|
-
return
|
|
1234
|
+
return ''
|
|
1146
1235
|
|
|
1147
1236
|
# remaining plusargs as stored in self.args['unprocessed-plusargs'] (list)
|
|
1148
1237
|
if plusarg.startswith('+'):
|
|
1149
1238
|
if not self.config.get('bare_plusarg_supported', False):
|
|
1150
1239
|
self.error(f"bare plusarg(s) are not supported: {plusarg}'")
|
|
1151
|
-
return
|
|
1240
|
+
return ''
|
|
1152
1241
|
if plusarg not in self.args['unprocessed-plusargs']:
|
|
1153
1242
|
self.args['unprocessed-plusargs'].append(plusarg)
|
|
1154
1243
|
# For anything added to unprocessed-plusarg, we have to return it, to let
|
|
@@ -1157,7 +1246,7 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1157
1246
|
|
|
1158
1247
|
self.error(f"Didn't understand +plusarg: '{plusarg}'",
|
|
1159
1248
|
error_code=status_constants.EDA_COMMAND_OR_ARGS_ERROR)
|
|
1160
|
-
return
|
|
1249
|
+
return ''
|
|
1161
1250
|
|
|
1162
1251
|
|
|
1163
1252
|
def append_shell_commands(self, cmds : list) -> None:
|
|
@@ -1439,8 +1528,8 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1439
1528
|
unparsed = Command.process_tokens(self, tokens, process_all=False, pwd=pwd)
|
|
1440
1529
|
util.debug(f'CommandDesign - after Command.process_tokens(..) {unparsed=}')
|
|
1441
1530
|
|
|
1442
|
-
# deal with +define
|
|
1443
|
-
# walk the list, remove all items after we're done.
|
|
1531
|
+
# deal with +define+, +incdir+, +(plusargName)+, or -GParameterName=Value:
|
|
1532
|
+
# consume it and remove from unparsed, walk the list, remove all items after we're done.
|
|
1444
1533
|
remove_list = []
|
|
1445
1534
|
for token in unparsed:
|
|
1446
1535
|
# Since this is a raw argparser, we may have args that come from shlex.quote(token),
|
|
@@ -1454,6 +1543,15 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1454
1543
|
plusarg = strip_outer_quotes(token)
|
|
1455
1544
|
self.process_plusarg(plusarg, pwd=pwd)
|
|
1456
1545
|
remove_list.append(token)
|
|
1546
|
+
continue
|
|
1547
|
+
|
|
1548
|
+
# Parameters in -G<word>=<something>
|
|
1549
|
+
m = re.match(r"^\'?\-G\w+\=.+", token)
|
|
1550
|
+
if m:
|
|
1551
|
+
# Copy and strip all outer ' or " on the text:
|
|
1552
|
+
param = strip_outer_quotes(token)
|
|
1553
|
+
self.process_parameter_arg(param, pwd=pwd)
|
|
1554
|
+
remove_list.append(token)
|
|
1457
1555
|
|
|
1458
1556
|
for x in remove_list:
|
|
1459
1557
|
unparsed.remove(x)
|
|
@@ -305,7 +305,8 @@ def write_eda_config_and_args(
|
|
|
305
305
|
fullpath = os.path.join(dirpath, filename)
|
|
306
306
|
data = {}
|
|
307
307
|
for x in ['command_name', 'config', 'target', 'args', 'modified_args', 'defines',
|
|
308
|
-
'incdirs', 'files_v', 'files_sv', 'files_vhd'
|
|
308
|
+
'incdirs', 'files_v', 'files_sv', 'files_vhd', 'files_cpp', 'files_sdc',
|
|
309
|
+
'files_non_source']:
|
|
309
310
|
# Use deep copy b/c otherwise these are references to opencos.eda.
|
|
310
311
|
data[x] = copy.deepcopy(getattr(command_obj_ref, x, ''))
|
|
311
312
|
|