opencos-eda 0.2.53__tar.gz → 0.2.54__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.53/opencos_eda.egg-info → opencos_eda-0.2.54}/PKG-INFO +1 -1
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/commands/flist.py +1 -1
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/commands/sim.py +44 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/eda_base.py +19 -14
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/test_eda.py +1 -1
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/cocotb.py +7 -15
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/iverilog.py +4 -24
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/modelsim_ase.py +3 -6
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/quartus.py +124 -82
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/questa.py +5 -16
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/verilator.py +9 -15
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/vivado.py +27 -20
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/util.py +70 -13
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/utils/status_constants.py +1 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54/opencos_eda.egg-info}/PKG-INFO +1 -1
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/pyproject.toml +1 -1
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/LICENSE +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/LICENSE.spdx +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/README.md +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/__init__.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/_version.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/_waves_pkg.sv +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/commands/__init__.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/commands/build.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/commands/deps_help.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/commands/elab.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/commands/export.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/commands/lec.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/commands/multi.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/commands/open.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/commands/proj.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/commands/shell.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/commands/sweep.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/commands/synth.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/commands/targets.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/commands/upload.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/commands/waves.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/deps/__init__.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/deps/defaults.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/deps/deps_commands.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/deps/deps_file.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/deps/deps_processor.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/deps_schema.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/eda.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/eda_config.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/eda_config_defaults.yml +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/eda_config_max_verilator_waivers.yml +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/eda_config_reduced.yml +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/eda_deps_bash_completion.bash +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/eda_deps_sanitize.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/eda_extract_targets.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/eda_tool_helper.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/export_helper.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/export_json_convert.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/files.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/hw/__init__.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/hw/oc_cli.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/hw/pcie.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/names.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/peakrdl_cleanup.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/seed.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/__init__.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/custom_config.yml +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/deps_files/command_order/DEPS.yml +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/deps_files/error_msgs/DEPS.yml +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/deps_files/iverilog_test/DEPS.yml +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/deps_files/no_deps_here/DEPS.yml +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/deps_files/non_sv_reqs/DEPS.yml +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/deps_files/tags_with_tools/DEPS.yml +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/deps_files/test_err_fatal/DEPS.yml +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/helpers.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/test_build.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/test_deps_helpers.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/test_deps_schema.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/test_eda_elab.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/test_eda_synth.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/test_oc_cli.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tests/test_tools.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/__init__.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/invio.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/invio_helpers.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/invio_yosys.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/questa_fse.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/riviera.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/slang.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/slang_yosys.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/surelog.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/tabbycad_yosys.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/tools/yosys.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/utils/__init__.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/utils/markup_helpers.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/utils/str_helpers.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/utils/subprocess_helpers.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/utils/vscode_helper.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos/utils/vsim_helper.py +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos_eda.egg-info/SOURCES.txt +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos_eda.egg-info/dependency_links.txt +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos_eda.egg-info/entry_points.txt +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos_eda.egg-info/requires.txt +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/opencos_eda.egg-info/top_level.txt +0 -0
- {opencos_eda-0.2.53 → opencos_eda-0.2.54}/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.54
|
|
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
|
|
@@ -355,6 +355,50 @@ class CommandSim(CommandDesign):
|
|
|
355
355
|
error_code=status_constants.EDA_SIM_LOG_MISSING_MUST_STRING
|
|
356
356
|
)
|
|
357
357
|
|
|
358
|
+
def write_sh_scripts_to_work_dir(
|
|
359
|
+
self, compile_lists: list, elaborate_lists: list, simulate_lists: list,
|
|
360
|
+
compile_line_breaks: bool = True,
|
|
361
|
+
elaborate_line_breaks: bool = False,
|
|
362
|
+
simulate_line_breaks: bool = False,
|
|
363
|
+
simulate_sh_fname: str = 'simulate.sh'
|
|
364
|
+
) -> None:
|
|
365
|
+
'''Writes compile.sh, elaborate.sh, simulate.sh (if present), all.sh to work-dir
|
|
366
|
+
|
|
367
|
+
Will include the pre_compile_dep_shell_commands.sh if those are present.
|
|
368
|
+
compile_line_breaks defaults to True (one word per line w/ line breaks added)
|
|
369
|
+
'''
|
|
370
|
+
|
|
371
|
+
all_lists = [] # list - of - (command-list)
|
|
372
|
+
if self.has_dep_shell_commands:
|
|
373
|
+
all_lists = [
|
|
374
|
+
['./pre_compile_dep_shell_commands.sh']
|
|
375
|
+
]
|
|
376
|
+
|
|
377
|
+
if compile_lists:
|
|
378
|
+
util.write_shell_command_file(dirpath=self.args['work-dir'], filename='compile.sh',
|
|
379
|
+
command_lists=compile_lists,
|
|
380
|
+
line_breaks=compile_line_breaks)
|
|
381
|
+
all_lists.append(['./compile.sh'])
|
|
382
|
+
|
|
383
|
+
if elaborate_lists:
|
|
384
|
+
util.write_shell_command_file(dirpath=self.args['work-dir'], filename='elaborate.sh',
|
|
385
|
+
command_lists=elaborate_lists,
|
|
386
|
+
line_breaks=elaborate_line_breaks)
|
|
387
|
+
all_lists.append(['./elaborate.sh'])
|
|
388
|
+
|
|
389
|
+
if simulate_lists:
|
|
390
|
+
util.write_shell_command_file(dirpath=self.args['work-dir'], filename=simulate_sh_fname,
|
|
391
|
+
command_lists=simulate_lists,
|
|
392
|
+
line_breaks=simulate_line_breaks)
|
|
393
|
+
all_lists.append(['./' + simulate_sh_fname])
|
|
394
|
+
|
|
395
|
+
util.write_shell_command_file(dirpath=self.args['work-dir'], filename='all.sh',
|
|
396
|
+
command_lists=all_lists)
|
|
397
|
+
|
|
398
|
+
self.write_eda_config_and_args()
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
|
|
358
402
|
# Methods that derived classes must override:
|
|
359
403
|
|
|
360
404
|
def compile(self) -> None:
|
|
@@ -252,7 +252,7 @@ class Command: # pylint: disable=too-many-public-methods
|
|
|
252
252
|
})
|
|
253
253
|
self.modified_args = {}
|
|
254
254
|
self.config = copy.deepcopy(config) # avoid external modifications.
|
|
255
|
-
self.target = ""
|
|
255
|
+
self.target = "" # is set as the 'top' or final target short-name (no path info)
|
|
256
256
|
self.target_path = ""
|
|
257
257
|
self.status = 0
|
|
258
258
|
self.errors_log_f = None
|
|
@@ -943,6 +943,8 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
943
943
|
self.targets_dict = {} # key = targets that we've already processed in DEPS files
|
|
944
944
|
self.last_added_source_file_inferred_top = ''
|
|
945
945
|
|
|
946
|
+
self.has_dep_shell_commands = False
|
|
947
|
+
|
|
946
948
|
|
|
947
949
|
def run_dep_commands(self) -> None:
|
|
948
950
|
'''Run shell/peakrdl style commands from DEPS files
|
|
@@ -993,10 +995,12 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
993
995
|
|
|
994
996
|
d['exec_list'] = clist # update to tee_fpath is set.
|
|
995
997
|
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
998
|
+
if all_cmds_lists:
|
|
999
|
+
util.write_shell_command_file(
|
|
1000
|
+
dirpath=self.args['work-dir'], filename='pre_compile_dep_shell_commands.sh',
|
|
1001
|
+
command_lists=all_cmds_lists
|
|
1002
|
+
)
|
|
1003
|
+
self.has_dep_shell_commands = True
|
|
1000
1004
|
|
|
1001
1005
|
for i, d in enumerate(self.dep_shell_commands):
|
|
1002
1006
|
util.info(f'run_dep_shell_commands {i=}: {d=}')
|
|
@@ -1556,11 +1560,12 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1556
1560
|
|
|
1557
1561
|
# handle a missing self.args['top'] with last filepath or last target:
|
|
1558
1562
|
if not self.args.get('top', ''):
|
|
1563
|
+
top_path = ''
|
|
1559
1564
|
if not last_potential_top_isfile and last_potential_top_target[0]:
|
|
1560
1565
|
# If we have a target name from DEPS, prefer to use that.
|
|
1561
|
-
self.args['top'],
|
|
1566
|
+
self.args['top'], top_path = last_potential_top_target
|
|
1562
1567
|
util.info("--top not specified, inferred from target:",
|
|
1563
|
-
f"{self.args['top']} ({
|
|
1568
|
+
f"{self.args['top']} ({top_path})")
|
|
1564
1569
|
|
|
1565
1570
|
else:
|
|
1566
1571
|
best_top_fname = self.last_added_source_file_inferred_top
|
|
@@ -1570,26 +1575,29 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1570
1575
|
if not self.args['top'] and last_potential_top_file[0]:
|
|
1571
1576
|
# If we don't have a target name, and no top name yet, then go looking for the
|
|
1572
1577
|
# module name in the final source file added.
|
|
1573
|
-
|
|
1578
|
+
top_path = last_potential_top_file[1] # from tuple: (top, fpath)
|
|
1574
1579
|
self.args['top'] = util.get_inferred_top_module_name(
|
|
1575
1580
|
module_guess=last_potential_top_file[0],
|
|
1576
1581
|
module_fpath=last_potential_top_file[1]
|
|
1577
1582
|
)
|
|
1578
1583
|
if self.args['top']:
|
|
1579
1584
|
util.info("--top not specified, inferred from final source file:",
|
|
1580
|
-
f"{self.args['top']} ({
|
|
1585
|
+
f"{self.args['top']} ({top_path})")
|
|
1581
1586
|
# If top wasn't set, and we're using the final command-line 'arg' filename
|
|
1582
1587
|
# (not from DEPS.yml) we need to override self.target if that was set. Otherwise
|
|
1583
1588
|
# it won't save to the correct work-dir:
|
|
1584
1589
|
self.target = self.args['top']
|
|
1585
1590
|
|
|
1591
|
+
|
|
1592
|
+
util.info(f'{self.command_name}: top-most target name: {self.target}')
|
|
1593
|
+
|
|
1586
1594
|
if self.error_on_missing_top and not self.args.get('top', ''):
|
|
1587
1595
|
self.error("Did not get a --top or DEPS top, required to run command",
|
|
1588
1596
|
f"'{self.command_name}' for tool={self.args.get('tool', None)}",
|
|
1589
1597
|
error_code=status_constants.EDA_COMMAND_MISSING_TOP)
|
|
1590
1598
|
|
|
1591
1599
|
if self.tool_changed_respawn:
|
|
1592
|
-
util.
|
|
1600
|
+
util.info(
|
|
1593
1601
|
'CommandDesign: need to respawn due to tool change to',
|
|
1594
1602
|
f'\'{self.tool_changed_respawn["tool"]}\' from',
|
|
1595
1603
|
f'\'{self.tool_changed_respawn["orig_tool"]}\'',
|
|
@@ -1615,7 +1623,7 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1615
1623
|
for k,v in self.args.items():
|
|
1616
1624
|
|
|
1617
1625
|
# Some args cannot be extracted and work, so omit these:
|
|
1618
|
-
if k in
|
|
1626
|
+
if k in remove_args:
|
|
1619
1627
|
continue
|
|
1620
1628
|
if any(k.startswith(x) for x in remove_args_startswith):
|
|
1621
1629
|
continue
|
|
@@ -1637,9 +1645,6 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1637
1645
|
return ret
|
|
1638
1646
|
|
|
1639
1647
|
|
|
1640
|
-
#_THREADS_START = 0
|
|
1641
|
-
#_THREADS_DONE = 0
|
|
1642
|
-
|
|
1643
1648
|
class ThreadStats:
|
|
1644
1649
|
'''To avoid globals for two ints, keep a class holder so CommandParallel and
|
|
1645
1650
|
CommandParallelWorker can share values'''
|
|
@@ -170,7 +170,7 @@ class TestsRequiresVerilator( # pylint: disable=too-many-public-methods
|
|
|
170
170
|
assert res.stderr == b''
|
|
171
171
|
|
|
172
172
|
res = subprocess.run(
|
|
173
|
-
[ './
|
|
173
|
+
[ './simulate.sh' ], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
174
174
|
check=True
|
|
175
175
|
)
|
|
176
176
|
rc = res.returncode
|
|
@@ -122,20 +122,12 @@ class CommandSimCocotb(CommandSim, ToolCocotb):
|
|
|
122
122
|
util.safe_mkdirs(base=self.args['work-dir'], new_dirs=paths)
|
|
123
123
|
|
|
124
124
|
# Write shell scripts
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
util.write_shell_command_file(
|
|
133
|
-
dirpath=self.args['work-dir'],
|
|
134
|
-
filename='all.sh',
|
|
135
|
-
command_lists=[
|
|
136
|
-
['./pre_compile_dep_shell_commands.sh'],
|
|
137
|
-
['./cocotb_test.sh'],
|
|
138
|
-
]
|
|
125
|
+
self.write_sh_scripts_to_work_dir(
|
|
126
|
+
compile_lists=[],
|
|
127
|
+
elaborate_lists=[],
|
|
128
|
+
simulate_lists=self.cocotb_command_lists,
|
|
129
|
+
simulate_line_breaks=True,
|
|
130
|
+
simulate_sh_fname='cocotb_test.sh'
|
|
139
131
|
)
|
|
140
132
|
|
|
141
133
|
def _find_cocotb_test_files(self):
|
|
@@ -317,7 +309,7 @@ def run_cocotb_test():
|
|
|
317
309
|
runner = get_runner(simulator)
|
|
318
310
|
|
|
319
311
|
build_args = []
|
|
320
|
-
|
|
312
|
+
|
|
321
313
|
if simulator == "verilator":
|
|
322
314
|
build_args.extend({list(self.args.get('verilate-args', []))!r})
|
|
323
315
|
|
|
@@ -84,32 +84,12 @@ class CommandSimIverilog(CommandSim, ToolIverilog):
|
|
|
84
84
|
|
|
85
85
|
paths = ['logs']
|
|
86
86
|
util.safe_mkdirs(base=self.args['work-dir'], new_dirs=paths)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
command_lists=self.iverilog_command_lists,
|
|
92
|
-
line_breaks=True
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
util.write_shell_command_file(
|
|
96
|
-
dirpath=self.args['work-dir'],
|
|
97
|
-
filename='simulate_only.sh',
|
|
98
|
-
command_lists=self.iverilog_exec_command_lists
|
|
87
|
+
self.write_sh_scripts_to_work_dir(
|
|
88
|
+
compile_lists=self.iverilog_command_lists,
|
|
89
|
+
elaborate_lists=[],
|
|
90
|
+
simulate_lists=self.iverilog_exec_command_lists
|
|
99
91
|
)
|
|
100
92
|
|
|
101
|
-
util.write_shell_command_file(
|
|
102
|
-
dirpath=self.args['work-dir'],
|
|
103
|
-
filename='all.sh',
|
|
104
|
-
command_lists = [
|
|
105
|
-
['./pre_compile_dep_shell_commands.sh'],
|
|
106
|
-
['./compile_only.sh'],
|
|
107
|
-
['./simulate_only.sh'],
|
|
108
|
-
]
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
self.write_eda_config_and_args()
|
|
112
|
-
|
|
113
93
|
def compile(self):
|
|
114
94
|
if self.args['stop-before-compile']:
|
|
115
95
|
return
|
|
@@ -82,15 +82,12 @@ class CommandSimModelsimAse(CommandSim, ToolModelsimAse):
|
|
|
82
82
|
command_lists=vsim_command_lists
|
|
83
83
|
)
|
|
84
84
|
|
|
85
|
+
# Write simulate.sh and all.sh to work-dir:
|
|
85
86
|
vsim_command_lists = self.get_simulate_command_lists()
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
filename='all.sh',
|
|
89
|
-
command_lists = [['./pre_compile_dep_shell_commands.sh']] + vsim_command_lists
|
|
87
|
+
self.write_sh_scripts_to_work_dir(
|
|
88
|
+
compile_lists=[], elaborate_lists=[], simulate_lists=vsim_command_lists
|
|
90
89
|
)
|
|
91
90
|
|
|
92
|
-
self.write_eda_config_and_args()
|
|
93
|
-
|
|
94
91
|
def compile(self):
|
|
95
92
|
if self.args['stop-before-compile']:
|
|
96
93
|
# don't run anything, save everyting we've already run in _prep_compile()
|
|
@@ -30,12 +30,13 @@ class ToolQuartus(Tool):
|
|
|
30
30
|
quartus_release = None
|
|
31
31
|
quartus_base_path = ''
|
|
32
32
|
quartus_exe = ''
|
|
33
|
+
quartus_gui_exe = ''
|
|
33
34
|
|
|
34
35
|
def __init__(self, config: dict):
|
|
35
36
|
super().__init__(config=config)
|
|
36
37
|
self.args.update({
|
|
37
|
-
'part': '
|
|
38
|
-
'family': '
|
|
38
|
+
'part': 'A3CY135BM16AE6S',
|
|
39
|
+
'family': 'Agilex 3',
|
|
39
40
|
})
|
|
40
41
|
self.args_help.update({
|
|
41
42
|
'part': 'Device used for commands: synth, build.',
|
|
@@ -53,6 +54,7 @@ class ToolQuartus(Tool):
|
|
|
53
54
|
else:
|
|
54
55
|
self.quartus_exe = path
|
|
55
56
|
self.quartus_base_path, _ = os.path.split(path)
|
|
57
|
+
self.quartus_gui_exe = shutil.which('quartus') # vs quartus_sh
|
|
56
58
|
|
|
57
59
|
|
|
58
60
|
|
|
@@ -157,15 +159,15 @@ class CommandSynthQuartus(CommandSynth, ToolQuartus):
|
|
|
157
159
|
# Add artifact tracking
|
|
158
160
|
util.artifacts.add_extension(
|
|
159
161
|
search_paths=self.args['work-dir'], file_extension='qpf',
|
|
160
|
-
typ='
|
|
162
|
+
typ='tcl', description='Quartus Project File'
|
|
161
163
|
)
|
|
162
164
|
util.artifacts.add_extension(
|
|
163
165
|
search_paths=self.args['work-dir'], file_extension='qsf',
|
|
164
|
-
typ='
|
|
166
|
+
typ='tcl', description='Quartus Settings File'
|
|
165
167
|
)
|
|
166
168
|
util.artifacts.add_extension(
|
|
167
169
|
search_paths=self.args['work-dir'], file_extension='rpt',
|
|
168
|
-
typ='
|
|
170
|
+
typ='text', description='Quartus Synthesis Report'
|
|
169
171
|
)
|
|
170
172
|
|
|
171
173
|
self.exec(self.args['work-dir'], command_list)
|
|
@@ -187,27 +189,9 @@ class CommandSynthQuartus(CommandSynth, ToolQuartus):
|
|
|
187
189
|
f"set_global_assignment -name TOP_LEVEL_ENTITY {top}",
|
|
188
190
|
]
|
|
189
191
|
|
|
190
|
-
# Create a symbolic link or copy the include file to resolve lib/ paths
|
|
191
|
-
for incdir in self.incdirs:
|
|
192
|
-
if 'lib' in incdir:
|
|
193
|
-
lib_defines = os.path.join(incdir, 'oclib_defines.vh')
|
|
194
|
-
if os.path.exists(lib_defines):
|
|
195
|
-
# Copy the include file to the work directory as lib/oclib_defines.vh
|
|
196
|
-
work_lib_dir = os.path.join(self.args['work-dir'], 'lib')
|
|
197
|
-
os.makedirs(work_lib_dir, exist_ok=True)
|
|
198
|
-
work_lib_defines = os.path.join(work_lib_dir, 'oclib_defines.vh')
|
|
199
|
-
|
|
200
|
-
shutil.copy2(lib_defines, work_lib_defines)
|
|
201
|
-
|
|
202
|
-
# Add the copied file as a source
|
|
203
|
-
rel_path = os.path.relpath(
|
|
204
|
-
work_lib_defines, self.args['work-dir']
|
|
205
|
-
).replace('\\', '/')
|
|
206
|
-
tcl_lines.append(
|
|
207
|
-
f"set_global_assignment -name VERILOG_FILE \"{rel_path}\""
|
|
208
|
-
)
|
|
209
|
-
break
|
|
210
192
|
# Add source files (convert to relative paths and use forward slashes)
|
|
193
|
+
# Note that default of self.args['all-sv'] is False so we should have added
|
|
194
|
+
# all files to self.files_sv instead of files_v:
|
|
211
195
|
for f in self.files_v:
|
|
212
196
|
rel_path = os.path.relpath(f, self.args['work-dir']).replace('\\', '/')
|
|
213
197
|
tcl_lines.append(f"set_global_assignment -name VERILOG_FILE \"{rel_path}\"")
|
|
@@ -219,25 +203,8 @@ class CommandSynthQuartus(CommandSynth, ToolQuartus):
|
|
|
219
203
|
tcl_lines.append(f"set_global_assignment -name VHDL_FILE \"{rel_path}\"")
|
|
220
204
|
|
|
221
205
|
# Add include directories - Quartus needs the base directory where "lib/" can be found
|
|
222
|
-
project_root = None
|
|
223
206
|
for incdir in self.incdirs:
|
|
224
207
|
tcl_lines.append(f"set_global_assignment -name SEARCH_PATH \"{incdir}\"")
|
|
225
|
-
# Find the project root (where lib/ directory exists)
|
|
226
|
-
if 'lib' in incdir and os.path.exists(incdir):
|
|
227
|
-
parent_dir = os.path.dirname(incdir)
|
|
228
|
-
if os.path.exists(os.path.join(parent_dir, 'lib')):
|
|
229
|
-
project_root = parent_dir
|
|
230
|
-
|
|
231
|
-
# Set the project root as the main search path so "lib/oclib_defines.vh" resolves correctly
|
|
232
|
-
if project_root:
|
|
233
|
-
tcl_lines.append(
|
|
234
|
-
f"set_global_assignment -name SEARCH_PATH \"{project_root}\""
|
|
235
|
-
)
|
|
236
|
-
# Add the lib directory as an include path
|
|
237
|
-
lib_path = os.path.join(project_root, 'lib').replace('\\', '/')
|
|
238
|
-
tcl_lines.append(
|
|
239
|
-
f"set_global_assignment -name USER_LIBRARIES \"{lib_path}\""
|
|
240
|
-
)
|
|
241
208
|
|
|
242
209
|
# Add all include directories as user libraries for better include resolution
|
|
243
210
|
for incdir in self.incdirs:
|
|
@@ -262,9 +229,8 @@ class CommandSynthQuartus(CommandSynth, ToolQuartus):
|
|
|
262
229
|
|
|
263
230
|
tcl_lines += [
|
|
264
231
|
"# Run synthesis",
|
|
265
|
-
"
|
|
266
|
-
|
|
267
|
-
"project_close"
|
|
232
|
+
'flng::run_flow_command -flow "compile" -end "dni_synthesis"',
|
|
233
|
+
'flng::run_flow_command -flow "compile" -end "sta_early" -resume',
|
|
268
234
|
]
|
|
269
235
|
|
|
270
236
|
with open(tcl_file, 'w', encoding='utf-8') as ftcl:
|
|
@@ -283,22 +249,24 @@ class CommandBuildQuartus(CommandBuild, ToolQuartus):
|
|
|
283
249
|
'proj': False,
|
|
284
250
|
'resynth': False,
|
|
285
251
|
'reset': False,
|
|
252
|
+
'add-tcl-files': [],
|
|
253
|
+
'flow-tcl-files': [],
|
|
286
254
|
})
|
|
287
255
|
|
|
288
|
-
def do_it(self):
|
|
256
|
+
def do_it(self) -> None: # pylint: disable=too-many-branches,too-many-statements
|
|
289
257
|
# add defines for this job
|
|
290
258
|
self.set_tool_defines()
|
|
291
259
|
self.write_eda_config_and_args()
|
|
292
260
|
|
|
293
261
|
# create FLIST
|
|
294
|
-
flist_file = os.path.join(self.args['work-dir'],'build.flist')
|
|
295
|
-
util.debug(f"CommandBuildQuartus: {self.args['top
|
|
262
|
+
flist_file = os.path.abspath(os.path.join(self.args['work-dir'], 'build.flist'))
|
|
263
|
+
util.debug(f"CommandBuildQuartus: top={self.args['top']} target={self.target}",
|
|
264
|
+
f"design={self.args['design']}")
|
|
296
265
|
|
|
297
|
-
eda_path = eda_base.get_eda_exec('flist')
|
|
298
266
|
command_list = [
|
|
299
|
-
|
|
267
|
+
eda_base.get_eda_exec('flist'), 'flist',
|
|
268
|
+
'--no-default-log',
|
|
300
269
|
'--tool=' + self.args['tool'],
|
|
301
|
-
self.args['top-path'],
|
|
302
270
|
'--force',
|
|
303
271
|
'--out=' + flist_file,
|
|
304
272
|
'--no-quote-define',
|
|
@@ -314,46 +282,85 @@ class CommandBuildQuartus(CommandBuild, ToolQuartus):
|
|
|
314
282
|
'--prefix-vhd=' + shlex.quote("set_global_assignment -name VHDL_FILE "),
|
|
315
283
|
'--emit-rel-path', # Use relative paths for better portability
|
|
316
284
|
]
|
|
285
|
+
|
|
286
|
+
# create an eda.flist_input.f that we'll pass to flist:
|
|
287
|
+
with open(os.path.join(self.args['work-dir'], 'eda.flist_input.f'),
|
|
288
|
+
'w', encoding='utf-8') as f:
|
|
289
|
+
f.write('\n'.join(self.files_v + self.files_sv + self.files_vhd + ['']))
|
|
290
|
+
command_list.append('--input-file=eda.flist_input.f')
|
|
291
|
+
|
|
292
|
+
|
|
317
293
|
for key,value in self.defines.items():
|
|
318
294
|
if value is None:
|
|
319
295
|
command_list += [ f"+define+{key}" ]
|
|
320
296
|
else:
|
|
321
297
|
command_list += [ shlex.quote(f"+define+{key}={value}") ]
|
|
322
298
|
|
|
323
|
-
cwd = util.getcwd()
|
|
324
|
-
util.debug(f"CommandBuildQuartus: {cwd=}")
|
|
325
|
-
|
|
326
299
|
# Write out a .sh command for debug
|
|
327
300
|
command_list = util.ShellCommandList(command_list, tee_fpath='run_eda_flist.log')
|
|
328
301
|
util.write_shell_command_file(dirpath=self.args['work-dir'], filename='run_eda_flist.sh',
|
|
329
302
|
command_lists=[command_list], line_breaks=True)
|
|
330
303
|
|
|
331
|
-
self.exec(
|
|
304
|
+
self.exec(work_dir=self.args['work-dir'], command_list=command_list,
|
|
305
|
+
tee_fpath=command_list.tee_fpath)
|
|
332
306
|
|
|
333
307
|
if self.args['job-name'] == "":
|
|
334
308
|
self.args['job-name'] = self.args['design']
|
|
335
|
-
project_dir = 'project.'+self.args['job-name']
|
|
309
|
+
project_dir = 'project.' + self.args['job-name']
|
|
336
310
|
|
|
337
311
|
# Create a simple Quartus build TCL script
|
|
338
|
-
build_tcl_file = os.path.join(self.args['work-dir'], 'build.tcl')
|
|
312
|
+
build_tcl_file = os.path.abspath(os.path.join(self.args['work-dir'], 'build.tcl'))
|
|
313
|
+
build_tcl_lines = [
|
|
314
|
+
'# Quartus Build Script',
|
|
315
|
+
'',
|
|
316
|
+
f'set Top {self.args["top"]}'
|
|
317
|
+
'',
|
|
318
|
+
'load_package flow',
|
|
319
|
+
f'project_new {self.args["design"]} -overwrite',
|
|
320
|
+
f'set_global_assignment -name FAMILY \"{self.args["family"]}\"',
|
|
321
|
+
f'set_global_assignment -name DEVICE {self.args["part"]}',
|
|
322
|
+
'set_global_assignment -name TOP_LEVEL_ENTITY "$Top"',
|
|
323
|
+
'',
|
|
324
|
+
'# Source the flist file',
|
|
325
|
+
'source build.flist',
|
|
326
|
+
'',
|
|
327
|
+
]
|
|
328
|
+
|
|
329
|
+
# If we have additinal TCL files via --add-tcl-files, then source those too:
|
|
330
|
+
if self.args['add-tcl-files']:
|
|
331
|
+
build_tcl_lines.append('')
|
|
332
|
+
build_tcl_lines.append('# Source TCL files from --add-tcl-files args')
|
|
333
|
+
for fname in self.args['add-tcl-files']:
|
|
334
|
+
fname_abs = os.path.abspath(fname)
|
|
335
|
+
if not os.path.isfile(fname_abs):
|
|
336
|
+
self.error(f'add-tcl-files: "{fname_abs}"; does not exist')
|
|
337
|
+
build_tcl_lines.append(f'source {fname_abs}')
|
|
338
|
+
build_tcl_lines.append('')
|
|
339
|
+
|
|
340
|
+
# If we don't have any args for --flow-tcl-files, then use a default flow:
|
|
341
|
+
if not self.args['flow-tcl-files']:
|
|
342
|
+
build_tcl_lines.extend([
|
|
343
|
+
'# Default flow for compile',
|
|
344
|
+
'flng::run_flow_command -flow "compile"',
|
|
345
|
+
''
|
|
346
|
+
])
|
|
347
|
+
else:
|
|
348
|
+
build_tcl_lines.append('')
|
|
349
|
+
build_tcl_lines.append('# Flow TCL files from --flow-tcl-files args')
|
|
350
|
+
for fname in self.args['flow-tcl-files']:
|
|
351
|
+
fname_abs = os.path.abspath(fname)
|
|
352
|
+
if not os.path.isfile(fname_abs):
|
|
353
|
+
self.error(f'flow-tcl-files: "{fname_abs}"; does not exist')
|
|
354
|
+
build_tcl_lines.append(f'source {fname_abs}')
|
|
355
|
+
build_tcl_lines.append('')
|
|
356
|
+
|
|
339
357
|
with open(build_tcl_file, 'w', encoding='utf-8') as ftcl:
|
|
340
|
-
ftcl.write(
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
# Source the flist file
|
|
348
|
-
source [lindex $argv 1]
|
|
349
|
-
|
|
350
|
-
# Run synthesis and compile
|
|
351
|
-
execute_flow -compile
|
|
352
|
-
project_close
|
|
353
|
-
''')
|
|
354
|
-
|
|
355
|
-
# launch Quartus build
|
|
356
|
-
command_list = [self.quartus_exe, '-t', build_tcl_file, project_dir, flist_file]
|
|
358
|
+
ftcl.write('\n'.join(build_tcl_lines))
|
|
359
|
+
|
|
360
|
+
# launch Quartus build, from work-dir:
|
|
361
|
+
command_list_gui = [self.quartus_gui_exe, '-t', 'build.tcl', project_dir]
|
|
362
|
+
command_list = [self.quartus_exe, '-t', 'build.tcl', project_dir]
|
|
363
|
+
saved_qpf_filename = self.args["design"] + '.qpf'
|
|
357
364
|
if not util.args['verbose']:
|
|
358
365
|
command_list.append('-q')
|
|
359
366
|
|
|
@@ -361,28 +368,63 @@ project_close
|
|
|
361
368
|
command_list = util.ShellCommandList(command_list, tee_fpath=None)
|
|
362
369
|
util.write_shell_command_file(dirpath=self.args['work-dir'], filename='run_quartus.sh',
|
|
363
370
|
command_lists=[command_list], line_breaks=True)
|
|
371
|
+
util.write_shell_command_file(dirpath=self.args['work-dir'], filename='run_quartus_gui.sh',
|
|
372
|
+
command_lists=[
|
|
373
|
+
command_list_gui,
|
|
374
|
+
['quartus', saved_qpf_filename], # reopen when done.
|
|
375
|
+
], line_breaks=True)
|
|
364
376
|
|
|
365
377
|
# Add artifact tracking for build
|
|
378
|
+
artifacts_search_paths = [
|
|
379
|
+
self.args['work-dir'],
|
|
380
|
+
os.path.join(self.args['work-dir'], 'output_files'),
|
|
381
|
+
]
|
|
382
|
+
|
|
366
383
|
util.artifacts.add_extension(
|
|
367
|
-
search_paths=
|
|
384
|
+
search_paths=artifacts_search_paths, file_extension='sof',
|
|
368
385
|
typ='bitstream', description='Quartus SRAM Object File (bitstream)'
|
|
369
386
|
)
|
|
370
387
|
util.artifacts.add_extension(
|
|
371
|
-
search_paths=
|
|
388
|
+
search_paths=artifacts_search_paths, file_extension='pof',
|
|
372
389
|
typ='bitstream', description='Quartus Programmer Object File'
|
|
373
390
|
)
|
|
374
391
|
util.artifacts.add_extension(
|
|
375
|
-
search_paths=
|
|
376
|
-
typ='
|
|
392
|
+
search_paths=artifacts_search_paths, file_extension='rpt',
|
|
393
|
+
typ='text', description='Quartus Timing, Fitter, or other report'
|
|
377
394
|
)
|
|
378
395
|
util.artifacts.add_extension(
|
|
379
|
-
search_paths=
|
|
380
|
-
typ='
|
|
396
|
+
search_paths=artifacts_search_paths, file_extension='summary',
|
|
397
|
+
typ='text', description='Quartus Timing, Fitter, or other summary'
|
|
381
398
|
)
|
|
382
399
|
|
|
383
|
-
self.
|
|
400
|
+
if self.args['stop-before-compile']:
|
|
401
|
+
util.info(f"--stop-before-compile set: scripts in : {self.args['work-dir']}")
|
|
402
|
+
return
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
if self.args['gui'] and self.quartus_gui_exe:
|
|
406
|
+
self.exec(
|
|
407
|
+
work_dir=self.args['work-dir'], command_list=command_list_gui
|
|
408
|
+
)
|
|
409
|
+
else:
|
|
410
|
+
self.exec(
|
|
411
|
+
work_dir=self.args['work-dir'], command_list=command_list,
|
|
412
|
+
tee_fpath=command_list.tee_fpath
|
|
413
|
+
)
|
|
414
|
+
if not os.path.isfile(os.path.join(self.args['work-dir'], saved_qpf_filename)):
|
|
415
|
+
self.error('Saved project file does not exist:',
|
|
416
|
+
os.path.join(self.args['work-dir'], saved_qpf_filename))
|
|
417
|
+
|
|
384
418
|
util.info(f"Build done, results are in: {self.args['work-dir']}")
|
|
385
419
|
|
|
420
|
+
# Note: in GUI mode, if you ran: quaruts -t build.tcl, it will exit on completion,
|
|
421
|
+
# so we'll re-open the project.
|
|
422
|
+
if self.args['gui'] and self.quartus_gui_exe:
|
|
423
|
+
self.exec(
|
|
424
|
+
work_dir=self.args['work-dir'],
|
|
425
|
+
command_list=['quartus', saved_qpf_filename]
|
|
426
|
+
)
|
|
427
|
+
|
|
386
428
|
|
|
387
429
|
class CommandFListQuartus(CommandFList, ToolQuartus):
|
|
388
430
|
'''CommandFListQuartus is a command handler for: eda flist --tool=quartus'''
|
|
@@ -485,7 +527,7 @@ class CommandUploadQuartus(CommandUpload, ToolQuartus):
|
|
|
485
527
|
self.args.update({
|
|
486
528
|
'sof-file': "",
|
|
487
529
|
'cable': "1",
|
|
488
|
-
'device': "1",
|
|
530
|
+
'device': "1",
|
|
489
531
|
'list-cables': False,
|
|
490
532
|
'list-devices': False,
|
|
491
533
|
'list-sof-files': False,
|
|
@@ -101,22 +101,11 @@ class CommandSimQuesta(CommandSim, ToolQuesta):
|
|
|
101
101
|
self.vlog_commands = self.get_compile_command_lists()
|
|
102
102
|
self.vopt_commands = self.get_elaborate_command_lists()
|
|
103
103
|
self.vsim_commands = self.get_simulate_command_lists()
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
util.write_shell_command_file(dirpath=self.args['work-dir'], filename='simulate.sh',
|
|
110
|
-
command_lists=self.vsim_commands)
|
|
111
|
-
util.write_shell_command_file(dirpath=self.args['work-dir'], filename='all.sh',
|
|
112
|
-
command_lists = [
|
|
113
|
-
['./pre_compile_dep_shell_commands.sh'],
|
|
114
|
-
['./compile.sh'],
|
|
115
|
-
['./elaborate.sh'],
|
|
116
|
-
['./simulate.sh'],
|
|
117
|
-
])
|
|
118
|
-
|
|
119
|
-
self.write_eda_config_and_args()
|
|
104
|
+
self.write_sh_scripts_to_work_dir(
|
|
105
|
+
compile_lists=self.vlog_commands,
|
|
106
|
+
elaborate_lists=self.vopt_commands,
|
|
107
|
+
simulate_lists=self.vsim_commands
|
|
108
|
+
)
|
|
120
109
|
|
|
121
110
|
def compile(self):
|
|
122
111
|
if self.args['stop-before-compile']:
|