opencos-eda 0.3.3__py3-none-any.whl → 0.3.6__py3-none-any.whl
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/commands/sim.py +16 -6
- opencos/deps/defaults.py +1 -0
- opencos/deps/deps_processor.py +60 -24
- opencos/deps_schema.py +17 -0
- opencos/eda.py +13 -19
- opencos/eda_base.py +78 -29
- opencos/eda_config.py +86 -41
- opencos/eda_config_defaults.yml +8 -1
- opencos/eda_extract_targets.py +0 -0
- opencos/eda_tool_helper.py +19 -0
- opencos/export_helper.py +89 -31
- opencos/files.py +3 -1
- opencos/hw/oc_cli.py +0 -0
- opencos/tests/helpers.py +60 -17
- opencos/tests/test_eda.py +11 -1
- opencos/tools/cocotb.py +94 -21
- opencos/tools/iverilog.py +4 -0
- opencos/tools/riviera.py +23 -12
- opencos/tools/verilator.py +91 -2
- opencos/tools/vivado.py +1 -0
- opencos/util.py +86 -57
- opencos/utils/str_helpers.py +6 -1
- opencos/utils/subprocess_helpers.py +66 -3
- {opencos_eda-0.3.3.dist-info → opencos_eda-0.3.6.dist-info}/METADATA +12 -3
- {opencos_eda-0.3.3.dist-info → opencos_eda-0.3.6.dist-info}/RECORD +28 -28
- {opencos_eda-0.3.3.dist-info → opencos_eda-0.3.6.dist-info}/WHEEL +0 -0
- {opencos_eda-0.3.3.dist-info → opencos_eda-0.3.6.dist-info}/entry_points.txt +0 -0
- {opencos_eda-0.3.3.dist-info → opencos_eda-0.3.6.dist-info}/licenses/LICENSE +0 -0
- {opencos_eda-0.3.3.dist-info → opencos_eda-0.3.6.dist-info}/licenses/LICENSE.spdx +0 -0
- {opencos_eda-0.3.3.dist-info → opencos_eda-0.3.6.dist-info}/top_level.txt +0 -0
opencos/tools/cocotb.py
CHANGED
|
@@ -10,7 +10,9 @@ import subprocess
|
|
|
10
10
|
from opencos import util
|
|
11
11
|
from opencos.eda_base import Tool
|
|
12
12
|
from opencos.commands import CommandSim
|
|
13
|
+
from opencos.utils import status_constants
|
|
13
14
|
from opencos.utils.str_helpers import sanitize_defines_for_sh
|
|
15
|
+
from opencos.tools import verilator # For default waivers.
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
class ToolCocotb(Tool):
|
|
@@ -76,6 +78,8 @@ class CommandSimCocotb(CommandSim, ToolCocotb):
|
|
|
76
78
|
'tcl-file': None,
|
|
77
79
|
'cocotb-test-module': None,
|
|
78
80
|
'cocotb-test-runner': 'python',
|
|
81
|
+
'cocotb-test-runner-file': '',
|
|
82
|
+
'cocotb-test-run-dir': None, # If None, use self.args['work-dir']
|
|
79
83
|
'cocotb-simulator': 'verilator',
|
|
80
84
|
'cocotb-makefile': False,
|
|
81
85
|
'cocotb-python-runner': True,
|
|
@@ -86,17 +90,25 @@ class CommandSimCocotb(CommandSim, ToolCocotb):
|
|
|
86
90
|
'waves': 'Include waveforms by setting COCOTB_ENABLE_WAVES=1',
|
|
87
91
|
'cocotb-test-module': 'Python test module name (e.g., test_my_design)',
|
|
88
92
|
'cocotb-test-runner': 'Test runner to use: python (default) or pytest',
|
|
89
|
-
'cocotb-
|
|
90
|
-
|
|
93
|
+
'cocotb-test-runner-file': 'Bring your own test_runner.py file',
|
|
94
|
+
'cocotb-test-run-dir': (
|
|
95
|
+
'Directory where cocotb-test-runner will run, if unset uses default eda.work/(name)'
|
|
96
|
+
),
|
|
97
|
+
'cocotb-simulator': (
|
|
98
|
+
'Simulator backend: verilator (default), icarus, etc.'
|
|
99
|
+
' Note that iverilog will convert to icarus here'
|
|
100
|
+
),
|
|
91
101
|
'cocotb-makefile': 'Use traditional Makefile system instead of Python runner',
|
|
92
102
|
'cocotb-python-runner': 'Use Python-based runner system (default, cocotb 1.8+)',
|
|
93
|
-
'cocotb-standalone-makefile': (
|
|
94
|
-
|
|
103
|
+
'cocotb-standalone-makefile': (
|
|
104
|
+
'Use provided Makefile as-is, run make in source directory'
|
|
105
|
+
),
|
|
95
106
|
})
|
|
96
107
|
|
|
97
108
|
self.cocotb_command_lists = []
|
|
98
109
|
self.cocotb_test_files = []
|
|
99
110
|
|
|
111
|
+
|
|
100
112
|
def set_tool_defines(self):
|
|
101
113
|
ToolCocotb.set_tool_defines(self)
|
|
102
114
|
|
|
@@ -155,12 +167,13 @@ class CommandSimCocotb(CommandSim, ToolCocotb):
|
|
|
155
167
|
simulate_sh_fname='cocotb_test.sh'
|
|
156
168
|
)
|
|
157
169
|
|
|
170
|
+
|
|
158
171
|
def _find_cocotb_test_files(self):
|
|
159
172
|
'''Find Python test files that contain cocotb tests'''
|
|
160
173
|
self.cocotb_test_files = []
|
|
161
174
|
|
|
162
175
|
# Look for test files in the current directory and deps
|
|
163
|
-
for file_path in self.files_non_source:
|
|
176
|
+
for file_path in self.files_non_source + self.files_py:
|
|
164
177
|
if (file_path.endswith('.py') and
|
|
165
178
|
('test' in file_path.lower() or 'tb' in file_path.lower())):
|
|
166
179
|
# Check if it's a cocotb test file
|
|
@@ -193,8 +206,19 @@ class CommandSimCocotb(CommandSim, ToolCocotb):
|
|
|
193
206
|
def _prepare_python_runner_system(self):
|
|
194
207
|
'''Prepare cocotb using the Python-based runner system (cocotb 1.8+)'''
|
|
195
208
|
|
|
196
|
-
# Create a Python runner script
|
|
197
|
-
|
|
209
|
+
# Create a Python runner script, or use from --cocotb-test-runner-file
|
|
210
|
+
if self.args['cocotb-test-runner-file']:
|
|
211
|
+
|
|
212
|
+
runner_script = self.args['cocotb-test-runner-file']
|
|
213
|
+
if not os.path.isfile(self.args['cocotb-test-runner-file']):
|
|
214
|
+
self.error(
|
|
215
|
+
"File does not exist, for: --cocotb-test-runner-file=",
|
|
216
|
+
f"{self.args['cocotb-test-runner-file']}",
|
|
217
|
+
error_code=status_constants.EDA_GENERAL_FILE_NOT_FOUND
|
|
218
|
+
)
|
|
219
|
+
return
|
|
220
|
+
else:
|
|
221
|
+
runner_script = self._create_python_runner_script()
|
|
198
222
|
|
|
199
223
|
if self.args['cocotb-test-runner'] == 'pytest':
|
|
200
224
|
# Use pytest to run the tests
|
|
@@ -212,28 +236,41 @@ class CommandSimCocotb(CommandSim, ToolCocotb):
|
|
|
212
236
|
# Set environment variables
|
|
213
237
|
env_vars = self._get_cocotb_env_vars()
|
|
214
238
|
|
|
215
|
-
# Create command with environment variables
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
239
|
+
# Create command with environment variables, needs to be list-of-(cmd_list)
|
|
240
|
+
self.cocotb_command_lists = [
|
|
241
|
+
util.ShellCommandList(
|
|
242
|
+
self._create_env_command(env_vars) + cmd_list,
|
|
243
|
+
tee_fpath='cocotb_test.log',
|
|
244
|
+
# If someone wanted to run this from a specific dir, then
|
|
245
|
+
# run it from there.
|
|
246
|
+
work_dir=self.args['cocotb-test-run-dir']
|
|
247
|
+
)
|
|
248
|
+
]
|
|
219
249
|
|
|
220
250
|
def _prepare_makefile_system(self):
|
|
221
251
|
'''Prepare cocotb using the traditional Makefile system'''
|
|
222
252
|
|
|
223
253
|
makefile_path = os.path.join(self.args['work-dir'], 'Makefile')
|
|
254
|
+
self.files_makefile.append(makefile_path)
|
|
224
255
|
with open(makefile_path, 'w', encoding='utf-8') as f:
|
|
225
256
|
f.write(self._create_makefile_content())
|
|
226
257
|
|
|
227
258
|
cmd_list = self._create_shell_command_with_success('make -f Makefile')
|
|
228
|
-
self.cocotb_command_lists = [
|
|
229
|
-
|
|
259
|
+
self.cocotb_command_lists = [
|
|
260
|
+
util.ShellCommandList(
|
|
261
|
+
cmd_list, tee_fpath='cocotb_makefile.log',
|
|
262
|
+
# If someone wanted to run this from a specific dir, then
|
|
263
|
+
# run it from there.
|
|
264
|
+
work_dir=self.args['cocotb-test-run-dir']
|
|
265
|
+
)
|
|
266
|
+
]
|
|
230
267
|
|
|
231
268
|
def _prepare_standalone_makefile_system(self):
|
|
232
269
|
'''Use provided Makefile as-is, run make in source directory'''
|
|
233
270
|
|
|
234
271
|
# Find the Makefile in our dependencies
|
|
235
272
|
makefile_path = None
|
|
236
|
-
for file_path in self.files_non_source:
|
|
273
|
+
for file_path in self.files_non_source + self.files_makefile:
|
|
237
274
|
if os.path.basename(file_path).lower() == 'makefile':
|
|
238
275
|
makefile_path = file_path
|
|
239
276
|
break
|
|
@@ -241,10 +278,19 @@ class CommandSimCocotb(CommandSim, ToolCocotb):
|
|
|
241
278
|
if not makefile_path:
|
|
242
279
|
self.error('No Makefile found in deps for --cocotb-standalone-makefile')
|
|
243
280
|
|
|
281
|
+
if any(value for key,value in self.args.items() if key.startswith('export')):
|
|
282
|
+
util.warning(f'Using an --export arg with Cocotb standalong Makefile {makefile_path}',
|
|
283
|
+
'is not fully supported')
|
|
284
|
+
|
|
244
285
|
makefile_dir = os.path.dirname(os.path.abspath(makefile_path))
|
|
245
|
-
cmd_list = self._create_shell_command_with_success(
|
|
246
|
-
self.cocotb_command_lists = [
|
|
247
|
-
|
|
286
|
+
cmd_list = self._create_shell_command_with_success('make')
|
|
287
|
+
self.cocotb_command_lists = [
|
|
288
|
+
util.ShellCommandList(
|
|
289
|
+
cmd_list,
|
|
290
|
+
tee_fpath='cocotb_standalone.log',
|
|
291
|
+
work_dir=makefile_dir
|
|
292
|
+
)
|
|
293
|
+
]
|
|
248
294
|
|
|
249
295
|
def _get_test_module_name(self) -> str:
|
|
250
296
|
'''Get the test module name from args or detected files'''
|
|
@@ -280,8 +326,22 @@ class CommandSimCocotb(CommandSim, ToolCocotb):
|
|
|
280
326
|
|
|
281
327
|
return script_path
|
|
282
328
|
|
|
329
|
+
|
|
283
330
|
def _generate_runner_script_content(self, test_module: str, hdl_sources: list) -> str:
|
|
284
331
|
'''Generate the content for the Python runner script'''
|
|
332
|
+
|
|
333
|
+
if shutil.which('verilator'):
|
|
334
|
+
# TODO(drew): this shortcuts if verilator is truly usable,
|
|
335
|
+
# consider using eda_tool_helper to get "tools_loaded", which
|
|
336
|
+
# is not set in self.config['tools_loaded'] when --tool=cocotb.
|
|
337
|
+
# Would need minor refactor for eda.py methods auto_tools_order,
|
|
338
|
+
# tool_setup to go into eda_tool_helper.py, and those methods would
|
|
339
|
+
# need hooks to be non-destructive to config.
|
|
340
|
+
tmp_verilator_obj = verilator.VerilatorSim(config=self.config)
|
|
341
|
+
verilator_waivers = tmp_verilator_obj.get_verilator_tool_config_waivers()
|
|
342
|
+
else:
|
|
343
|
+
verilator_waivers = []
|
|
344
|
+
|
|
285
345
|
return f'''#!/usr/bin/env python3
|
|
286
346
|
"""
|
|
287
347
|
Cocotb test runner script generated by opencos
|
|
@@ -337,6 +397,8 @@ def run_cocotb_test():
|
|
|
337
397
|
|
|
338
398
|
if simulator == "verilator":
|
|
339
399
|
build_args.extend({list(self.args.get('verilate-args', []))!r})
|
|
400
|
+
build_args.extend({list(self.args.get('compile-args', []))!r})
|
|
401
|
+
build_args.extend({list(verilator_waivers)!r})
|
|
340
402
|
|
|
341
403
|
# Build the design
|
|
342
404
|
runner.build(
|
|
@@ -449,9 +511,20 @@ include $(shell cocotb-config --makefiles)/Makefile.sim
|
|
|
449
511
|
'''Get environment variables for cocotb execution'''
|
|
450
512
|
env_vars = {}
|
|
451
513
|
|
|
514
|
+
top = self.args.get('top', 'top')
|
|
515
|
+
|
|
452
516
|
# Basic cocotb configuration
|
|
453
|
-
env_vars
|
|
454
|
-
|
|
517
|
+
env_vars.update({
|
|
518
|
+
'SIM': self.args['cocotb-simulator'],
|
|
519
|
+
'TOPLEVEL': top,
|
|
520
|
+
'COCOTB_TOPLEVEL': top,
|
|
521
|
+
})
|
|
522
|
+
|
|
523
|
+
if test_module := self.args['cocotb-test-module']:
|
|
524
|
+
env_vars.update({
|
|
525
|
+
'MODULE': test_module,
|
|
526
|
+
'COCOTB_TEST_MODULES': test_module,
|
|
527
|
+
})
|
|
455
528
|
|
|
456
529
|
# Enable waves if requested
|
|
457
530
|
if self.args.get('waves', False):
|
|
@@ -464,8 +537,8 @@ include $(shell cocotb-config --makefiles)/Makefile.sim
|
|
|
464
537
|
env_vars['COCOTB_LOG_LEVEL'] = 'INFO'
|
|
465
538
|
|
|
466
539
|
# Random seed
|
|
467
|
-
if self.args.get('seed'):
|
|
468
|
-
env_vars['COCOTB_RANDOM_SEED'] = str(
|
|
540
|
+
if seed := self.args.get('seed'):
|
|
541
|
+
env_vars['COCOTB_RANDOM_SEED'] = str(seed)
|
|
469
542
|
|
|
470
543
|
return env_vars
|
|
471
544
|
|
opencos/tools/iverilog.py
CHANGED
|
@@ -160,6 +160,10 @@ class CommandSimIverilog(CommandSim, ToolIverilog):
|
|
|
160
160
|
cmd_list += self.tool_config.get('simulate-args', '').split()
|
|
161
161
|
if self.args['waves']:
|
|
162
162
|
cmd_list += self.tool_config.get('simulate-waves-args', '').split()
|
|
163
|
+
for x in self.args['sim-plusargs']:
|
|
164
|
+
if x[0] != '+':
|
|
165
|
+
x = f'+{x}'
|
|
166
|
+
cmd_list.append(x)
|
|
163
167
|
return [ util.ShellCommandList(cmd_list, tee_fpath='sim.log') ]
|
|
164
168
|
|
|
165
169
|
def get_post_simulate_command_lists(self, **kwargs) -> list:
|
opencos/tools/riviera.py
CHANGED
|
@@ -13,6 +13,7 @@ import subprocess
|
|
|
13
13
|
from opencos import util
|
|
14
14
|
from opencos.tools.modelsim_ase import ToolModelsimAse, CommandSimModelsimAse
|
|
15
15
|
from opencos.utils.str_helpers import sanitize_defines_for_sh
|
|
16
|
+
from opencos.utils import status_constants
|
|
16
17
|
|
|
17
18
|
class ToolRiviera(ToolModelsimAse):
|
|
18
19
|
'''ToolRiviera used by opencos.eda for --tool=riviera'''
|
|
@@ -61,6 +62,7 @@ class CommandSimRiviera(CommandSimModelsimAse, ToolRiviera):
|
|
|
61
62
|
'gui': False,
|
|
62
63
|
'waves-fst': True,
|
|
63
64
|
'waves-vcd': False,
|
|
65
|
+
'coverage-tcl': '',
|
|
64
66
|
})
|
|
65
67
|
self.args_help.update({
|
|
66
68
|
'waves-fst': (
|
|
@@ -70,6 +72,10 @@ class CommandSimRiviera(CommandSimModelsimAse, ToolRiviera):
|
|
|
70
72
|
),
|
|
71
73
|
'waves-vcd': 'If using --waves, apply simulation runtime arg +trace=vcd',
|
|
72
74
|
'waves': 'Save a .asdb offline wavefile, can be used with --waves-fst or --waves-vcd',
|
|
75
|
+
'coverage-tcl': (
|
|
76
|
+
'bring your own .tcl file to run in Riviera (vsim) for coverage. The default'
|
|
77
|
+
' tcl steps are (from tool config in --config-yml): '
|
|
78
|
+
) + '; '.join(self.tool_config.get('simulate-coverage-tcl', [])),
|
|
73
79
|
})
|
|
74
80
|
|
|
75
81
|
def set_tool_defines(self):
|
|
@@ -183,7 +189,9 @@ class CommandSimRiviera(CommandSimModelsimAse, ToolRiviera):
|
|
|
183
189
|
|
|
184
190
|
|
|
185
191
|
|
|
186
|
-
def write_vsim_dot_do(
|
|
192
|
+
def write_vsim_dot_do( # pylint: disable=too-many-branches
|
|
193
|
+
self, dot_do_to_write: list
|
|
194
|
+
) -> None:
|
|
187
195
|
'''Writes files(s) based on dot_do_to_write(list of str)
|
|
188
196
|
|
|
189
197
|
list arg values can be empty (all) or have items 'all', 'sim', 'lint', 'vlog'.'''
|
|
@@ -278,18 +286,21 @@ class CommandSimRiviera(CommandSimModelsimAse, ToolRiviera):
|
|
|
278
286
|
"}",
|
|
279
287
|
]
|
|
280
288
|
|
|
289
|
+
vsim_dot_do_lines += [
|
|
290
|
+
"run -all;",
|
|
291
|
+
]
|
|
281
292
|
if self.args['coverage']:
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
+
if self.args['coverage-tcl']:
|
|
294
|
+
tclfile = os.path.abspath(self.args['coverage-tcl'])
|
|
295
|
+
if not os.path.isfile(tclfile):
|
|
296
|
+
self.error(f'--coverage-tcl file not found: {tclfile}',
|
|
297
|
+
error_code=status_constants.EDA_COMMAND_OR_ARGS_ERROR)
|
|
298
|
+
vsim_dot_do_lines += [
|
|
299
|
+
f'source {tclfile}'
|
|
300
|
+
]
|
|
301
|
+
else:
|
|
302
|
+
# default TCL for coverage:
|
|
303
|
+
vsim_dot_do_lines += self.tool_config.get('simulate-coverage-tcl', [])
|
|
293
304
|
|
|
294
305
|
|
|
295
306
|
vsim_dot_do_lines += [
|
opencos/tools/verilator.py
CHANGED
|
@@ -83,6 +83,7 @@ class VerilatorSim(CommandSim, ToolVerilator):
|
|
|
83
83
|
'lint-only': False,
|
|
84
84
|
'cc-mode': False,
|
|
85
85
|
'verilator-coverage-args': [],
|
|
86
|
+
'uvm': False,
|
|
86
87
|
'x-assign': '',
|
|
87
88
|
'x-initial': '',
|
|
88
89
|
})
|
|
@@ -116,6 +117,15 @@ class VerilatorSim(CommandSim, ToolVerilator):
|
|
|
116
117
|
' where valid string values are: 0, unique, fast.'
|
|
117
118
|
' Also conditinally adds to verilated exe call:'
|
|
118
119
|
' +verilator+rand+reset+[0,2] for arg values 0, unique|fast'),
|
|
120
|
+
'uvm': (
|
|
121
|
+
'Warns on Verilator < 5.042, or missing $UVM_HOME environment var set (or in'
|
|
122
|
+
' .env, $UVM_HOME/uvm_pkg.sv should exist), and will run verilator with args:'
|
|
123
|
+
' -Wno-fatal +define+UVM_NO_DPI'
|
|
124
|
+
),
|
|
125
|
+
'verilator-coverage-args': (
|
|
126
|
+
'Requires --coverage, args to be applied to verilator_coverage, which runs'
|
|
127
|
+
' after running the compiled executable simulation'
|
|
128
|
+
),
|
|
119
129
|
})
|
|
120
130
|
|
|
121
131
|
self.verilate_command_lists = []
|
|
@@ -212,12 +222,19 @@ class VerilatorSim(CommandSim, ToolVerilator):
|
|
|
212
222
|
|
|
213
223
|
verilate_command_list = self._get_start_verilator_command_list(lint_only=lint_only)
|
|
214
224
|
|
|
215
|
-
|
|
225
|
+
# Handle UVM things (return args), but also handles uvm_pkg.sv in self.files_sv:
|
|
226
|
+
# since we run this 2x (lint-only and normal) only do warnings for one of them:
|
|
227
|
+
verilate_command_list += self._verilator_args_uvm(
|
|
228
|
+
warnings=(not lint_only), add_uvm_pkg_if_found=True
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
verilate_command_list += self.get_verilator_tool_config_waivers()
|
|
216
232
|
|
|
217
233
|
verilate_command_list += self._verilator_args_defaults_cflags_nproc()
|
|
218
234
|
|
|
219
235
|
verilate_command_list += self._get_verilator_waves_args(lint_only=lint_only)
|
|
220
236
|
|
|
237
|
+
|
|
221
238
|
if self.args.get('coverage', True):
|
|
222
239
|
verilate_command_list += self.tool_config.get(
|
|
223
240
|
'compile-coverage-args', '--coverage').split()
|
|
@@ -391,7 +408,10 @@ class VerilatorSim(CommandSim, ToolVerilator):
|
|
|
391
408
|
|
|
392
409
|
return verilate_command_list
|
|
393
410
|
|
|
394
|
-
def
|
|
411
|
+
def get_verilator_tool_config_waivers(self) -> list:
|
|
412
|
+
'''Returns list of args to verilator for waviers, from --compile-waivers and
|
|
413
|
+
|
|
414
|
+
--config-yml for tool: (config)'''
|
|
395
415
|
|
|
396
416
|
# Add compile waivers from self.config (tools.verilator.compile-waivers list):
|
|
397
417
|
# list(set(mylist)) to get unique.
|
|
@@ -486,6 +506,75 @@ class VerilatorSim(CommandSim, ToolVerilator):
|
|
|
486
506
|
return verilate_args
|
|
487
507
|
|
|
488
508
|
|
|
509
|
+
def _verilator_support_uvm_pkg_fpath(self, add_if_found: bool = True) -> bool:
|
|
510
|
+
'''Returns False if we could not find a suitable uvm_pkg.sv to use, or if --no-uvm.
|
|
511
|
+
|
|
512
|
+
This will also auto-add uvm_pkg.sv from $UVM_HOME/uvm_pkg.sv if not present in
|
|
513
|
+
self.files already (adds to front of self.files_sv)
|
|
514
|
+
'''
|
|
515
|
+
|
|
516
|
+
if not self.args['uvm']:
|
|
517
|
+
return False
|
|
518
|
+
|
|
519
|
+
for fname, exists in self.files.items():
|
|
520
|
+
if exists and os.path.split(fname)[1] == 'uvm_pkg.sv':
|
|
521
|
+
# already present in our source files (assume someone doing it manually
|
|
522
|
+
# or via DEPS)
|
|
523
|
+
return True
|
|
524
|
+
|
|
525
|
+
uvm_home = os.environ.get('UVM_HOME', '')
|
|
526
|
+
if not uvm_home:
|
|
527
|
+
return False
|
|
528
|
+
|
|
529
|
+
uvm_pkg_fpath = os.path.join(uvm_home, 'uvm_pkg.sv')
|
|
530
|
+
if add_if_found and os.path.isfile(uvm_pkg_fpath):
|
|
531
|
+
uvm_pkg_fpath = os.path.abspath(uvm_pkg_fpath)
|
|
532
|
+
util.info(f'For --uvm, adding to source files: {uvm_pkg_fpath}')
|
|
533
|
+
self.files[uvm_pkg_fpath] = True
|
|
534
|
+
self.files_sv.insert(0, uvm_pkg_fpath)
|
|
535
|
+
self.files_caller_info[uvm_pkg_fpath] = 'verilator.py'
|
|
536
|
+
util.info(f'For --uvm, adding +incdir+: {uvm_home}')
|
|
537
|
+
self.incdirs.append(os.path.abspath(uvm_home))
|
|
538
|
+
return True
|
|
539
|
+
|
|
540
|
+
return False
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
def _verilator_args_uvm(
|
|
544
|
+
self, warnings: bool = True, add_uvm_pkg_if_found: bool = True
|
|
545
|
+
) -> list:
|
|
546
|
+
'''Returns list of args to be added to verilator (compile) step if --uvm present
|
|
547
|
+
|
|
548
|
+
Warnings on potential issues (Veriltor version, missing uvm_pkg.sv).
|
|
549
|
+
Optionally adds uvm_pkg.sv to source files.
|
|
550
|
+
'''
|
|
551
|
+
|
|
552
|
+
# Handle --uvm args:
|
|
553
|
+
if not self.args['uvm']:
|
|
554
|
+
return []
|
|
555
|
+
|
|
556
|
+
if warnings:
|
|
557
|
+
|
|
558
|
+
# prefers Verilator >= v5.042, $UVM_HOME to be set, or warning.
|
|
559
|
+
version_list = self._VERSION.split('.')
|
|
560
|
+
if int(version_list[0]) < 5 or \
|
|
561
|
+
(int(version_list[0]) == 5 and int(version_list[1]) < 42):
|
|
562
|
+
util.warning(f'Verilator version is {self._VERSION}, --uvm set prefers Verilator',
|
|
563
|
+
'version > v5.042')
|
|
564
|
+
|
|
565
|
+
if not os.environ.get('UVM_HOME', ''):
|
|
566
|
+
util.warning('--uvm set, however env (or .env or --env-file) $UVM_HOME is not set')
|
|
567
|
+
|
|
568
|
+
uvm_pkg_found = self._verilator_support_uvm_pkg_fpath(add_if_found=add_uvm_pkg_if_found)
|
|
569
|
+
if warnings and not uvm_pkg_found:
|
|
570
|
+
util.warning(
|
|
571
|
+
'--uvm set, however no suitable uvm_pkg.sv is source files,',
|
|
572
|
+
f'nor in $UVM_HOME/uvm_pkg.sv. $UVM_HOME={os.environ.get("UVM_HOME", "")}'
|
|
573
|
+
)
|
|
574
|
+
|
|
575
|
+
return ['-Wno-fatal', '+define+UVM_NO_DPI']
|
|
576
|
+
|
|
577
|
+
|
|
489
578
|
def artifacts_add(self, name: str, typ: str, description: str) -> None:
|
|
490
579
|
'''Override from Command.artifacts_add, so we can catch known file
|
|
491
580
|
|
opencos/tools/vivado.py
CHANGED
|
@@ -272,6 +272,7 @@ class CommandSimVivado(CommandSim, ToolVivado):
|
|
|
272
272
|
xsim_plusargs_list.append('--testplusarg')
|
|
273
273
|
if x[0] == '+':
|
|
274
274
|
x = x[1:]
|
|
275
|
+
x = x.replace('"', '\\\"') # we have to preserve " in the value.
|
|
275
276
|
xsim_plusargs_list.append(f'\"{x}\"')
|
|
276
277
|
|
|
277
278
|
# execute snapshot
|