opencos-eda 0.2.51__tar.gz → 0.2.52__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.51/opencos_eda.egg-info → opencos_eda-0.2.52}/PKG-INFO +2 -1
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/commands/waves.py +12 -2
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/eda.py +16 -3
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/eda_config.py +1 -1
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/eda_config_defaults.yml +34 -0
- opencos_eda-0.2.52/opencos/tests/test_tools.py +350 -0
- opencos_eda-0.2.52/opencos/tools/cocotb.py +483 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tools/verilator.py +31 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/util.py +2 -0
- opencos_eda-0.2.52/opencos/utils/vscode_helper.py +47 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52/opencos_eda.egg-info}/PKG-INFO +2 -1
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos_eda.egg-info/SOURCES.txt +2 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos_eda.egg-info/requires.txt +1 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/pyproject.toml +2 -1
- opencos_eda-0.2.51/opencos/tests/test_tools.py +0 -156
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/LICENSE +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/LICENSE.spdx +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/README.md +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/__init__.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/_version.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/_waves_pkg.sv +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/commands/__init__.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/commands/build.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/commands/elab.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/commands/export.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/commands/flist.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/commands/lec.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/commands/multi.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/commands/open.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/commands/proj.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/commands/shell.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/commands/sim.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/commands/sweep.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/commands/synth.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/commands/targets.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/commands/upload.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/deps/__init__.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/deps/defaults.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/deps/deps_commands.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/deps/deps_file.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/deps/deps_processor.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/deps_schema.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/eda_base.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/eda_config_max_verilator_waivers.yml +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/eda_config_reduced.yml +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/eda_deps_bash_completion.bash +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/eda_deps_sanitize.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/eda_extract_targets.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/eda_tool_helper.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/export_helper.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/export_json_convert.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/files.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/hw/__init__.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/hw/oc_cli.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/hw/pcie.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/names.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/peakrdl_cleanup.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/seed.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tests/__init__.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tests/custom_config.yml +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tests/deps_files/command_order/DEPS.yml +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tests/deps_files/error_msgs/DEPS.yml +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tests/deps_files/iverilog_test/DEPS.yml +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tests/deps_files/no_deps_here/DEPS.yml +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tests/deps_files/non_sv_reqs/DEPS.yml +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tests/deps_files/tags_with_tools/DEPS.yml +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tests/deps_files/test_err_fatal/DEPS.yml +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tests/helpers.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tests/test_build.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tests/test_deps_helpers.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tests/test_deps_schema.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tests/test_eda.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tests/test_eda_elab.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tests/test_eda_synth.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tests/test_oc_cli.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tools/__init__.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tools/invio.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tools/invio_helpers.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tools/invio_yosys.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tools/iverilog.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tools/modelsim_ase.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tools/questa.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tools/questa_fse.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tools/riviera.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tools/slang.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tools/slang_yosys.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tools/surelog.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tools/tabbycad_yosys.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tools/vivado.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/tools/yosys.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/utils/__init__.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/utils/markup_helpers.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/utils/status_constants.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/utils/str_helpers.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/utils/subprocess_helpers.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos/utils/vsim_helper.py +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos_eda.egg-info/dependency_links.txt +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos_eda.egg-info/entry_points.txt +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/opencos_eda.egg-info/top_level.txt +0 -0
- {opencos_eda-0.2.51 → opencos_eda-0.2.52}/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.52
|
|
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,4 +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.0b1
|
|
18
19
|
Dynamic: license-file
|
|
@@ -32,6 +32,8 @@ class CommandWaves(CommandDesign):
|
|
|
32
32
|
|
|
33
33
|
VSIM_TOOLS = set([
|
|
34
34
|
'questa',
|
|
35
|
+
'questa_fse',
|
|
36
|
+
'riviera',
|
|
35
37
|
'modelsim_ase',
|
|
36
38
|
])
|
|
37
39
|
|
|
@@ -137,13 +139,21 @@ class CommandWaves(CommandDesign):
|
|
|
137
139
|
self.error(f"Don't know how to open {wave_file} without one of",
|
|
138
140
|
f"{self.VSIM_TOOLS} in PATH")
|
|
139
141
|
elif wave_file.endswith('.fst'):
|
|
140
|
-
if '
|
|
142
|
+
if ('vaporview' in self.config['tools_loaded'] or \
|
|
143
|
+
'surfer' in self.config['tools_loaded']) and shutil.which('code'):
|
|
144
|
+
command_list = ['code', '-n', '.', wave_file]
|
|
145
|
+
self.exec(os.path.dirname(wave_file), command_list)
|
|
146
|
+
elif 'gtkwave' in self.config['tools_loaded'] and shutil.which('gtkwave'):
|
|
141
147
|
command_list = ['gtkwave', wave_file]
|
|
142
148
|
self.exec(os.path.dirname(wave_file), command_list)
|
|
143
149
|
else:
|
|
144
150
|
self.error(f"Don't know how to open {wave_file} without GtkWave in PATH")
|
|
145
151
|
elif wave_file.endswith('.vcd'):
|
|
146
|
-
if '
|
|
152
|
+
if ('vaporview' in self.config['tools_loaded'] or \
|
|
153
|
+
'surfer' in self.config['tools_loaded']) and shutil.which('code'):
|
|
154
|
+
command_list = ['code', '-n', '.', wave_file]
|
|
155
|
+
self.exec(os.path.dirname(wave_file), command_list)
|
|
156
|
+
elif 'gtkwave' in self.config['tools_loaded'] and shutil.which('gtkwave'):
|
|
147
157
|
command_list = ['gtkwave', wave_file]
|
|
148
158
|
self.exec(os.path.dirname(wave_file), command_list)
|
|
149
159
|
elif self._vsim_available(from_tools=self.VSIM_VCD_TOOLS):
|
|
@@ -21,7 +21,7 @@ from pathlib import Path
|
|
|
21
21
|
import opencos
|
|
22
22
|
from opencos import util, eda_config, eda_base
|
|
23
23
|
from opencos.eda_base import Tool, which_tool
|
|
24
|
-
from opencos.utils import vsim_helper
|
|
24
|
+
from opencos.utils import vsim_helper, vscode_helper
|
|
25
25
|
|
|
26
26
|
# Configure util:
|
|
27
27
|
util.progname = "EDA"
|
|
@@ -213,6 +213,19 @@ def auto_tool_setup( # pylint: disable=too-many-locals,too-many-branches,too-man
|
|
|
213
213
|
vsim_helper.init() # only runs checks once internally
|
|
214
214
|
has_vsim_helper = vsim_helper.TOOL_IS.get(name, False)
|
|
215
215
|
|
|
216
|
+
has_vscode_helper = True
|
|
217
|
+
needs_vscode_extensions = value.get('requires_vscode_extension', None)
|
|
218
|
+
if needs_vscode_extensions:
|
|
219
|
+
if not isinstance(needs_vscode_extensions, list):
|
|
220
|
+
util.error(
|
|
221
|
+
f'eda config issue, tool {name}: requires_vscode_extension must be a list'
|
|
222
|
+
)
|
|
223
|
+
else:
|
|
224
|
+
vscode_helper.init() # only runs checks once internally
|
|
225
|
+
has_vscode_helper = all(
|
|
226
|
+
x in vscode_helper.EXTENSIONS for x in needs_vscode_extensions
|
|
227
|
+
)
|
|
228
|
+
|
|
216
229
|
if has_all_exe:
|
|
217
230
|
requires_cmd_list = value.get('requires_cmd', [])
|
|
218
231
|
for cmd in requires_cmd_list:
|
|
@@ -230,8 +243,8 @@ def auto_tool_setup( # pylint: disable=too-many-locals,too-many-branches,too-man
|
|
|
230
243
|
util.debug(f"... No, exception {e} running {cmd_list}")
|
|
231
244
|
|
|
232
245
|
|
|
233
|
-
if all(
|
|
234
|
-
has_vsim_helper
|
|
246
|
+
if all((has_all_py, has_all_env, has_all_exe, has_all_in_exe_path,
|
|
247
|
+
has_vsim_helper, has_vscode_helper)):
|
|
235
248
|
exe = exe_list[0]
|
|
236
249
|
p = shutil.which(exe)
|
|
237
250
|
config['auto_tools_found'][name] = exe # populate key-value pairs w/ first exe in list
|
|
@@ -46,7 +46,7 @@ class Defaults:
|
|
|
46
46
|
supported_config_auto_tools_order_keys = set([
|
|
47
47
|
'exe', 'handlers',
|
|
48
48
|
'requires_env', 'requires_py', 'requires_cmd', 'requires_in_exe_path',
|
|
49
|
-
'requires_vsim_helper',
|
|
49
|
+
'requires_vsim_helper', 'requires_vscode_extension',
|
|
50
50
|
'disable-tools-multi',
|
|
51
51
|
])
|
|
52
52
|
supported_config_tool_keys = set([
|
|
@@ -280,6 +280,20 @@ tools:
|
|
|
280
280
|
simulate-waves-args: |
|
|
281
281
|
+trace
|
|
282
282
|
|
|
283
|
+
cocotb:
|
|
284
|
+
defines:
|
|
285
|
+
OC_TOOL_COCOTB: null
|
|
286
|
+
log-bad-strings:
|
|
287
|
+
- "ERROR"
|
|
288
|
+
- "FAILED"
|
|
289
|
+
- "AssertionError"
|
|
290
|
+
- "Exception"
|
|
291
|
+
- "Traceback"
|
|
292
|
+
- "COCOTB_TEST_FAILED"
|
|
293
|
+
log-must-strings:
|
|
294
|
+
- "passed"
|
|
295
|
+
- "Cocotb test completed successfully!"
|
|
296
|
+
|
|
283
297
|
|
|
284
298
|
vivado:
|
|
285
299
|
sim-libraries:
|
|
@@ -345,6 +359,17 @@ auto_tools_order:
|
|
|
345
359
|
handlers:
|
|
346
360
|
elab: opencos.tools.invio.CommandElabInvio
|
|
347
361
|
|
|
362
|
+
vaporview:
|
|
363
|
+
exe: code
|
|
364
|
+
requires_vscode_extension:
|
|
365
|
+
- lramseyer.vaporview
|
|
366
|
+
handlers: { }
|
|
367
|
+
|
|
368
|
+
surfer:
|
|
369
|
+
exe: code
|
|
370
|
+
requires_vscode_extension:
|
|
371
|
+
- surfer-project.surfer
|
|
372
|
+
handlers: { }
|
|
348
373
|
|
|
349
374
|
gtkwave:
|
|
350
375
|
exe: gtkwave
|
|
@@ -431,3 +456,12 @@ auto_tools_order:
|
|
|
431
456
|
handlers:
|
|
432
457
|
elab: opencos.tools.iverilog.CommandElabIverilog
|
|
433
458
|
sim: opencos.tools.iverilog.CommandSimIverilog
|
|
459
|
+
|
|
460
|
+
cocotb:
|
|
461
|
+
exe: python
|
|
462
|
+
requires_cmd:
|
|
463
|
+
- python -c "import cocotb; print(cocotb.__version__)"
|
|
464
|
+
requires_py:
|
|
465
|
+
- cocotb
|
|
466
|
+
handlers:
|
|
467
|
+
sim: opencos.tools.cocotb.CommandSimCocotb
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
'''pytests for testing a few different tools within opencos.eda'''
|
|
2
|
+
|
|
3
|
+
# pylint: disable=R0801 # (similar lines in 2+ files)
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from opencos import eda, eda_tool_helper, eda_base
|
|
10
|
+
|
|
11
|
+
from opencos.tools.verilator import ToolVerilator
|
|
12
|
+
from opencos.tools.vivado import ToolVivado
|
|
13
|
+
from opencos.tools.cocotb import ToolCocotb
|
|
14
|
+
from opencos.tests import helpers
|
|
15
|
+
from opencos.tests.helpers import eda_wrap
|
|
16
|
+
from opencos.utils.markup_helpers import yaml_safe_load
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
thispath = os.path.dirname(__file__)
|
|
20
|
+
|
|
21
|
+
def chdir_remove_work_dir(relpath):
|
|
22
|
+
'''Changes dir to relpath, removes the work directories (eda.work, eda.export*)'''
|
|
23
|
+
return helpers.chdir_remove_work_dir(thispath, relpath)
|
|
24
|
+
|
|
25
|
+
# Figure out what tools the system has available, without calling eda.main(..)
|
|
26
|
+
config, tools_loaded = eda_tool_helper.get_config_and_tools_loaded()
|
|
27
|
+
|
|
28
|
+
def test_tools_loaded():
|
|
29
|
+
'''Does not directly call 'eda.main' instead create a few Tool
|
|
30
|
+
|
|
31
|
+
class objects and confirm the versioning methods work.
|
|
32
|
+
'''
|
|
33
|
+
assert config
|
|
34
|
+
assert len(config.keys()) > 0
|
|
35
|
+
|
|
36
|
+
# It's possible we're running in some container or install that has no tools, for example,
|
|
37
|
+
# Windows.
|
|
38
|
+
if sys.platform.startswith('win') and \
|
|
39
|
+
not helpers.can_run_eda_command('elab', 'sim', config=config):
|
|
40
|
+
# Windows, not handlers for elab or sim:
|
|
41
|
+
pass
|
|
42
|
+
else:
|
|
43
|
+
assert len(tools_loaded) > 0
|
|
44
|
+
|
|
45
|
+
def version_checker(
|
|
46
|
+
obj: eda_base.Tool, chk_str: str
|
|
47
|
+
) -> None:
|
|
48
|
+
assert obj.get_versions()
|
|
49
|
+
full_ver = obj.get_full_tool_and_versions()
|
|
50
|
+
assert chk_str in full_ver, f'{chk_str=} not in {full_ver=}'
|
|
51
|
+
ver_num = full_ver.rsplit(':', maxsplit=1)[-1]
|
|
52
|
+
if 'b' in ver_num:
|
|
53
|
+
ver_num = ver_num.split('b')[0] # TODO(chaitanya): remove once cocotb 2.0 is released
|
|
54
|
+
if '.' in ver_num:
|
|
55
|
+
major_ver = ver_num.split('.')[0]
|
|
56
|
+
assert major_ver.isdigit(), (
|
|
57
|
+
f'Major version {major_ver=} is not a digit, from {full_ver=}'
|
|
58
|
+
)
|
|
59
|
+
assert float(major_ver) >= 0, (
|
|
60
|
+
f'{major_ver=} is not a valid version number, from {full_ver=}'
|
|
61
|
+
)
|
|
62
|
+
else:
|
|
63
|
+
assert float(ver_num), f'{ver_num=} is not a float, from {full_ver=}'
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# Do some very crude checks on the eda.Tool methods, and make
|
|
67
|
+
# sure versions work for Verilator and Vivado:
|
|
68
|
+
if 'verilator' in tools_loaded:
|
|
69
|
+
my_tool = ToolVerilator(config={})
|
|
70
|
+
version_checker(obj=my_tool, chk_str='verilator:')
|
|
71
|
+
|
|
72
|
+
if 'vivado' in tools_loaded:
|
|
73
|
+
my_tool = ToolVivado(config={})
|
|
74
|
+
version_checker(obj=my_tool, chk_str='vivado:')
|
|
75
|
+
|
|
76
|
+
if 'cocotb' in tools_loaded:
|
|
77
|
+
my_tool = ToolCocotb(config={})
|
|
78
|
+
version_checker(obj=my_tool, chk_str='cocotb:')
|
|
79
|
+
|
|
80
|
+
# Run these on simulation tools.
|
|
81
|
+
list_of_commands = [
|
|
82
|
+
'sim',
|
|
83
|
+
'elab'
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
list_of_tools = [
|
|
87
|
+
'iverilog',
|
|
88
|
+
'verilator',
|
|
89
|
+
'vivado',
|
|
90
|
+
'modelsim_ase',
|
|
91
|
+
'questa_fse',
|
|
92
|
+
]
|
|
93
|
+
|
|
94
|
+
list_of_deps_targets = [
|
|
95
|
+
('tb_no_errs', True), # target:str, sim_expect_pass:bool (sim only, all elab should pass)
|
|
96
|
+
('tb_dollar_fatal', False),
|
|
97
|
+
('tb_dollar_err', False),
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
cannot_use_cocotb = 'cocotb' not in tools_loaded or \
|
|
101
|
+
('iverilog' not in tools_loaded and \
|
|
102
|
+
'verilator' not in tools_loaded)
|
|
103
|
+
CANNOT_USE_COCOTB_REASON = 'requires cocotb in tools_loaded, and one of (iverilog, verilator) too'
|
|
104
|
+
|
|
105
|
+
@pytest.mark.parametrize("command", list_of_commands)
|
|
106
|
+
@pytest.mark.parametrize("tool", list_of_tools)
|
|
107
|
+
@pytest.mark.parametrize("target,sim_expect_pass", list_of_deps_targets)
|
|
108
|
+
def test_err_fatal(command, tool, target, sim_expect_pass):
|
|
109
|
+
'''tests that: eda <sim|elab> --tool <parameter-tool> <parameter-target>
|
|
110
|
+
|
|
111
|
+
will correctly pass or fail depending on if it is supported or not.
|
|
112
|
+
'''
|
|
113
|
+
if tool not in tools_loaded:
|
|
114
|
+
pytest.skip(f"{tool=} skipped, {tools_loaded=}")
|
|
115
|
+
return # skip/pass
|
|
116
|
+
|
|
117
|
+
relative_dir = "deps_files/test_err_fatal"
|
|
118
|
+
os.chdir(os.path.join(thispath, relative_dir))
|
|
119
|
+
rc = eda.main(command, '--tool', tool, target)
|
|
120
|
+
print(f'{rc=}')
|
|
121
|
+
if command != 'sim' or sim_expect_pass:
|
|
122
|
+
# command='elab' should pass.
|
|
123
|
+
assert rc == 0
|
|
124
|
+
else:
|
|
125
|
+
assert rc > 0
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@pytest.mark.skipif('vivado' not in tools_loaded, reason="requires vivado")
|
|
129
|
+
def test_vivado_tool_defines():
|
|
130
|
+
'''This test attempts to confirm that the following class inheritance works:
|
|
131
|
+
|
|
132
|
+
Command <- CommandDesign <- CommandSim <- CommandSimVivado <- CommandElabVivado
|
|
133
|
+
|
|
134
|
+
in particular that CommandElabVivado(CommandSimVivado, ToolVivado) has the
|
|
135
|
+
correct ToolVivado.set_tool_defines() method, and that no other parent Command
|
|
136
|
+
class has overriden it to defeat the defines that should be set.
|
|
137
|
+
|
|
138
|
+
We also run with an added dependency (lib_ultrascale_plus_defines) to check that
|
|
139
|
+
defines are set as expected.
|
|
140
|
+
'''
|
|
141
|
+
|
|
142
|
+
chdir_remove_work_dir('../../lib')
|
|
143
|
+
rc = eda_wrap(
|
|
144
|
+
'elab', '--tool', 'vivado', 'third_party/vendors/xilinx/lib_ultrascale_plus_defines',
|
|
145
|
+
'oclib_fifo'
|
|
146
|
+
)
|
|
147
|
+
assert rc == 0
|
|
148
|
+
|
|
149
|
+
# Confirm that args and defines we expected to be set are set.
|
|
150
|
+
eda_config_yml_path = os.path.join(
|
|
151
|
+
os.getcwd(), 'eda.work', 'oclib_fifo.elab', 'eda_output_config.yml'
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
data = yaml_safe_load(eda_config_yml_path)
|
|
155
|
+
assert 'args' in data
|
|
156
|
+
assert data['args'].get('top', '') == 'oclib_fifo'
|
|
157
|
+
assert 'config' in data
|
|
158
|
+
assert 'eda_original_args' in data['config']
|
|
159
|
+
assert 'oclib_fifo' in data['config']['eda_original_args']
|
|
160
|
+
assert data.get('target', '') == 'oclib_fifo'
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
# This checks opencos.tools.vivado.ToolVivado.set_tool_defines():
|
|
164
|
+
# We ran with --xilinx, so we expect certain defines to be set, others not to be set.
|
|
165
|
+
assert 'defines' in data
|
|
166
|
+
|
|
167
|
+
assert 'OC_TOOL_VIVADO' in data['defines']
|
|
168
|
+
assert 'OC_LIBRARY' in data['defines']
|
|
169
|
+
assert 'OC_LIBRARY_ULTRASCALE_PLUS' in data['defines']
|
|
170
|
+
|
|
171
|
+
assert 'OC_LIBRARY_BEHAVIORAL' not in data['defines']
|
|
172
|
+
assert 'VERILATOR' not in data['defines']
|
|
173
|
+
assert 'SYNTHESIS' not in data['defines']
|
|
174
|
+
|
|
175
|
+
assert data['defines']['OC_LIBRARY'] == '1'
|
|
176
|
+
assert data['defines']['OC_LIBRARY_ULTRASCALE_PLUS'] is None # key present, no value
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
@pytest.mark.skipif(cannot_use_cocotb, reason=CANNOT_USE_COCOTB_REASON)
|
|
180
|
+
def test_cocotb_tool_defines():
|
|
181
|
+
'''Test cocotb tool defines, configs, and integration.'''
|
|
182
|
+
|
|
183
|
+
chdir_remove_work_dir('../../examples/cocotb')
|
|
184
|
+
|
|
185
|
+
# Test 0: Using eda multi:
|
|
186
|
+
rc = eda_wrap('multi', 'sim', '--tool=cocotb', '*test')
|
|
187
|
+
assert rc == 0
|
|
188
|
+
|
|
189
|
+
# Test 1: basic cocotb sim command with Python runner (default)
|
|
190
|
+
rc = eda_wrap('sim', '--tool', 'cocotb', 'cocotb_counter_test')
|
|
191
|
+
assert rc == 0
|
|
192
|
+
|
|
193
|
+
# Test 2: cocotb works with different simulators/configurations
|
|
194
|
+
rc = eda_wrap('sim', '--tool', 'cocotb', 'cocotb_counter_waves_test')
|
|
195
|
+
assert rc == 0
|
|
196
|
+
|
|
197
|
+
# Test 3: Makefile approach
|
|
198
|
+
rc = eda_wrap('sim', '--tool', 'cocotb', 'cocotb_counter_makefile_test')
|
|
199
|
+
assert rc == 0
|
|
200
|
+
|
|
201
|
+
# Test 4: cocotb-specific defines are set correctly
|
|
202
|
+
eda_config_yml_path = os.path.join(
|
|
203
|
+
os.getcwd(), 'eda.work', 'cocotb_counter_test.sim', 'eda_output_config.yml'
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
data = yaml_safe_load(eda_config_yml_path)
|
|
207
|
+
assert 'args' in data
|
|
208
|
+
assert data['args'].get('top', '') == 'counter'
|
|
209
|
+
assert 'config' in data
|
|
210
|
+
assert 'eda_original_args' in data['config']
|
|
211
|
+
assert 'cocotb_counter_test' in data['config']['eda_original_args'] or \
|
|
212
|
+
'./cocotb_counter_test' in data['config']['eda_original_args']
|
|
213
|
+
assert data.get('target', '') == 'cocotb_counter_test'
|
|
214
|
+
|
|
215
|
+
assert 'defines' in data
|
|
216
|
+
assert 'OC_TOOL_COCOTB' in data['defines']
|
|
217
|
+
assert 'SIMULATION' in data['defines']
|
|
218
|
+
assert 'COCOTB' in data['defines']
|
|
219
|
+
|
|
220
|
+
assert data['defines']['SIMULATION'] == 1
|
|
221
|
+
assert data['defines']['COCOTB'] == 1
|
|
222
|
+
assert data['defines']['OC_TOOL_COCOTB'] is None # key present, no value
|
|
223
|
+
|
|
224
|
+
assert 'VERILATOR' not in data['defines']
|
|
225
|
+
assert 'SYNTHESIS' not in data['defines']
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
@pytest.mark.parametrize("cocotb_simulator", ['verilator', 'iverilog'])
|
|
230
|
+
@pytest.mark.parametrize("waves_arg", ["", "--waves"])
|
|
231
|
+
@pytest.mark.skipif(cannot_use_cocotb, reason=CANNOT_USE_COCOTB_REASON)
|
|
232
|
+
def test_cocotb_different_simulators(cocotb_simulator, waves_arg):
|
|
233
|
+
'''Test cocotb with different simulator configurations.'''
|
|
234
|
+
|
|
235
|
+
if cocotb_simulator not in tools_loaded:
|
|
236
|
+
pytest.skip(f"{cocotb_simulator=} skipped, {tools_loaded=}")
|
|
237
|
+
return #skip/bypass
|
|
238
|
+
|
|
239
|
+
chdir_remove_work_dir('../../examples/cocotb')
|
|
240
|
+
|
|
241
|
+
rc = eda_wrap(
|
|
242
|
+
'sim', '--tool', 'cocotb',
|
|
243
|
+
f'--cocotb-simulator={cocotb_simulator}',
|
|
244
|
+
waves_arg,
|
|
245
|
+
'cocotb_counter_test',
|
|
246
|
+
)
|
|
247
|
+
assert rc == 0
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
@pytest.mark.skipif(cannot_use_cocotb, reason=CANNOT_USE_COCOTB_REASON)
|
|
252
|
+
def test_cocotb_tool_instantiation():
|
|
253
|
+
'''Test that ToolCocotb can be instantiated and has correct properties.'''
|
|
254
|
+
|
|
255
|
+
tool = ToolCocotb(config={})
|
|
256
|
+
|
|
257
|
+
# version detection works
|
|
258
|
+
version = tool.get_versions()
|
|
259
|
+
assert version, "Should return a non-empty version string"
|
|
260
|
+
assert isinstance(version, str)
|
|
261
|
+
|
|
262
|
+
# tool defines
|
|
263
|
+
tool.set_tool_defines()
|
|
264
|
+
defines = tool.defines
|
|
265
|
+
assert 'SIMULATION' in defines
|
|
266
|
+
assert 'COCOTB' in defines
|
|
267
|
+
assert 'OC_TOOL_COCOTB' in defines
|
|
268
|
+
assert defines['SIMULATION'] == 1
|
|
269
|
+
assert defines['COCOTB'] == 1
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
@pytest.mark.skipif(cannot_use_cocotb, reason=CANNOT_USE_COCOTB_REASON)
|
|
274
|
+
def test_cocotb_failure_cases():
|
|
275
|
+
'''Test cocotb failure scenarios to ensure proper error handling.'''
|
|
276
|
+
|
|
277
|
+
chdir_remove_work_dir('../../examples/cocotb')
|
|
278
|
+
|
|
279
|
+
# Test 1: missing test files should fail gracefully
|
|
280
|
+
rc = eda_wrap('sim', '--tool', 'cocotb', 'counter') # Just HDL, no test files
|
|
281
|
+
assert rc > 1, "Should fail when no cocotb test files are found"
|
|
282
|
+
|
|
283
|
+
# Test 2: non-existent target should fail
|
|
284
|
+
rc = eda_wrap('sim', '--tool', 'cocotb', 'nonexistent_target')
|
|
285
|
+
assert rc > 1, "Should fail for non-existent target"
|
|
286
|
+
|
|
287
|
+
# Test 3: invalid cocotb test module should fail
|
|
288
|
+
rc = eda_wrap(
|
|
289
|
+
'sim', '--tool', 'cocotb',
|
|
290
|
+
'--cocotb-test-module=nonexistent_test',
|
|
291
|
+
'cocotb_counter_test',
|
|
292
|
+
)
|
|
293
|
+
assert rc > 1, "Should fail with invalid test module"
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
@pytest.mark.skipif(cannot_use_cocotb, reason=CANNOT_USE_COCOTB_REASON)
|
|
297
|
+
def test_cocotb_missing_dependencies():
|
|
298
|
+
'''Test cocotb behavior when dependencies are missing.'''
|
|
299
|
+
|
|
300
|
+
# Test missing cocotb installation (simulate by checking error handling)
|
|
301
|
+
tool = ToolCocotb(config={})
|
|
302
|
+
version = tool.get_versions()
|
|
303
|
+
assert version, "Should return version when cocotb is properly installed"
|
|
304
|
+
|
|
305
|
+
# Test tool defines are properly set even with minimal config
|
|
306
|
+
tool.set_tool_defines()
|
|
307
|
+
defines = tool.defines
|
|
308
|
+
assert 'SIMULATION' in defines
|
|
309
|
+
assert 'COCOTB' in defines
|
|
310
|
+
assert 'OC_TOOL_COCOTB' in defines
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
@pytest.mark.skipif(cannot_use_cocotb, reason=CANNOT_USE_COCOTB_REASON)
|
|
314
|
+
def test_cocotb_invalid_simulator():
|
|
315
|
+
'''Test cocotb with invalid simulator configuration.'''
|
|
316
|
+
|
|
317
|
+
chdir_remove_work_dir('../../examples/cocotb')
|
|
318
|
+
|
|
319
|
+
rc = eda_wrap(
|
|
320
|
+
'sim', '--tool', 'cocotb',
|
|
321
|
+
'--cocotb-simulator=invalid_sim',
|
|
322
|
+
'cocotb_counter_test',
|
|
323
|
+
)
|
|
324
|
+
assert rc > 1, "Should fail with invalid simulator"
|
|
325
|
+
|
|
326
|
+
@pytest.mark.skipif(cannot_use_cocotb, reason=CANNOT_USE_COCOTB_REASON)
|
|
327
|
+
def test_cocotb_malformed_hdl():
|
|
328
|
+
'''Test cocotb with malformed HDL files.'''
|
|
329
|
+
|
|
330
|
+
chdir_remove_work_dir('../../lib/tests')
|
|
331
|
+
|
|
332
|
+
# Test with a target that has syntax errors - should fail during compilation
|
|
333
|
+
rc = eda_wrap(
|
|
334
|
+
'sim', '--tool', 'cocotb',
|
|
335
|
+
'--cocotb-test-module=test_counter',
|
|
336
|
+
'tb_dollar_fatal',
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
assert rc > 1, "Should fail with malformed HDL or failing test assertions"
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
@pytest.mark.skipif(cannot_use_cocotb, reason=CANNOT_USE_COCOTB_REASON)
|
|
343
|
+
def test_cocotb_test_failures():
|
|
344
|
+
'''Test that cocotb properly reports test failures.'''
|
|
345
|
+
|
|
346
|
+
chdir_remove_work_dir('../../examples/cocotb')
|
|
347
|
+
|
|
348
|
+
# Intentionally failing cocotb tests
|
|
349
|
+
rc = eda_wrap('sim', '--tool', 'cocotb', 'cocotb_failure_test')
|
|
350
|
+
assert rc > 1, "Should fail when cocotb tests contain assertion failures"
|