opencos-eda 0.2.43__tar.gz → 0.2.44__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.43/opencos_eda.egg-info → opencos_eda-0.2.44}/PKG-INFO +1 -1
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/commands/export.py +0 -1
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/commands/flist.py +4 -1
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/deps_helpers.py +2 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/eda.py +4 -3
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/eda_base.py +7 -1
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/eda_config.py +1 -1
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/eda_config_defaults.yml +6 -2
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/export_helper.py +6 -4
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/files.py +1 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/helpers.py +1 -1
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/test_eda_synth.py +63 -2
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tools/iverilog.py +1 -1
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tools/riviera.py +1 -1
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tools/slang.py +1 -1
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tools/surelog.py +1 -1
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tools/verilator.py +1 -1
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tools/vivado.py +22 -4
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tools/yosys.py +32 -13
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/util.py +5 -6
- {opencos_eda-0.2.43 → opencos_eda-0.2.44/opencos_eda.egg-info}/PKG-INFO +1 -1
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/pyproject.toml +1 -1
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/LICENSE +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/LICENSE.spdx +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/README.md +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/__init__.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/_version.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/_waves_pkg.sv +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/commands/__init__.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/commands/build.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/commands/elab.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/commands/multi.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/commands/open.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/commands/proj.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/commands/sim.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/commands/sweep.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/commands/synth.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/commands/targets.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/commands/upload.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/commands/waves.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/deps_schema.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/eda_config_max_verilator_waivers.yml +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/eda_config_reduced.yml +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/eda_deps_bash_completion.bash +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/eda_extract_targets.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/eda_tool_helper.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/export_json_convert.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/names.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/oc_cli.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/pcie.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/peakrdl_cleanup.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/seed.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/__init__.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/custom_config.yml +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/deps_files/command_order/DEPS.yml +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/deps_files/error_msgs/DEPS.yml +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/deps_files/iverilog_test/DEPS.yml +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/deps_files/no_deps_here/DEPS.yml +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/deps_files/non_sv_reqs/DEPS.yml +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/deps_files/tags_with_tools/DEPS.yml +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/deps_files/test_err_fatal/DEPS.yml +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/test_build.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/test_deps_helpers.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/test_deps_schema.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/test_eda.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/test_eda_elab.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/test_oc_cli.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tests/test_tools.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tools/__init__.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tools/invio.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tools/invio_helpers.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tools/invio_yosys.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tools/modelsim_ase.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tools/questa.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tools/slang_yosys.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos/tools/tabbycad_yosys.py +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos_eda.egg-info/SOURCES.txt +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos_eda.egg-info/dependency_links.txt +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos_eda.egg-info/entry_points.txt +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos_eda.egg-info/requires.txt +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/opencos_eda.egg-info/top_level.txt +0 -0
- {opencos_eda-0.2.43 → opencos_eda-0.2.44}/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.44
|
|
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
|
|
@@ -37,7 +37,6 @@ class CommandExport(CommandDesign):
|
|
|
37
37
|
self, tokens: list, process_all: bool = True, pwd: str = os.getcwd()
|
|
38
38
|
) -> list:
|
|
39
39
|
|
|
40
|
-
self.defines['OC_EXPORT'] = None
|
|
41
40
|
unparsed = CommandDesign.process_tokens(
|
|
42
41
|
self, tokens=tokens, process_all=process_all, pwd=pwd
|
|
43
42
|
)
|
|
@@ -47,11 +47,14 @@ class CommandFList(CommandDesign):
|
|
|
47
47
|
'no-quote-path' : False,
|
|
48
48
|
'build-script' : "", # we don't want this to error either
|
|
49
49
|
|
|
50
|
-
'print-to-stdout': False,
|
|
50
|
+
'print-to-stdout': False,
|
|
51
51
|
|
|
52
52
|
# ex: eda flist --print-to-stdout --emit-rel-path --quiet <target>
|
|
53
53
|
'emit-rel-path' : False,
|
|
54
54
|
})
|
|
55
|
+
self.args_help.update({
|
|
56
|
+
'print-to-stdout': "do not save file, print to stdout",
|
|
57
|
+
})
|
|
55
58
|
|
|
56
59
|
def process_tokens(
|
|
57
60
|
self, tokens: list , process_all: bool = True, pwd: str = os.getcwd()
|
|
@@ -320,9 +320,10 @@ def process_tokens(tokens: list, original_args: list, config: dict, interactive=
|
|
|
320
320
|
for value in unparsed:
|
|
321
321
|
if value in config['DEFAULT_HANDLERS'].keys():
|
|
322
322
|
command = value
|
|
323
|
-
if value in config['
|
|
323
|
+
if not parsed.tool and value in config['command_tool_is_optional']:
|
|
324
|
+
# only do this if --tool was not set.
|
|
324
325
|
run_auto_tool_setup = False
|
|
325
|
-
unparsed.remove(value)
|
|
326
|
+
unparsed.remove(value) # remove command (flist, export, targets, etc)
|
|
326
327
|
break
|
|
327
328
|
|
|
328
329
|
if not interactive:
|
|
@@ -361,7 +362,7 @@ def process_tokens(tokens: list, original_args: list, config: dict, interactive=
|
|
|
361
362
|
util.debug(f'{type(sco)=}')
|
|
362
363
|
if not parsed.tool and \
|
|
363
364
|
command not in config.get('command_determines_tool', []) and \
|
|
364
|
-
command not in config.get('
|
|
365
|
+
command not in config.get('command_tool_is_optional', []):
|
|
365
366
|
use_tool = which_tool(command, config)
|
|
366
367
|
util.info(f"--tool not specified, using default for {command=}: {use_tool}")
|
|
367
368
|
|
|
@@ -686,6 +686,7 @@ class CommandDesign(Command):
|
|
|
686
686
|
self.files_sv = []
|
|
687
687
|
self.files_vhd = []
|
|
688
688
|
self.files_cpp = []
|
|
689
|
+
self.files_sdc = []
|
|
689
690
|
self.files_non_source = []
|
|
690
691
|
self.files_caller_info = {}
|
|
691
692
|
self.dep_shell_commands = [] # each list entry is a {}
|
|
@@ -760,7 +761,8 @@ class CommandDesign(Command):
|
|
|
760
761
|
self.files.pop(key)
|
|
761
762
|
self.files[new_key] = True
|
|
762
763
|
|
|
763
|
-
my_file_lists_list = [self.files_v, self.files_sv, self.files_vhd, self.files_cpp
|
|
764
|
+
my_file_lists_list = [self.files_v, self.files_sv, self.files_vhd, self.files_cpp,
|
|
765
|
+
self.files_sdc]
|
|
764
766
|
for my_file_list in my_file_lists_list:
|
|
765
767
|
for iter,value in enumerate(my_file_list):
|
|
766
768
|
if value and type(value) is str and value.startswith(self._work_dir_add_srcs_path_string):
|
|
@@ -1029,6 +1031,7 @@ class CommandDesign(Command):
|
|
|
1029
1031
|
sv_file_ext_list = known_file_ext_dict.get('systemverilog', [])
|
|
1030
1032
|
vhdl_file_ext_list = known_file_ext_dict.get('vhdl', [])
|
|
1031
1033
|
cpp_file_ext_list = known_file_ext_dict.get('cpp', [])
|
|
1034
|
+
sdc_file_ext_list = known_file_ext_dict.get('synth_constraints', [])
|
|
1032
1035
|
|
|
1033
1036
|
if forced_extension:
|
|
1034
1037
|
# If forced_extension='systemverilog', then use the first known extension for
|
|
@@ -1057,6 +1060,9 @@ class CommandDesign(Command):
|
|
|
1057
1060
|
elif file_ext in cpp_file_ext_list:
|
|
1058
1061
|
self.files_cpp.append(file_abspath)
|
|
1059
1062
|
util.debug("Added C++ file %s as %s" % (filename, file_abspath))
|
|
1063
|
+
elif file_ext in sdc_file_ext_list:
|
|
1064
|
+
self.files_sdc.append(file_abspath)
|
|
1065
|
+
util.debug("Added SDC file %s as %s" % (filename, file_abspath))
|
|
1060
1066
|
else:
|
|
1061
1067
|
# unknown file extension. In these cases we link the file to the working directory
|
|
1062
1068
|
# so it is available (for example, a .mem file that is expected to exist with relative path)
|
|
@@ -60,6 +60,9 @@ file_extensions:
|
|
|
60
60
|
- .vhdl
|
|
61
61
|
cpp:
|
|
62
62
|
- .cpp
|
|
63
|
+
synth_constraints:
|
|
64
|
+
- .sdc
|
|
65
|
+
- .xdc
|
|
63
66
|
|
|
64
67
|
inferred_top:
|
|
65
68
|
# file extensions that we can infer "top" module from, if --top omitted.
|
|
@@ -72,8 +75,9 @@ command_determines_tool:
|
|
|
72
75
|
# eda commands that will self-determine the tool to use
|
|
73
76
|
- waves
|
|
74
77
|
|
|
75
|
-
|
|
76
|
-
# eda commands that
|
|
78
|
+
command_tool_is_optional:
|
|
79
|
+
# eda commands that may not need to use a tool at all, will skip auto_tools_order if --tool=None (default)
|
|
80
|
+
- flist
|
|
77
81
|
- export
|
|
78
82
|
- targets
|
|
79
83
|
|
|
@@ -352,23 +352,25 @@ class ExportHelper:
|
|
|
352
352
|
}
|
|
353
353
|
}
|
|
354
354
|
|
|
355
|
-
|
|
355
|
+
|
|
356
|
+
if deps_file_args:
|
|
356
357
|
data[self.target]['args'] = deps_file_args.copy()
|
|
357
358
|
|
|
358
359
|
if self.args.get('top', None):
|
|
359
360
|
data[self.target]['top'] = self.args['top']
|
|
360
361
|
|
|
361
|
-
if
|
|
362
|
+
if self.cmd_design_obj.defines:
|
|
362
363
|
data[self.target]['defines'] = self.cmd_design_obj.defines.copy()
|
|
363
364
|
for define in _remove_DEPS_yml_defines:
|
|
364
365
|
# Remove defines keys for OC_ROOT and OC_SEED. Change OC_SEED to _ORIG_OC_SEED
|
|
365
366
|
if define in data[self.target]['defines']:
|
|
366
367
|
data[self.target]['defines'].pop(define)
|
|
367
368
|
|
|
368
|
-
|
|
369
|
+
reqs_fullpath_list = self.included_files + self.cmd_design_obj.files_non_source
|
|
370
|
+
if reqs_fullpath_list:
|
|
369
371
|
# Need to strip path information from non-source files:
|
|
370
372
|
data[self.target]['reqs'] = list()
|
|
371
|
-
for fullpath in
|
|
373
|
+
for fullpath in reqs_fullpath_list:
|
|
372
374
|
filename = os.path.split(fullpath)[1]
|
|
373
375
|
data[self.target]['reqs'].append(filename)
|
|
374
376
|
|
|
@@ -128,7 +128,7 @@ class Helpers:
|
|
|
128
128
|
'''Changes directory to self.DEFAULT_DIR and removes eda.work, eda.export paths'''
|
|
129
129
|
chdir_remove_work_dir('', self.DEFAULT_DIR)
|
|
130
130
|
|
|
131
|
-
def log_it(self, command_str:str, logfile=None, use_eda_wrap=True):
|
|
131
|
+
def log_it(self, command_str:str, logfile=None, use_eda_wrap=True) -> int:
|
|
132
132
|
'''Replacement for calling eda.main or eda_wrap, when you want an internal logfile
|
|
133
133
|
|
|
134
134
|
Usage:
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
'''pytests for: eda [multi|tools-multi] synth [args] <target(s)>'''
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
+
import shutil
|
|
5
|
+
|
|
4
6
|
import pytest
|
|
5
7
|
|
|
6
8
|
from opencos import eda, eda_tool_helper
|
|
7
9
|
from opencos.tests import helpers
|
|
10
|
+
from opencos.tests.helpers import Helpers
|
|
8
11
|
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
THISPATH = os.path.dirname(__file__)
|
|
11
14
|
|
|
12
15
|
def chdir_remove_work_dir(relpath):
|
|
13
16
|
'''Changes dir to relpath, removes the work directories (eda.work, eda.export*)'''
|
|
14
|
-
return helpers.chdir_remove_work_dir(
|
|
17
|
+
return helpers.chdir_remove_work_dir(THISPATH, relpath)
|
|
15
18
|
|
|
16
19
|
# Figure out what tools the system has available, without calling eda.main(..)
|
|
17
20
|
config, tools_loaded = eda_tool_helper.get_config_and_tools_loaded()
|
|
@@ -75,3 +78,61 @@ class Tests:
|
|
|
75
78
|
rc = eda.main(*cmdlist)
|
|
76
79
|
print(f'{rc=}')
|
|
77
80
|
assert rc == 0
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def vivado_has_xpms() -> bool:
|
|
84
|
+
'''Returns True if Vivado is installed and has visibility to XPMs'''
|
|
85
|
+
if 'vivado' not in tools_loaded:
|
|
86
|
+
return False
|
|
87
|
+
vivado_exe = shutil.which('vivado')
|
|
88
|
+
vivado_bin_path, _ = os.path.split(vivado_exe)
|
|
89
|
+
vivado_base_path, _ = os.path.split(vivado_bin_path) # strip bin/vivado
|
|
90
|
+
|
|
91
|
+
return os.path.exists(os.path.join(vivado_base_path, 'data', 'ip', 'xpm'))
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@pytest.mark.skipif(
|
|
95
|
+
'slang_yosys' not in tools_loaded, reason="requires slang_yosys for synth"
|
|
96
|
+
)
|
|
97
|
+
class TestsSlangYosys(Helpers):
|
|
98
|
+
'''Tests that require tool=slang_yosys to be available'''
|
|
99
|
+
|
|
100
|
+
def test_sdc_file(self):
|
|
101
|
+
'''Test for 'eda synth' on oclib_fifo_with_sdc
|
|
102
|
+
|
|
103
|
+
This does not use the actual .sdc file, but it also shouldn't fail with
|
|
104
|
+
that file in the 'deps' list (CommandDesign should track it correctly)
|
|
105
|
+
'''
|
|
106
|
+
chdir_remove_work_dir('deps_files/test_sdc_files')
|
|
107
|
+
cmd_str = 'synth --tool=slang_yosys oclib_fifo_with_sdc'
|
|
108
|
+
rc = self.log_it(cmd_str, use_eda_wrap=False)
|
|
109
|
+
assert rc == 0
|
|
110
|
+
|
|
111
|
+
@pytest.mark.skipif('vivado' not in tools_loaded, reason="requires vivado")
|
|
112
|
+
@pytest.mark.skipif(not vivado_has_xpms(), reason="requires install to have XPMs")
|
|
113
|
+
class TestsVivado(Helpers):
|
|
114
|
+
'''Tests that require tool=vivado with XPMs available for synthesis'''
|
|
115
|
+
|
|
116
|
+
def test_sdc_file(self):
|
|
117
|
+
'''Test for 'eda synth' on oclib_fifo_with_sdc
|
|
118
|
+
|
|
119
|
+
And check that the .sdc file was used and not the default generated .xdc
|
|
120
|
+
file
|
|
121
|
+
'''
|
|
122
|
+
chdir_remove_work_dir('deps_files/test_sdc_files')
|
|
123
|
+
cmd_str = 'synth --tool=vivado oclib_fifo_with_sdc'
|
|
124
|
+
rc = self.log_it(cmd_str, use_eda_wrap=False)
|
|
125
|
+
assert rc == 0
|
|
126
|
+
|
|
127
|
+
# apparently this doesn't get saved in the eda.log. That's not great,
|
|
128
|
+
# but we can check the <target>.synth.log file.
|
|
129
|
+
synth_log = os.path.join(
|
|
130
|
+
THISPATH, 'deps_files', 'test_sdc_files',
|
|
131
|
+
'eda.work', 'oclib_fifo_with_sdc.synth', 'oclib_fifo.synth.log'
|
|
132
|
+
)
|
|
133
|
+
sdc_lines = self.get_log_lines_with('.sdc', logfile=synth_log)
|
|
134
|
+
assert sdc_lines
|
|
135
|
+
for sdc_line in sdc_lines:
|
|
136
|
+
assert 'oclib_fifo_vivado.sdc' in sdc_line
|
|
137
|
+
assert 'test_sdc_files' in sdc_line
|
|
138
|
+
assert 'eda.work' not in sdc_line
|
|
@@ -37,7 +37,7 @@ class ToolIverilog(Tool):
|
|
|
37
37
|
iverilog_version_ret = subprocess.run(
|
|
38
38
|
[self.iverilog_exe, '-v'], capture_output=True, check=False
|
|
39
39
|
)
|
|
40
|
-
lines = iverilog_version_ret.stdout.decode("utf-8").split('\n')
|
|
40
|
+
lines = iverilog_version_ret.stdout.decode("utf-8", errors="replace").split('\n')
|
|
41
41
|
words = lines[0].split() # 'Icarus Verilog version 13.0 (devel) (s20221226-568-g62727e8b2)'
|
|
42
42
|
version = words[3]
|
|
43
43
|
util.debug(f'{iverilog_path=} {lines[0]=}')
|
|
@@ -36,7 +36,7 @@ class ToolRiviera(ToolModelsimAse):
|
|
|
36
36
|
capture_output=True,
|
|
37
37
|
check=False
|
|
38
38
|
)
|
|
39
|
-
stdout = version_ret.stdout.decode('utf-8').rstrip()
|
|
39
|
+
stdout = version_ret.stdout.decode('utf-8', errors='replace').rstrip()
|
|
40
40
|
|
|
41
41
|
# Expect:
|
|
42
42
|
# Aldec, Inc. Riviera-PRO version 2025.04.139.9738 built for Linux64 on May 30, 2025
|
|
@@ -44,7 +44,7 @@ class ToolSlang(Tool):
|
|
|
44
44
|
capture_output=True,
|
|
45
45
|
check=False
|
|
46
46
|
)
|
|
47
|
-
stdout = version_ret.stdout.decode('utf-8')
|
|
47
|
+
stdout = version_ret.stdout.decode('utf-8', errors='replace')
|
|
48
48
|
util.debug(f'{path=} {version_ret=}')
|
|
49
49
|
words = stdout.split() # slang version 8.0.6+b4a74b00
|
|
50
50
|
if len(words) < 3:
|
|
@@ -33,7 +33,7 @@ class ToolSurelog(Tool):
|
|
|
33
33
|
version_ret = subprocess.run(
|
|
34
34
|
[self.surelog_exe, '--version'], capture_output=True, check=False
|
|
35
35
|
)
|
|
36
|
-
stdout = version_ret.stdout.decode('utf-8')
|
|
36
|
+
stdout = version_ret.stdout.decode('utf-8', errors='replace')
|
|
37
37
|
util.debug(f'{path=} {version_ret=}')
|
|
38
38
|
words = stdout.split() # VERSION: 1.84 (first line)
|
|
39
39
|
if len(words) < 2:
|
|
@@ -49,7 +49,7 @@ class ToolVerilator(Tool):
|
|
|
49
49
|
capture_output=True,
|
|
50
50
|
check=False
|
|
51
51
|
)
|
|
52
|
-
stdout = version_ret.stdout.decode('utf-8')
|
|
52
|
+
stdout = version_ret.stdout.decode('utf-8', errors='replace')
|
|
53
53
|
util.debug(f'{path=} {version_ret=}')
|
|
54
54
|
words = stdout.split() # 'Verilator 5.027 devel rev v5.026-92-g403a197e2
|
|
55
55
|
if len(words) < 1:
|
|
@@ -70,7 +70,7 @@ class ToolVivado(Tool):
|
|
|
70
70
|
#try:
|
|
71
71
|
# # Get version from vivado -version, or xsim --version:
|
|
72
72
|
# vivado_ret = subprocess.run(['vivado', '-version'], capture_output=True)
|
|
73
|
-
# lines = vivado_ret.stdout.decode('utf-8').split('\n')
|
|
73
|
+
# lines = vivado_ret.stdout.decode('utf-8', errors='replace').split('\n')
|
|
74
74
|
# words = lines[0].split() # vivado v2024.2.1 (64-bit)
|
|
75
75
|
# version = words[1][1:] # 2024.2.1
|
|
76
76
|
# self._VERSION = version
|
|
@@ -388,9 +388,14 @@ class CommandSynthVivado(CommandSynth, ToolVivado):
|
|
|
388
388
|
self.exec(self.args['work-dir'], command_list)
|
|
389
389
|
|
|
390
390
|
|
|
391
|
-
def write_tcl_file(
|
|
391
|
+
def write_tcl_file( # pylint: disable=too-many-locals,too-many-branches
|
|
392
|
+
self, tcl_file: str
|
|
393
|
+
) -> None:
|
|
392
394
|
'''Writes synthesis capable Vivado tcl file to filepath 'tcl_file'.'''
|
|
393
395
|
|
|
396
|
+
# TODO(drew): This method needs to be broken up to avoid the pylint
|
|
397
|
+
# waivers.
|
|
398
|
+
|
|
394
399
|
v = self.get_vivado_tcl_verbose_arg()
|
|
395
400
|
|
|
396
401
|
defines = ""
|
|
@@ -416,9 +421,12 @@ class CommandSynthVivado(CommandSynth, ToolVivado):
|
|
|
416
421
|
part = self.args['part']
|
|
417
422
|
top = self.args['top']
|
|
418
423
|
|
|
424
|
+
default_xdc = False
|
|
419
425
|
if self.args['xdc'] != "":
|
|
420
|
-
default_xdc = False
|
|
421
426
|
xdc_file = os.path.abspath(self.args['xdc'])
|
|
427
|
+
elif self.files_sdc:
|
|
428
|
+
# Use files from DEPS target or command line.
|
|
429
|
+
xdc_file = ''
|
|
422
430
|
else:
|
|
423
431
|
default_xdc = True
|
|
424
432
|
xdc_file = os.path.abspath(os.path.join(self.args['work-dir'],
|
|
@@ -427,7 +435,17 @@ class CommandSynthVivado(CommandSynth, ToolVivado):
|
|
|
427
435
|
|
|
428
436
|
tcl_lines += [
|
|
429
437
|
f"create_fileset -constrset constraints_1 {v}",
|
|
430
|
-
|
|
438
|
+
]
|
|
439
|
+
for _file in self.files_sdc:
|
|
440
|
+
# NOTE - sdc files cannot (yet) be attached to other modules.
|
|
441
|
+
tcl_lines += [
|
|
442
|
+
f"add_files -fileset constraints_1 {_file} {v}",
|
|
443
|
+
]
|
|
444
|
+
if xdc_file:
|
|
445
|
+
tcl_lines += [
|
|
446
|
+
f"add_files -fileset constraints_1 {xdc_file} {v}",
|
|
447
|
+
]
|
|
448
|
+
tcl_lines += [
|
|
431
449
|
"# FIRST PASS -- auto_detect_xpm",
|
|
432
450
|
"synth_design -rtl -rtl_skip_ip -rtl_skip_constraints -no_timing_driven -no_iobuf " \
|
|
433
451
|
+ f"-top {top} {incdirs} {defines} {v}",
|
|
@@ -46,7 +46,7 @@ class ToolYosys(Tool):
|
|
|
46
46
|
[self.sta_exe, '-version'], capture_output=True, check=False
|
|
47
47
|
)
|
|
48
48
|
util.debug(f'{self.yosys_exe} {sta_version_ret=}')
|
|
49
|
-
sta_ver = sta_version_ret.stdout.decode('utf-8').split()[0]
|
|
49
|
+
sta_ver = sta_version_ret.stdout.decode('utf-8', errors='replace').split()[0]
|
|
50
50
|
if sta_ver:
|
|
51
51
|
self.sta_version = sta_ver
|
|
52
52
|
|
|
@@ -56,7 +56,7 @@ class ToolYosys(Tool):
|
|
|
56
56
|
util.debug(f'{self.yosys_exe} {version_ret=}')
|
|
57
57
|
|
|
58
58
|
# Yosys 0.48 (git sha1 aaa534749, clang++ 14.0.0-1ubuntu1.1 -fPIC -O3)
|
|
59
|
-
words = version_ret.stdout.decode('utf-8').split()
|
|
59
|
+
words = version_ret.stdout.decode('utf-8', errors='replace').split()
|
|
60
60
|
|
|
61
61
|
if len(words) < 2:
|
|
62
62
|
self.error(f'{self.yosys_exe} --version: returned unexpected str {version_ret=}')
|
|
@@ -93,16 +93,27 @@ class CommonSynthYosys(CommandSynth, ToolYosys):
|
|
|
93
93
|
'yosys-blackbox': [], # list of modules that yosys will blackbox.
|
|
94
94
|
})
|
|
95
95
|
self.args_help.update({
|
|
96
|
-
'sta':
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
96
|
+
'sta': (
|
|
97
|
+
'After running Yosys, run "sta" with --liberty-file.'
|
|
98
|
+
' sta can be installed via: https://github.com/The-OpenROAD-Project/OpenSTA'
|
|
99
|
+
),
|
|
100
|
+
'sdc-file': (
|
|
101
|
+
'.sdc file to use with --sta, if not present will use auto constraints.'
|
|
102
|
+
' Note you can have .sdc files in "deps" of DEPS.yml targets.'
|
|
103
|
+
),
|
|
104
|
+
'liberty-file': (
|
|
105
|
+
'Single liberty file for synthesis and sta,'
|
|
106
|
+
' for example: github/OpenSTA/examples/nangate45_slow.lib.gz'
|
|
107
|
+
),
|
|
101
108
|
'yosys-synth': 'The synth command provided to Yosys, see: yosys help.',
|
|
102
|
-
'yosys-pre-synth':
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
109
|
+
'yosys-pre-synth': (
|
|
110
|
+
'Yosys commands performed prior to running "synth"'
|
|
111
|
+
' (or eda arg value for --yosys-synth)'
|
|
112
|
+
),
|
|
113
|
+
'yosys-blackbox': (
|
|
114
|
+
'List of modules that yosys will blackbox, likely will need these'
|
|
115
|
+
' in Verilog-2001 for yosys to read outside of slang and synth'
|
|
116
|
+
),
|
|
106
117
|
})
|
|
107
118
|
|
|
108
119
|
self.yosys_out_dir = ''
|
|
@@ -193,6 +204,9 @@ class CommonSynthYosys(CommandSynth, ToolYosys):
|
|
|
193
204
|
# Need to create sta.f:
|
|
194
205
|
if self.args['sdc-file']:
|
|
195
206
|
sdc_path = self.args['sdc-file']
|
|
207
|
+
elif self.files_sdc:
|
|
208
|
+
# Use files from DEPS target or command line.
|
|
209
|
+
sdc_path = ''
|
|
196
210
|
else:
|
|
197
211
|
# Need to create sdc.f:
|
|
198
212
|
sdc_path = 'sdc.f'
|
|
@@ -204,9 +218,14 @@ class CommonSynthYosys(CommandSynth, ToolYosys):
|
|
|
204
218
|
'read_liberty ' + self.args['liberty-file'],
|
|
205
219
|
'read_verilog ' + self.yosys_v_path,
|
|
206
220
|
'link_design ' + self.args['top'],
|
|
207
|
-
'read_sdc ' + sdc_path,
|
|
208
|
-
'report_checks',
|
|
209
221
|
]
|
|
222
|
+
for _file in self.files_sdc:
|
|
223
|
+
lines.append('read_sdc ' + _file)
|
|
224
|
+
if sdc_path:
|
|
225
|
+
lines.append('read_sdc ' + sdc_path)
|
|
226
|
+
|
|
227
|
+
lines.append('report_checks')
|
|
228
|
+
|
|
210
229
|
f.write('\n'.join(lines))
|
|
211
230
|
|
|
212
231
|
return util.ShellCommandList(
|
|
@@ -33,11 +33,10 @@ args = {
|
|
|
33
33
|
'errors' : 0,
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
def strip_all_quotes(s:str):
|
|
36
|
+
def strip_all_quotes(s: str) -> str:
|
|
38
37
|
return s.replace("'", '').replace('"', '')
|
|
39
38
|
|
|
40
|
-
def strip_outer_quotes(s:str):
|
|
39
|
+
def strip_outer_quotes(s: str) -> str:
|
|
41
40
|
ret = str(s)
|
|
42
41
|
while (ret.startswith("'") and ret.endswith("'")) or \
|
|
43
42
|
(ret.startswith('"') and ret.endswith('"')):
|
|
@@ -732,7 +731,7 @@ def subprocess_run_background(work_dir, command_list, background=True, fake:bool
|
|
|
732
731
|
stderr = ''
|
|
733
732
|
with open(tee_fpath, 'w') as f:
|
|
734
733
|
for line in iter(proc.stdout.readline, b''):
|
|
735
|
-
line = line.rstrip().decode("utf-8")
|
|
734
|
+
line = line.rstrip().decode("utf-8", errors="replace")
|
|
736
735
|
if not background:
|
|
737
736
|
print(line)
|
|
738
737
|
f.write(line + '\n')
|
|
@@ -749,8 +748,8 @@ def subprocess_run_background(work_dir, command_list, background=True, fake:bool
|
|
|
749
748
|
stdout, stderr = proc.communicate()
|
|
750
749
|
rc = proc.returncode
|
|
751
750
|
|
|
752
|
-
stdout = stdout.decode('utf-8') if stdout else ""
|
|
753
|
-
stderr = stderr.decode('utf-8') if stderr else ""
|
|
751
|
+
stdout = stdout.decode('utf-8', errors="replace") if stdout else ""
|
|
752
|
+
stderr = stderr.decode('utf-8', errors="replace") if stderr else ""
|
|
754
753
|
debug(f"shell_run_background: {rc=}")
|
|
755
754
|
if stdout:
|
|
756
755
|
for lineno, line in enumerate(stdout.strip().split('\n')):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opencos-eda
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.44
|
|
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
|