opencos-eda 0.3.15__py3-none-any.whl → 0.3.17__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/flist.py +143 -88
- opencos/commands/shell.py +1 -1
- opencos/commands/sim.py +21 -8
- opencos/commands/waves.py +3 -1
- opencos/deps/defaults.py +6 -2
- opencos/deps/deps_file.py +30 -9
- opencos/deps/deps_processor.py +99 -65
- opencos/deps_schema.py +8 -0
- opencos/docs/DEPS.md +6 -0
- opencos/eda.py +30 -5
- opencos/eda_base.py +21 -9
- opencos/eda_config.py +2 -1
- opencos/eda_config_defaults.yml +9 -1
- opencos/eda_tool_helper.py +84 -9
- opencos/files.py +41 -0
- opencos/tools/cocotb.py +1 -1
- opencos/tools/invio.py +1 -1
- opencos/tools/invio_yosys.py +1 -1
- opencos/tools/iverilog.py +1 -1
- opencos/tools/quartus.py +1 -1
- opencos/tools/questa_common.py +6 -3
- opencos/tools/riviera.py +5 -3
- opencos/tools/slang.py +1 -1
- opencos/tools/slang_yosys.py +36 -8
- opencos/tools/surelog.py +1 -1
- opencos/tools/verilator.py +209 -20
- opencos/tools/vivado.py +1 -1
- opencos/tools/yosys.py +155 -30
- opencos/util.py +5 -1
- opencos/utils/docker_checks.py +224 -0
- opencos/utils/subprocess_helpers.py +3 -1
- {opencos_eda-0.3.15.dist-info → opencos_eda-0.3.17.dist-info}/METADATA +1 -1
- {opencos_eda-0.3.15.dist-info → opencos_eda-0.3.17.dist-info}/RECORD +38 -37
- {opencos_eda-0.3.15.dist-info → opencos_eda-0.3.17.dist-info}/WHEEL +0 -0
- {opencos_eda-0.3.15.dist-info → opencos_eda-0.3.17.dist-info}/entry_points.txt +0 -0
- {opencos_eda-0.3.15.dist-info → opencos_eda-0.3.17.dist-info}/licenses/LICENSE +0 -0
- {opencos_eda-0.3.15.dist-info → opencos_eda-0.3.17.dist-info}/licenses/LICENSE.spdx +0 -0
- {opencos_eda-0.3.15.dist-info → opencos_eda-0.3.17.dist-info}/top_level.txt +0 -0
opencos/tools/verilator.py
CHANGED
|
@@ -7,14 +7,24 @@ Contains classes for ToolVerilator and VerilatorSim, VerilatorElab.
|
|
|
7
7
|
|
|
8
8
|
import multiprocessing
|
|
9
9
|
import os
|
|
10
|
+
from pathlib import Path
|
|
10
11
|
import subprocess
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
from opencos import util
|
|
14
15
|
from opencos.commands import CommandSim
|
|
15
16
|
from opencos.eda_base import Tool
|
|
16
|
-
from opencos.files import safe_shutil_which
|
|
17
|
+
from opencos.files import safe_shutil_which, get_source_files_paths
|
|
18
|
+
from opencos.util import Colors
|
|
17
19
|
from opencos.utils.str_helpers import sanitize_defines_for_sh
|
|
20
|
+
from opencos.utils.docker_checks import docker_ok, get_docker_run_command, \
|
|
21
|
+
get_error_str_cant_run_docker
|
|
22
|
+
|
|
23
|
+
class Warned:
|
|
24
|
+
'''So we only make the same warnings once, ToolVerilator may be called > 1 times'''
|
|
25
|
+
tool_get_versions_docker: bool = False
|
|
26
|
+
tool_get_versions_verilator_coverage: bool = False
|
|
27
|
+
|
|
18
28
|
|
|
19
29
|
class ToolVerilator(Tool):
|
|
20
30
|
'''ToolVerilator used by opencos.eda for --tool=verilator'''
|
|
@@ -23,17 +33,32 @@ class ToolVerilator(Tool):
|
|
|
23
33
|
_EXE = 'verilator'
|
|
24
34
|
_URL = 'github.com/verilator/verilator'
|
|
25
35
|
|
|
36
|
+
DEFAULT_DOCKER_IMAGE = 'verilator/verilator:latest'
|
|
37
|
+
|
|
26
38
|
verilator_base_path = ''
|
|
27
39
|
verilator_exe = ''
|
|
28
40
|
verilator_coverage_exe = ''
|
|
41
|
+
no_verilator_but_has_docker = False
|
|
29
42
|
|
|
30
|
-
def get_versions(self) -> str:
|
|
43
|
+
def get_versions(self, **kwargs) -> str: # pylint: disable=too-many-branches
|
|
31
44
|
if self._VERSION:
|
|
32
45
|
return self._VERSION
|
|
33
46
|
# __init__ would have set self.EXE to full path.
|
|
34
47
|
path = safe_shutil_which(self._EXE)
|
|
35
48
|
if not path:
|
|
36
|
-
|
|
49
|
+
# but can we run via docker?
|
|
50
|
+
if docker_ok():
|
|
51
|
+
if not Warned.tool_get_versions_docker:
|
|
52
|
+
Warned.tool_get_versions_docker = True
|
|
53
|
+
util.info(f'{Colors.cyan}"verilator"{Colors.green} not in path,',
|
|
54
|
+
f'may use {Colors.cyan}--docker-run{Colors.green}',
|
|
55
|
+
f'to run with {self.DEFAULT_DOCKER_IMAGE}, see',
|
|
56
|
+
f'{Colors.cyan}--help{Colors.green} for other options.')
|
|
57
|
+
self.verilator_exe = 'verilator'
|
|
58
|
+
self.verilator_base_path = ''
|
|
59
|
+
self.no_verilator_but_has_docker = True
|
|
60
|
+
else:
|
|
61
|
+
self.error(f'"{self._EXE}" not in path or not installed, see {self._URL})')
|
|
37
62
|
else:
|
|
38
63
|
self.verilator_exe = path
|
|
39
64
|
self.verilator_base_path, _ = os.path.split(path)
|
|
@@ -43,27 +68,42 @@ class ToolVerilator(Tool):
|
|
|
43
68
|
self.verilator_coverage_exe = safe_shutil_which(
|
|
44
69
|
os.path.join(self.verilator_base_path, 'verilator_coverage')
|
|
45
70
|
)
|
|
46
|
-
if not self.verilator_coverage_exe
|
|
71
|
+
if not self.verilator_coverage_exe and not docker_ok() and \
|
|
72
|
+
not Warned.tool_get_versions_verilator_coverage:
|
|
73
|
+
Warned.tool_get_versions_verilator_coverage = True
|
|
47
74
|
util.warning('"verilator_coverage" not in path, need from same path',
|
|
48
75
|
f'as "{self.verilator_exe}"')
|
|
49
76
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
77
|
+
if path:
|
|
78
|
+
version_ret = subprocess.run(
|
|
79
|
+
[self.verilator_exe, '--version'],
|
|
80
|
+
capture_output=True,
|
|
81
|
+
check=False
|
|
82
|
+
)
|
|
83
|
+
elif docker_ok():
|
|
84
|
+
version_ret = subprocess.run(
|
|
85
|
+
['docker', 'run', self.DEFAULT_DOCKER_IMAGE, '--version'],
|
|
86
|
+
capture_output=True,
|
|
87
|
+
check=False
|
|
88
|
+
)
|
|
89
|
+
else:
|
|
90
|
+
self._VERSION = 'unknown'
|
|
91
|
+
return self._VERSION
|
|
92
|
+
|
|
55
93
|
stdout = version_ret.stdout.decode('utf-8', errors='replace')
|
|
56
94
|
util.debug(f'{path=} {version_ret=}')
|
|
57
95
|
words = stdout.split() # 'Verilator 5.027 devel rev v5.026-92-g403a197e2
|
|
58
|
-
if len(words) <
|
|
96
|
+
if len(words) < 2:
|
|
59
97
|
util.warning(
|
|
60
98
|
f'{self.verilator_exe} --version: returned unexpected string {version_ret=}'
|
|
61
99
|
)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
100
|
+
version = ''
|
|
101
|
+
else:
|
|
102
|
+
version = words[1]
|
|
103
|
+
ver_list = version.split('.')
|
|
104
|
+
if len(ver_list) != 2:
|
|
105
|
+
util.warning(f'{self.verilator_exe} --version: returned unexpected',
|
|
106
|
+
f'string {version_ret=} {version=}')
|
|
67
107
|
self._VERSION = version
|
|
68
108
|
return self._VERSION
|
|
69
109
|
|
|
@@ -84,6 +124,7 @@ class VerilatorSim(CommandSim, ToolVerilator):
|
|
|
84
124
|
'verilator-coverage-args': [],
|
|
85
125
|
'x-assign': '',
|
|
86
126
|
'x-initial': '',
|
|
127
|
+
'docker-image': self.DEFAULT_DOCKER_IMAGE
|
|
87
128
|
})
|
|
88
129
|
|
|
89
130
|
self.args_help.update({
|
|
@@ -137,6 +178,8 @@ class VerilatorSim(CommandSim, ToolVerilator):
|
|
|
137
178
|
self.verilated_exec_command_lists = []
|
|
138
179
|
self.verilated_post_exec_coverage_command_lists = []
|
|
139
180
|
|
|
181
|
+
self.docker_arg_set = False
|
|
182
|
+
|
|
140
183
|
|
|
141
184
|
def set_tool_defines(self):
|
|
142
185
|
ToolVerilator.set_tool_defines(self)
|
|
@@ -149,6 +192,27 @@ class VerilatorSim(CommandSim, ToolVerilator):
|
|
|
149
192
|
self.set_tool_defines()
|
|
150
193
|
self.update_library_map()
|
|
151
194
|
|
|
195
|
+
self.docker_arg_set = self.args['docker-run']
|
|
196
|
+
if self.no_verilator_but_has_docker and not self.docker_arg_set:
|
|
197
|
+
self.error('"verilator" was not found in PATH, but can be run with --docker-run',
|
|
198
|
+
'and optionally --docker-image=verilator/verilator:vX.YYY')
|
|
199
|
+
return
|
|
200
|
+
|
|
201
|
+
if self.docker_arg_set:
|
|
202
|
+
# check that user can run docker?
|
|
203
|
+
if docker_ok():
|
|
204
|
+
# If this is docker, we cannot use the full path from self.verilator_exe,
|
|
205
|
+
# we have to simply use 'verilator' in the shell script that the docker image
|
|
206
|
+
# will run.
|
|
207
|
+
self.verilator_exe = 'verilator'
|
|
208
|
+
arg = '--docker-run'
|
|
209
|
+
util.info(
|
|
210
|
+
f'Running with {arg} --docker-image={self.args["docker-image"]}',
|
|
211
|
+
color=Colors.byellow
|
|
212
|
+
)
|
|
213
|
+
else:
|
|
214
|
+
self.error(get_error_str_cant_run_docker())
|
|
215
|
+
|
|
152
216
|
# If there are C++ files here, then we will run Verilator in --cc mode:
|
|
153
217
|
if self.files_cpp:
|
|
154
218
|
self.args['cc-mode'] = True
|
|
@@ -164,12 +228,18 @@ class VerilatorSim(CommandSim, ToolVerilator):
|
|
|
164
228
|
paths = ['obj_dir', 'logs']
|
|
165
229
|
util.safe_mkdirs(base=self.args['work-dir'], new_dirs=paths)
|
|
166
230
|
|
|
167
|
-
util.write_shell_command_file(dirpath=self.args['work-dir'], filename='lint_only.sh',
|
|
168
|
-
command_lists=self.lint_only_command_lists, line_breaks=True)
|
|
169
231
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
232
|
+
util.write_shell_command_file(
|
|
233
|
+
dirpath=self.args['work-dir'], filename='lint_only.sh',
|
|
234
|
+
command_lists=self.lint_only_command_lists, line_breaks=True
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
if self.args.get('lint-only', False):
|
|
238
|
+
sim_cmd_lists = []
|
|
239
|
+
else:
|
|
240
|
+
sim_cmd_lists = self.verilated_exec_command_lists + \
|
|
241
|
+
(self.verilated_post_exec_coverage_command_lists
|
|
242
|
+
if self.args.get('coverage', True) else [])
|
|
173
243
|
|
|
174
244
|
self.write_sh_scripts_to_work_dir(
|
|
175
245
|
compile_lists=self.verilate_command_lists,
|
|
@@ -177,6 +247,125 @@ class VerilatorSim(CommandSim, ToolVerilator):
|
|
|
177
247
|
simulate_lists=sim_cmd_lists
|
|
178
248
|
)
|
|
179
249
|
|
|
250
|
+
if self.docker_arg_set:
|
|
251
|
+
self.prepare_compile_docker()
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def prepare_compile_docker(self) -> None:
|
|
255
|
+
'''Takes existing generated shell scripts, and saves out different ones.
|
|
256
|
+
|
|
257
|
+
will be used in compile() and simulate() steps.
|
|
258
|
+
|
|
259
|
+
1. Assume the existing compile.sh exists.
|
|
260
|
+
a. Create docker_wrap_compile.sh that has:
|
|
261
|
+
docker [run|exec] --entrypoint /bin/bash IMAGE \
|
|
262
|
+
-c "cd WORK-DIR && ./copmile.sh"
|
|
263
|
+
b. where compile.sh is
|
|
264
|
+
i. The original contents from self.verilate_command_lists, but with
|
|
265
|
+
'verilator' instead of '/path/to/verilator', which was handled
|
|
266
|
+
elsewhere looking at self.args['docker']
|
|
267
|
+
|
|
268
|
+
2. Assume simulate.sh exists (or not)
|
|
269
|
+
a. Create docker_wrap_simulate.sh that has:
|
|
270
|
+
docker [run|exec] --entrypoint /bin/bash IMAGE \
|
|
271
|
+
-c "cd WORK-DIR && ./in_docker_simulate.sh"
|
|
272
|
+
b. simulate.sh unchanged, should already have the coverage commands
|
|
273
|
+
|
|
274
|
+
3. Overwrite all.sh to call:
|
|
275
|
+
- docker_wrap_compile.sh
|
|
276
|
+
- docker_wrap_simulate.sh
|
|
277
|
+
|
|
278
|
+
4. Destroy the self.*_command_lists so they point to the bash scripts.
|
|
279
|
+
'''
|
|
280
|
+
if not self.docker_arg_set:
|
|
281
|
+
return
|
|
282
|
+
|
|
283
|
+
# TODO(drew): Windows friendly? Probably not. a lot of ./ going on here.
|
|
284
|
+
|
|
285
|
+
work_dir_abs = Path(self.args['work-dir']).resolve()
|
|
286
|
+
|
|
287
|
+
docker_command = 'run'
|
|
288
|
+
docker_run_base_cmd = get_docker_run_command(
|
|
289
|
+
image=self.args['docker-image'],
|
|
290
|
+
docker_command=docker_command,
|
|
291
|
+
env_dict={'CCACHE_DIR': '/tmp/ccache'}, # For macos verilator compatibility
|
|
292
|
+
ro_volumes=get_source_files_paths(cmd_des_obj=self, minimal_root_paths=True),
|
|
293
|
+
rw_volumes=[work_dir_abs],
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
util.write_shell_command_file(
|
|
297
|
+
dirpath=self.args['work-dir'],
|
|
298
|
+
filename='docker_wrap_compile.sh',
|
|
299
|
+
command_lists=[
|
|
300
|
+
util.ShellCommandList(docker_run_base_cmd + [
|
|
301
|
+
'-c', f'\'cd {work_dir_abs} && ./compile.sh\'',
|
|
302
|
+
], tee_fpath='compile.log')
|
|
303
|
+
],
|
|
304
|
+
line_breaks=False
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
util.write_shell_command_file(
|
|
308
|
+
dirpath=self.args['work-dir'],
|
|
309
|
+
filename='docker_wrap_lint_only.sh',
|
|
310
|
+
command_lists=[
|
|
311
|
+
util.ShellCommandList(docker_run_base_cmd + [
|
|
312
|
+
'-c', f'\'cd {work_dir_abs} && ./lint_only.sh\'',
|
|
313
|
+
], tee_fpath='lint_only.log')
|
|
314
|
+
],
|
|
315
|
+
line_breaks=False
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
util.write_shell_command_file(
|
|
319
|
+
dirpath=self.args['work-dir'],
|
|
320
|
+
filename='docker_wrap_simulate.sh',
|
|
321
|
+
command_lists=[
|
|
322
|
+
util.ShellCommandList(docker_run_base_cmd + [
|
|
323
|
+
'-c', f'\'cd {work_dir_abs} && ./simulate.sh\'',
|
|
324
|
+
], tee_fpath='sim.log')
|
|
325
|
+
],
|
|
326
|
+
line_breaks=False
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
all_lists = [] # list - of - (command-list)
|
|
331
|
+
if self.has_pre_compile_dep_shell_commands:
|
|
332
|
+
all_lists.append(['./pre_compile_dep_shell_commands.sh'])
|
|
333
|
+
if self.args.get('lint-only', False):
|
|
334
|
+
all_lists.append(['./docker_wrap_lint_only.sh'])
|
|
335
|
+
else:
|
|
336
|
+
all_lists.append(['./docker_wrap_compile.sh'])
|
|
337
|
+
all_lists.append(['./docker_wrap_simulate.sh'])
|
|
338
|
+
if self.has_post_tool_dep_shell_commands:
|
|
339
|
+
all_lists.append(['./post_tool_dep_shell_commands.sh'])
|
|
340
|
+
|
|
341
|
+
util.write_shell_command_file(
|
|
342
|
+
dirpath=self.args['work-dir'], filename='all.sh',
|
|
343
|
+
command_lists=all_lists, line_breaks=True
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
# Overwrite our command lists so compile(), simulate() work correctly.
|
|
347
|
+
if self.verilate_command_lists:
|
|
348
|
+
self.verilate_command_lists = [
|
|
349
|
+
util.ShellCommandList(
|
|
350
|
+
['./docker_wrap_compile.sh'], tee_fpath='docker_wrap_compile.log'
|
|
351
|
+
)
|
|
352
|
+
]
|
|
353
|
+
if self.lint_only_command_lists:
|
|
354
|
+
self.lint_only_command_lists = [
|
|
355
|
+
util.ShellCommandList(
|
|
356
|
+
['./docker_wrap_lint_only.sh'], tee_fpath='docker_wrap_lint_only.log'
|
|
357
|
+
)
|
|
358
|
+
]
|
|
359
|
+
if self.verilated_exec_command_lists:
|
|
360
|
+
self.verilated_exec_command_lists = [
|
|
361
|
+
util.ShellCommandList(
|
|
362
|
+
['./docker_wrap_simulate.sh'], tee_fpath='docker_wrap_simulate.log'
|
|
363
|
+
)
|
|
364
|
+
]
|
|
365
|
+
self.verilated_post_exec_coverage_command_lists = [ ] # clear, in docker_wrap_simulate
|
|
366
|
+
|
|
367
|
+
return
|
|
368
|
+
|
|
180
369
|
|
|
181
370
|
def compile(self):
|
|
182
371
|
if self.args['stop-before-compile']:
|
opencos/tools/vivado.py
CHANGED
opencos/tools/yosys.py
CHANGED
|
@@ -9,11 +9,13 @@ import os
|
|
|
9
9
|
import subprocess
|
|
10
10
|
|
|
11
11
|
from opencos import util, eda_config
|
|
12
|
-
from opencos.commands import CommandSynth, CommandLec
|
|
12
|
+
from opencos.commands import CommandSynth, CommandLec, CommandFList
|
|
13
13
|
from opencos.eda_base import Tool, get_eda_exec
|
|
14
14
|
from opencos.files import safe_shutil_which
|
|
15
15
|
from opencos.utils.markup_helpers import yaml_safe_load
|
|
16
16
|
|
|
17
|
+
from opencos.commands.sim import parameters_dict_get_command_list
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
def get_commands_to_run_scriptfiles(
|
|
19
21
|
script_fnames_list: list, yosys_exe: str
|
|
@@ -37,6 +39,63 @@ def get_commands_to_run_scriptfiles(
|
|
|
37
39
|
return yosys_cmdlists
|
|
38
40
|
|
|
39
41
|
|
|
42
|
+
|
|
43
|
+
def get_yosys_defines_incdirs_files(
|
|
44
|
+
command_design_obj,
|
|
45
|
+
for_synthesis: bool = True,
|
|
46
|
+
**kwargs,
|
|
47
|
+
) -> list:
|
|
48
|
+
'''
|
|
49
|
+
Returns a partial list of all the args for a read_verilog or read_slang command in yosys
|
|
50
|
+
Handles defines, incdirs, files_sv, files_v
|
|
51
|
+
|
|
52
|
+
command_design_obj is intended to be a opencos.eda_base.CommandDesign or derived class
|
|
53
|
+
object.
|
|
54
|
+
|
|
55
|
+
This should be used by CommandFList or CommandSynth derivations for yosys tools:
|
|
56
|
+
*Yosys, *SlangYosys
|
|
57
|
+
|
|
58
|
+
Valid kwargs bools (default True if ommitted) - defines, incdirs, verilog, systemverilog, top
|
|
59
|
+
'''
|
|
60
|
+
|
|
61
|
+
ret_list = []
|
|
62
|
+
|
|
63
|
+
defines = getattr(command_design_obj, 'defines', {})
|
|
64
|
+
incdirs = getattr(command_design_obj, 'incdirs', [])
|
|
65
|
+
files_v = getattr(command_design_obj, 'files_v', [])
|
|
66
|
+
files_sv = getattr(command_design_obj, 'files_sv', [])
|
|
67
|
+
top = getattr(command_design_obj, 'args', {}).get('top', '')
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
if kwargs.get('defines', True):
|
|
71
|
+
for name, value in defines.items():
|
|
72
|
+
if not name:
|
|
73
|
+
continue
|
|
74
|
+
if for_synthesis and name in ['SIMULATION']:
|
|
75
|
+
continue
|
|
76
|
+
|
|
77
|
+
if value is None:
|
|
78
|
+
ret_list.append(f'--define-macro {name}')
|
|
79
|
+
else:
|
|
80
|
+
ret_list.append(f'--define-macro {name}={value}')
|
|
81
|
+
|
|
82
|
+
# We must define SYNTHESIS for oclib_defines.vh to work correctly.
|
|
83
|
+
if for_synthesis and 'SYNTHESIS' not in defines:
|
|
84
|
+
ret_list.append('--define-macro SYNTHESIS')
|
|
85
|
+
|
|
86
|
+
if kwargs.get('incdirs', True):
|
|
87
|
+
for path in incdirs:
|
|
88
|
+
ret_list.append(f'-I {path}')
|
|
89
|
+
if kwargs.get('verilog', True):
|
|
90
|
+
ret_list.extend(files_v)
|
|
91
|
+
if kwargs.get('systemverilog', True):
|
|
92
|
+
ret_list.extend(files_sv)
|
|
93
|
+
if kwargs.get('top', True) and top:
|
|
94
|
+
ret_list.append(f'--top {top}')
|
|
95
|
+
|
|
96
|
+
return ret_list
|
|
97
|
+
|
|
98
|
+
|
|
40
99
|
class ToolYosys(Tool):
|
|
41
100
|
'''Parent class for ToolTabbyCadYosys, ToolInvioYosys, ToolSlangYosys'''
|
|
42
101
|
|
|
@@ -48,7 +107,7 @@ class ToolYosys(Tool):
|
|
|
48
107
|
sta_exe = ''
|
|
49
108
|
sta_version = ''
|
|
50
109
|
|
|
51
|
-
def get_versions(self) -> str:
|
|
110
|
+
def get_versions(self, **kwargs) -> str:
|
|
52
111
|
if self._VERSION:
|
|
53
112
|
return self._VERSION
|
|
54
113
|
|
|
@@ -478,34 +537,7 @@ class CommonSynthYosys(CommandSynth, ToolYosys):
|
|
|
478
537
|
|
|
479
538
|
Handles defines, incdirs, files_sv, files_v
|
|
480
539
|
'''
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
for name,value in self.defines.items():
|
|
484
|
-
if not name:
|
|
485
|
-
continue
|
|
486
|
-
if name in ['SIMULATION']:
|
|
487
|
-
continue
|
|
488
|
-
|
|
489
|
-
if value is None:
|
|
490
|
-
ret_list.append(f'--define-macro {name}')
|
|
491
|
-
else:
|
|
492
|
-
ret_list.append(f'--define-macro {name}={value}')
|
|
493
|
-
|
|
494
|
-
# We must define SYNTHESIS for oclib_defines.vh to work correctly.
|
|
495
|
-
if 'SYNTHESIS' not in self.defines:
|
|
496
|
-
ret_list.append('--define-macro SYNTHESIS')
|
|
497
|
-
|
|
498
|
-
for path in self.incdirs:
|
|
499
|
-
ret_list.append(f'-I {path}')
|
|
500
|
-
|
|
501
|
-
for path in self.files_v:
|
|
502
|
-
ret_list.append(path)
|
|
503
|
-
|
|
504
|
-
for path in self.files_sv:
|
|
505
|
-
ret_list.append(path)
|
|
506
|
-
|
|
507
|
-
ret_list.append(f'--top {self.args["top"]}')
|
|
508
|
-
return ret_list
|
|
540
|
+
return get_yosys_defines_incdirs_files(command_design_obj=self, for_synthesis=True)
|
|
509
541
|
|
|
510
542
|
|
|
511
543
|
class CommandLecYosys(CommandLec, ToolYosys):
|
|
@@ -742,3 +774,96 @@ class CommandLecYosys(CommandLec, ToolYosys):
|
|
|
742
774
|
lec_cmd_list = 'yosys --scriptfile yosys_lec.f'.split()
|
|
743
775
|
util.info(f'LEC running {lec_cmd_list}')
|
|
744
776
|
self.exec(self.args['work-dir'], lec_cmd_list)
|
|
777
|
+
|
|
778
|
+
|
|
779
|
+
class CommonFListYosys(CommandFList, ToolYosys):
|
|
780
|
+
'''
|
|
781
|
+
Handler for: eda flist --tool=yosys
|
|
782
|
+
|
|
783
|
+
This will create a eda.yosys_read_verilog.f flist (or to std-out if --print-to-stdout),
|
|
784
|
+
suitable for args passed to a "read_verilog" command in yosys, such as:
|
|
785
|
+
|
|
786
|
+
read_verilog -f FILE_CREATED_BY_THIS_HANDLER [other args]
|
|
787
|
+
|
|
788
|
+
'''
|
|
789
|
+
def __init__(self, config: dict, **kwargs):
|
|
790
|
+
CommandFList.__init__(self, config=config,
|
|
791
|
+
# Added bonus - remove some CommandFList args that we don't
|
|
792
|
+
# need:
|
|
793
|
+
include_prefix_args=False, include_quote_args=False,
|
|
794
|
+
include_format_define_args=False)
|
|
795
|
+
ToolYosys.__init__(self, config=self.config)
|
|
796
|
+
|
|
797
|
+
self.args.update({
|
|
798
|
+
'force': True, # always overwrite the output
|
|
799
|
+
'out': 'eda_flist.yosys.read_verilog.f',
|
|
800
|
+
|
|
801
|
+
'emit-define' : True,
|
|
802
|
+
'emit-parameter' : True,
|
|
803
|
+
'emit-incdir' : True,
|
|
804
|
+
'emit-plusargs' : True,
|
|
805
|
+
'emit-v' : True,
|
|
806
|
+
'emit-sv' : True,
|
|
807
|
+
'emit-vhd' : True,
|
|
808
|
+
'emit-cpp' : False,
|
|
809
|
+
'emit-non-sources' : False, # as comments, from DEPS 'reqs'
|
|
810
|
+
})
|
|
811
|
+
|
|
812
|
+
def get_flist_plusargs_list(self) -> list:
|
|
813
|
+
'''Overriden from CommandFList.'''
|
|
814
|
+
if self.args['unprocessed-plusargs']:
|
|
815
|
+
util.warning(f'Command "flist" for --tool={self._TOOL} is not intended for simulation',
|
|
816
|
+
'and plusargs were present. They will NOT be included in the flist:',
|
|
817
|
+
f'{self.args["unprocessed-plusargs"]}')
|
|
818
|
+
|
|
819
|
+
return []
|
|
820
|
+
|
|
821
|
+
def get_write_flist_lines(
|
|
822
|
+
self, add_comment_lines: bool = False
|
|
823
|
+
) -> list:
|
|
824
|
+
'''Override from CommandFList'''
|
|
825
|
+
|
|
826
|
+
# Want: defines + parameters + incdirs + files + --top=VALUE, similar to
|
|
827
|
+
# how we call CommonSynthYosys.get_yosys_read_verilog_defines_incdirs_files(),
|
|
828
|
+
# but without the additional args
|
|
829
|
+
|
|
830
|
+
ret = []
|
|
831
|
+
|
|
832
|
+
# Use our overriden method to post warnings about brining simulation Plusargs to
|
|
833
|
+
# a Yosys tool:
|
|
834
|
+
_ = self.get_flist_plusargs_list()
|
|
835
|
+
|
|
836
|
+
if add_comment_lines:
|
|
837
|
+
ret.append(f"## {self.args=}")
|
|
838
|
+
|
|
839
|
+
if self.files_non_source:
|
|
840
|
+
ret.append('## reqs (non-source files that are dependencies):')
|
|
841
|
+
for f in self.files_non_source:
|
|
842
|
+
if self.args['emit-rel-path']:
|
|
843
|
+
f = os.path.relpath(f)
|
|
844
|
+
ret.append(f'## {f}')
|
|
845
|
+
|
|
846
|
+
# Note - top is included in this:
|
|
847
|
+
include_items = []
|
|
848
|
+
if self.args['emit-define']:
|
|
849
|
+
include_items.append('defines')
|
|
850
|
+
if self.args['emit-incdir']:
|
|
851
|
+
include_items.append('incdirs')
|
|
852
|
+
|
|
853
|
+
ret.extend(get_yosys_defines_incdirs_files(
|
|
854
|
+
command_design_obj=self,
|
|
855
|
+
for_synthesis=True,
|
|
856
|
+
# True/False kwargs if you want that emitted:
|
|
857
|
+
defines=self.args['emit-define'],
|
|
858
|
+
incdirs=self.args['emit-incdir'],
|
|
859
|
+
verilog=self.args['emit-v'],
|
|
860
|
+
systemverilog=self.args['emit-sv'],
|
|
861
|
+
top=True
|
|
862
|
+
))
|
|
863
|
+
|
|
864
|
+
# and parameters:
|
|
865
|
+
ret.extend(parameters_dict_get_command_list(
|
|
866
|
+
params=self.parameters, arg_prefix='-G '
|
|
867
|
+
))
|
|
868
|
+
|
|
869
|
+
return ret
|
opencos/util.py
CHANGED
|
@@ -20,6 +20,7 @@ from importlib import import_module
|
|
|
20
20
|
from dotenv import load_dotenv
|
|
21
21
|
from supports_color import supportsColor
|
|
22
22
|
|
|
23
|
+
import opencos
|
|
23
24
|
from opencos.files import safe_shutil_which
|
|
24
25
|
from opencos.utils import status_constants
|
|
25
26
|
from opencos.utils.str_helpers import strip_ansi_color
|
|
@@ -359,7 +360,10 @@ def get_argparser() -> argparse.ArgumentParser:
|
|
|
359
360
|
# boolean actions:
|
|
360
361
|
bool_action_kwargs = get_argparse_bool_action_kwargs()
|
|
361
362
|
|
|
362
|
-
parser.add_argument('--version', default=False, action='store_true'
|
|
363
|
+
parser.add_argument('--version', default=False, action='store_true',
|
|
364
|
+
help=('Shows our version:'
|
|
365
|
+
f' {opencos.__version__} ({opencos.__pyproject_name__})')
|
|
366
|
+
)
|
|
363
367
|
parser.add_argument('--color', **bool_action_kwargs, default=bool(supportsColor.stdout),
|
|
364
368
|
help='Use shell colors for info/warning/error messaging')
|
|
365
369
|
parser.add_argument('--emoji', **bool_action_kwargs, default=args['emoji'],
|