opencos-eda 0.2.28__py3-none-any.whl → 0.2.32__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/export.py +2 -1
- opencos/commands/flist.py +49 -12
- opencos/commands/multi.py +101 -130
- opencos/commands/synth.py +0 -1
- opencos/commands/upload.py +7 -7
- opencos/commands/waves.py +50 -19
- opencos/deps_helpers.py +93 -3
- opencos/deps_schema.py +28 -18
- opencos/eda.py +6 -1
- opencos/eda_base.py +29 -10
- opencos/eda_config.py +1 -0
- opencos/eda_config_defaults.yml +4 -1
- opencos/eda_extract_deps_keys.py +27 -10
- opencos/files.py +6 -8
- opencos/names.py +1 -0
- opencos/oc_cli.py +143 -1
- opencos/peakrdl_cleanup.py +0 -1
- opencos/tests/helpers.py +38 -10
- opencos/tests/test_deps_helpers.py +46 -2
- opencos/tests/test_eda.py +65 -41
- opencos/tests/test_tools.py +17 -9
- opencos/tools/iverilog.py +0 -2
- opencos/tools/modelsim_ase.py +11 -5
- opencos/tools/questa.py +14 -19
- opencos/tools/verilator.py +0 -2
- opencos/tools/vivado.py +253 -112
- opencos/tools/yosys.py +1 -6
- opencos/util.py +4 -0
- {opencos_eda-0.2.28.dist-info → opencos_eda-0.2.32.dist-info}/METADATA +1 -1
- {opencos_eda-0.2.28.dist-info → opencos_eda-0.2.32.dist-info}/RECORD +35 -35
- {opencos_eda-0.2.28.dist-info → opencos_eda-0.2.32.dist-info}/WHEEL +1 -1
- {opencos_eda-0.2.28.dist-info → opencos_eda-0.2.32.dist-info}/entry_points.txt +0 -0
- {opencos_eda-0.2.28.dist-info → opencos_eda-0.2.32.dist-info}/licenses/LICENSE +0 -0
- {opencos_eda-0.2.28.dist-info → opencos_eda-0.2.32.dist-info}/licenses/LICENSE.spdx +0 -0
- {opencos_eda-0.2.28.dist-info → opencos_eda-0.2.32.dist-info}/top_level.txt +0 -0
opencos/tools/vivado.py
CHANGED
|
@@ -10,6 +10,10 @@ import os
|
|
|
10
10
|
import re
|
|
11
11
|
import shlex
|
|
12
12
|
import shutil
|
|
13
|
+
import sys
|
|
14
|
+
|
|
15
|
+
from datetime import datetime
|
|
16
|
+
from pathlib import Path
|
|
13
17
|
|
|
14
18
|
from opencos import util, eda_base
|
|
15
19
|
from opencos.eda_base import Tool
|
|
@@ -30,8 +34,14 @@ class ToolVivado(Tool):
|
|
|
30
34
|
|
|
31
35
|
def __init__(self, config: dict):
|
|
32
36
|
super().__init__(config=config) # calls self.get_versions()
|
|
33
|
-
self.args
|
|
34
|
-
|
|
37
|
+
self.args.update({
|
|
38
|
+
'part': 'xcu200-fsgd2104-2-e',
|
|
39
|
+
'add-glbl-v': False,
|
|
40
|
+
})
|
|
41
|
+
self.args_help.update({
|
|
42
|
+
'part': 'Device used for commands: synth, build.',
|
|
43
|
+
'add-glbl-v': '(for simulation) add glbl.v to filelist',
|
|
44
|
+
})
|
|
35
45
|
|
|
36
46
|
|
|
37
47
|
def get_versions(self) -> str:
|
|
@@ -48,10 +58,10 @@ class ToolVivado(Tool):
|
|
|
48
58
|
|
|
49
59
|
xilinx_vivado = os.environ.get('XILINX_VIVADO')
|
|
50
60
|
if not xilinx_vivado or \
|
|
51
|
-
os.path.abspath(os.path.join(xilinx_vivado, 'bin'
|
|
52
|
-
os.path.abspath(self.vivado_exe):
|
|
61
|
+
os.path.abspath(os.path.join(xilinx_vivado, 'bin')) != \
|
|
62
|
+
os.path.abspath(os.path.dirname(self.vivado_exe)):
|
|
53
63
|
util.info("environment for XILINX_VIVADO is not set or doesn't match the vivado path:",
|
|
54
|
-
f"{xilinx_vivado=}")
|
|
64
|
+
f"XILINX_VIVADO={xilinx_vivado} EXE PATH={self.vivado_exe}")
|
|
55
65
|
|
|
56
66
|
version = None
|
|
57
67
|
# Note this is commented out b/c it's a bit slow, up to 1.0 second to
|
|
@@ -91,12 +101,6 @@ class ToolVivado(Tool):
|
|
|
91
101
|
self.defines['OC_TOOL_VIVADO'] = None
|
|
92
102
|
def_year_release = f'OC_TOOL_VIVADO_{self.vivado_year:04d}_{self.vivado_release:d}'
|
|
93
103
|
self.defines[def_year_release] = None
|
|
94
|
-
if self.args['xilinx']:
|
|
95
|
-
self.defines['OC_LIBRARY_ULTRASCALE_PLUS'] = None
|
|
96
|
-
self.defines['OC_LIBRARY'] = "1"
|
|
97
|
-
else:
|
|
98
|
-
self.defines['OC_LIBRARY_BEHAVIORAL'] = None
|
|
99
|
-
self.defines['OC_LIBRARY'] = "0"
|
|
100
104
|
|
|
101
105
|
# Code can be conditional on Vivado versions and often keys of "X or older" ...
|
|
102
106
|
versions = ['2021.1', '2021.2', '2022.1', '2022.2', '2023.1', '2023.2',
|
|
@@ -133,9 +137,18 @@ class CommandSimVivado(CommandSim, ToolVivado):
|
|
|
133
137
|
CommandSim.__init__(self, config)
|
|
134
138
|
ToolVivado.__init__(self, config=self.config)
|
|
135
139
|
# add args specific to this simulator
|
|
136
|
-
self.args
|
|
137
|
-
|
|
138
|
-
|
|
140
|
+
self.args.update({
|
|
141
|
+
'gui': False,
|
|
142
|
+
'tcl-file': 'sim.tcl',
|
|
143
|
+
'fpga': '',
|
|
144
|
+
'add-glbl-v': False,
|
|
145
|
+
})
|
|
146
|
+
self.args_help.update({
|
|
147
|
+
'gui': 'Run Vivado XSim in GUI mode',
|
|
148
|
+
'tcl-file': 'name of TCL file to be created for XSim',
|
|
149
|
+
'fpga': 'FPGA device name, can be used for various Xilinx IP or XCIs',
|
|
150
|
+
'add-glbl-v': 'Use the glbl.v in xvlog for this version of Vivado',
|
|
151
|
+
})
|
|
139
152
|
|
|
140
153
|
self.sim_libraries = self.tool_config.get('sim-libraries', [])
|
|
141
154
|
self.xvlog_commands = []
|
|
@@ -198,10 +211,13 @@ class CommandSimVivado(CommandSim, ToolVivado):
|
|
|
198
211
|
self.set_tool_defines()
|
|
199
212
|
ret = [] # list of (list of ['xvlog', arg0, arg1, ..])
|
|
200
213
|
|
|
214
|
+
if self.args['add-glbl-v']:
|
|
215
|
+
self._add_glbl_v()
|
|
216
|
+
|
|
201
217
|
# compile verilog
|
|
202
|
-
if self.files_v
|
|
218
|
+
if self.files_v:
|
|
203
219
|
ret.append(
|
|
204
|
-
self.get_xvlog_commands(files_list=self.files_v, typ='v'
|
|
220
|
+
self.get_xvlog_commands(files_list=self.files_v, typ='v')
|
|
205
221
|
)
|
|
206
222
|
|
|
207
223
|
# compile systemverilog
|
|
@@ -218,6 +234,8 @@ class CommandSimVivado(CommandSim, ToolVivado):
|
|
|
218
234
|
os.path.join(self.vivado_base_path, 'xelab'),
|
|
219
235
|
self.args['top']
|
|
220
236
|
]
|
|
237
|
+
if sys.platform == "win32":
|
|
238
|
+
command_list[0] += ".bat"
|
|
221
239
|
command_list += self.tool_config.get('elab-args',
|
|
222
240
|
'-s snapshot -timescale 1ns/1ps --stats').split()
|
|
223
241
|
if self.tool_config.get('elab-waves-args', ''):
|
|
@@ -230,7 +248,7 @@ class CommandSimVivado(CommandSim, ToolVivado):
|
|
|
230
248
|
command_list += ['-debug', 'wave']
|
|
231
249
|
if util.args['verbose']:
|
|
232
250
|
command_list += ['-v', '2']
|
|
233
|
-
if self.args['
|
|
251
|
+
if self.args['sim-library'] or self.args['add-glbl-v']:
|
|
234
252
|
self.sim_libraries += self.args['sim-library'] # Add any command line libraries
|
|
235
253
|
for x in self.sim_libraries:
|
|
236
254
|
command_list += ['-L', x]
|
|
@@ -265,11 +283,13 @@ class CommandSimVivado(CommandSim, ToolVivado):
|
|
|
265
283
|
|
|
266
284
|
# execute snapshot
|
|
267
285
|
command_list = [ os.path.join(self.vivado_base_path, 'xsim') ]
|
|
286
|
+
if sys.platform == "win32":
|
|
287
|
+
command_list[0] += ".bat"
|
|
268
288
|
command_list += self.tool_config.get('simulate-args', 'snapshot --stats').split()
|
|
269
289
|
if self.args['gui']:
|
|
270
290
|
command_list += ['-gui']
|
|
271
291
|
command_list += [
|
|
272
|
-
'--tclbatch', tcl_name,
|
|
292
|
+
'--tclbatch', tcl_name.replace('\\','\\\\'), # needed for windows paths
|
|
273
293
|
"--sv_seed", sv_seed
|
|
274
294
|
]
|
|
275
295
|
command_list += xsim_plusargs_list
|
|
@@ -279,25 +299,21 @@ class CommandSimVivado(CommandSim, ToolVivado):
|
|
|
279
299
|
def get_post_simulate_command_lists(self, **kwargs) -> list:
|
|
280
300
|
return []
|
|
281
301
|
|
|
282
|
-
def get_xvlog_commands(self, files_list: list,
|
|
283
|
-
typ: str = 'sv', add_glbl_v: bool = False) -> list:
|
|
302
|
+
def get_xvlog_commands(self, files_list: list, typ: str = 'sv') -> list:
|
|
284
303
|
'''Returns list. Vivado still treats .v files like Verilog-2001, so we split
|
|
285
304
|
|
|
286
305
|
xvlog into .v and .sv sections'''
|
|
287
306
|
command_list = []
|
|
307
|
+
|
|
288
308
|
if files_list:
|
|
289
309
|
command_list = [ os.path.join(self.vivado_base_path, 'xvlog') ]
|
|
310
|
+
if sys.platform == "win32":
|
|
311
|
+
command_list[0] += ".bat"
|
|
290
312
|
if typ == 'sv':
|
|
291
313
|
command_list.append('-sv')
|
|
292
314
|
command_list += self.tool_config.get('compile-args', '').split()
|
|
293
315
|
if util.args['verbose']:
|
|
294
316
|
command_list += ['-v', '2']
|
|
295
|
-
if (typ == 'v' or add_glbl_v) and self.args['xilinx']:
|
|
296
|
-
# Get the right glbl.v for the vivado being used.
|
|
297
|
-
glbl_v = self.vivado_base_path.replace('bin', 'data/verilog/src/glbl.v')
|
|
298
|
-
if not os.path.exists(glbl_v):
|
|
299
|
-
self.error(f"Could not find file {glbl_v=}")
|
|
300
|
-
command_list.append(glbl_v)
|
|
301
317
|
for value in self.incdirs:
|
|
302
318
|
command_list.append('-i')
|
|
303
319
|
command_list.append(value)
|
|
@@ -305,16 +321,27 @@ class CommandSimVivado(CommandSim, ToolVivado):
|
|
|
305
321
|
command_list.append('-d')
|
|
306
322
|
if value is None:
|
|
307
323
|
command_list.append(key)
|
|
324
|
+
elif sys.platform == "win32":
|
|
325
|
+
command_list.append(f"\"{key}={value}\"") # only thing that seems to work
|
|
308
326
|
elif "\'" in value:
|
|
309
327
|
command_list.append(f"\"{key}={value}\"")
|
|
310
328
|
else:
|
|
311
|
-
command_list.append(f"
|
|
329
|
+
command_list.append(f"{key}={value}")
|
|
312
330
|
command_list += self.args['compile-args']
|
|
313
331
|
command_list += files_list
|
|
314
332
|
return command_list
|
|
315
333
|
|
|
316
334
|
|
|
317
|
-
|
|
335
|
+
def _add_glbl_v(self):
|
|
336
|
+
'''Adds glbl.v from Vivado's install path to self.files_v'''
|
|
337
|
+
glbl_v = self.vivado_base_path.replace('bin', 'data/verilog/src/glbl.v')
|
|
338
|
+
if any(x.endswith('glbl.v') for x in self.files_v):
|
|
339
|
+
util.warning(f'--add-glbl-v: Not adding {glbl_v=} b/c glbl.v already in',
|
|
340
|
+
f'{self.files_v=}')
|
|
341
|
+
elif not os.path.exists(glbl_v):
|
|
342
|
+
self.error(f"Could not find file {glbl_v=}")
|
|
343
|
+
else:
|
|
344
|
+
self.files_v.insert(0, glbl_v)
|
|
318
345
|
|
|
319
346
|
|
|
320
347
|
class CommandElabVivado(CommandSimVivado):
|
|
@@ -559,6 +586,9 @@ class CommandProjVivado(CommandProj, ToolVivado):
|
|
|
559
586
|
f"add_files -norecurse {f} -fileset [get_filesets {fileset}]"
|
|
560
587
|
]
|
|
561
588
|
|
|
589
|
+
tcl_lines += [
|
|
590
|
+
f"set_property top {self.args['top']} [get_filesets sim_1]"
|
|
591
|
+
]
|
|
562
592
|
with open( tcl_file, 'w', encoding='utf-8' ) as fo:
|
|
563
593
|
fo.write('\n'.join(tcl_lines))
|
|
564
594
|
|
|
@@ -570,7 +600,7 @@ class CommandProjVivado(CommandProj, ToolVivado):
|
|
|
570
600
|
if not util.args['verbose']:
|
|
571
601
|
command_list.append('-notrace')
|
|
572
602
|
self.exec(self.args['work-dir'], command_list)
|
|
573
|
-
util.info(f"
|
|
603
|
+
util.info(f"Project run done, results are in: {self.args['work-dir']}")
|
|
574
604
|
|
|
575
605
|
|
|
576
606
|
class CommandBuildVivado(CommandBuild, ToolVivado):
|
|
@@ -600,12 +630,17 @@ class CommandBuildVivado(CommandBuild, ToolVivado):
|
|
|
600
630
|
'--tool', self.args['tool'],
|
|
601
631
|
self.args['top-path'],
|
|
602
632
|
'--force',
|
|
603
|
-
'--xilinx',
|
|
604
633
|
'--out', flist_file,
|
|
605
|
-
'--no-emit-incdir',
|
|
606
|
-
'--no-single-quote-define', # Needed to run in Command.exec( ... shell=False)
|
|
634
|
+
#'--no-emit-incdir',
|
|
635
|
+
#'--no-single-quote-define', # Needed to run in Command.exec( ... shell=False)
|
|
607
636
|
'--no-quote-define',
|
|
637
|
+
#'--bracket-quote-define',
|
|
638
|
+
'--quote-define-value',
|
|
639
|
+
'--escape-define-value',
|
|
640
|
+
'--no-equal-define',
|
|
641
|
+
'--bracket-quote-path',
|
|
608
642
|
# on --prefix- items, use shlex.quote(str) so spaces work with subprocess shell=False:
|
|
643
|
+
'--prefix-incdir', shlex.quote("oc_set_project_incdir "),
|
|
609
644
|
'--prefix-define', shlex.quote("oc_set_project_define "),
|
|
610
645
|
'--prefix-sv', shlex.quote("add_files -norecurse "),
|
|
611
646
|
'--prefix-v', shlex.quote("add_files -norecurse "),
|
|
@@ -674,96 +709,202 @@ class CommandUploadVivado(CommandUpload, ToolVivado):
|
|
|
674
709
|
CommandUpload.__init__(self, config)
|
|
675
710
|
ToolVivado.__init__(self, config=self.config)
|
|
676
711
|
# add args specific to this simulator
|
|
677
|
-
self.args
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
712
|
+
self.args.update({
|
|
713
|
+
'gui': False,
|
|
714
|
+
'bitfile': "",
|
|
715
|
+
'list-usbs': False,
|
|
716
|
+
'list-devices': False,
|
|
717
|
+
'list-bitfiles': False,
|
|
718
|
+
'usb': -1,
|
|
719
|
+
'device': -1,
|
|
720
|
+
'host': "localhost",
|
|
721
|
+
'port': 3121,
|
|
722
|
+
'tcl-file': "upload.tcl",
|
|
723
|
+
'test-mode': False,
|
|
724
|
+
})
|
|
725
|
+
# TODO(drew): Add self.args_help.update({...})
|
|
726
|
+
|
|
727
|
+
# TODO(drew): This method needs to be refactored (with tests somehow) to clean
|
|
728
|
+
# up pylint waivers
|
|
729
|
+
def do_it(self): # pylint: disable=too-many-locals,too-many-branches,too-many-statements
|
|
730
|
+
# add defines for this job
|
|
731
|
+
self.set_tool_defines()
|
|
732
|
+
self.write_eda_config_and_args()
|
|
684
733
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
734
|
+
bitfile = None
|
|
735
|
+
targets = []
|
|
736
|
+
if self.args['bitfile']:
|
|
737
|
+
if os.path.isfile(self.args['bitfile']):
|
|
738
|
+
bitfile = self.args['bitfile']
|
|
739
|
+
else:
|
|
740
|
+
# Not a file, treat as search pattern
|
|
741
|
+
targets = [self.args['bitfile']]
|
|
742
|
+
|
|
743
|
+
# TODO(drew): It might be nice to use positional args (supported by
|
|
744
|
+
# eda_base.Command) here, and in multi.py, so we don't accidentally
|
|
745
|
+
# grab errant --arg style strings as potential filenames or target patterns
|
|
746
|
+
for f in self.unparsed_args:
|
|
747
|
+
# self.unparsed_args are leftovers from Command.process_tokens(..)
|
|
748
|
+
if os.path.isfile(f):
|
|
749
|
+
if bitfile is None:
|
|
750
|
+
bitfile = f
|
|
751
|
+
else:
|
|
752
|
+
util.error("Too many bitfiles provided")
|
|
753
|
+
if not self.args['test-mode']:
|
|
754
|
+
sys.exit(0)
|
|
755
|
+
else:
|
|
756
|
+
# Not a file, treat as search pattern
|
|
757
|
+
targets.append(f)
|
|
758
|
+
|
|
759
|
+
# Auto-discover bitfile logic (for when we have no bitfile, and we
|
|
760
|
+
# weren't called just to listdevice/listusb)
|
|
761
|
+
if self.args['list-bitfiles'] or \
|
|
762
|
+
(not bitfile and not self.args['list-devices'] and not self.args['list-usbs']):
|
|
763
|
+
bitfiles: list[Path] = []
|
|
764
|
+
|
|
765
|
+
util.debug(f"Looking for bitfiles in {os.path.abspath('.')=}")
|
|
690
766
|
for root, _, files in os.walk("."):
|
|
691
|
-
for
|
|
692
|
-
if
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
767
|
+
for f in files:
|
|
768
|
+
if f.endswith(".bit"):
|
|
769
|
+
fullpath = os.path.abspath(Path(root) / f)
|
|
770
|
+
if fullpath not in bitfiles:
|
|
771
|
+
bitfiles.append(fullpath)
|
|
772
|
+
|
|
773
|
+
matched: list[Path] = []
|
|
774
|
+
for cand in bitfiles:
|
|
775
|
+
util.debug(f"Looking for {cand=} in {targets=}")
|
|
776
|
+
passing = all(re.search(t, str(cand)) for t in targets)
|
|
777
|
+
if passing:
|
|
778
|
+
matched.append(cand)
|
|
779
|
+
mod_time_string = datetime.fromtimestamp(
|
|
780
|
+
os.path.getmtime(cand)).strftime('%Y-%m-%d %H:%M:%S')
|
|
781
|
+
util.info(f"Found matching bitfile: {mod_time_string} : {cand}")
|
|
782
|
+
|
|
783
|
+
if len(matched) > 1:
|
|
784
|
+
if self.args['list-bitfiles']:
|
|
785
|
+
util.info("Too many matches to continue without adding search terms. Done.")
|
|
786
|
+
if not self.args['test-mode']:
|
|
787
|
+
sys.exit(0)
|
|
788
|
+
else:
|
|
789
|
+
util.error("Too many matches, please add search terms...")
|
|
697
790
|
|
|
698
|
-
if
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
791
|
+
if not matched and bitfile is None:
|
|
792
|
+
if self.args['list-bitfiles']:
|
|
793
|
+
util.info("No matching bitfiles found, done.")
|
|
794
|
+
if not self.args['test-mode']:
|
|
795
|
+
sys.exit(0)
|
|
796
|
+
else:
|
|
797
|
+
util.error("Failed to find a matching bitfile")
|
|
798
|
+
|
|
799
|
+
if matched and bitfile is None:
|
|
800
|
+
bitfile = matched[0]
|
|
801
|
+
|
|
802
|
+
# ── Generate TCL script ───────────────────────────────────────────────────
|
|
803
|
+
script_file = Path(self.args['tcl-file'])
|
|
804
|
+
log_file = Path("eda_upload.log")
|
|
805
|
+
|
|
806
|
+
try:
|
|
807
|
+
with script_file.open("w", encoding="utf-8") as fout:
|
|
808
|
+
w = fout.write # local alias (brevity)
|
|
809
|
+
|
|
810
|
+
w('open_hw_manager\n')
|
|
811
|
+
w(f'connect_hw_server -url {self.args["host"]}:{self.args["port"]}\n')
|
|
812
|
+
w('refresh_hw_server -force_poll\n')
|
|
813
|
+
|
|
814
|
+
w('set hw_targets [get_hw_targets -quiet */xilinx_tcf/Xilinx/*]\n')
|
|
815
|
+
w('set num_targets [llength $hw_targets]\n')
|
|
816
|
+
if self.args['list-usbs']:
|
|
817
|
+
w('puts "\\[INFO\\] OC_LOAD_BITFILE TCL $num_targets USB targets found"\n')
|
|
818
|
+
w('for {set u 0} {$u < $num_targets} {incr u} {\n')
|
|
819
|
+
w(' puts "\\[INFO\\] OC_LOAD_BITFILE TCL: USB $u : [lindex $hw_targets $u]"\n')
|
|
820
|
+
w('}\n')
|
|
821
|
+
w('if { $num_targets > 1} {\n')
|
|
822
|
+
w(' set maxusb [expr $num_targets - 1]\n')
|
|
823
|
+
w(' puts "\\[INFO\\] OC_LOAD_BITFILE TCL: With >1 target you need to specify'
|
|
824
|
+
'--usb <n> where <n> is 0-$maxusb"\n')
|
|
825
|
+
w('}\n')
|
|
826
|
+
w('if { $num_targets == 0 } {\n')
|
|
827
|
+
w(' puts "\\[ERROR\\] OC_LOAD_BITFILE TCL: No HW_targets found!"\n')
|
|
828
|
+
w(' exit\n}\n')
|
|
829
|
+
|
|
830
|
+
if self.args['usb'] == -1:
|
|
831
|
+
w('if { $num_targets == 1 } {\n')
|
|
832
|
+
w(' puts "\\[INFO\\] OC_LOAD_BITFILE TCL: Defaulting to USB #0, since there is'
|
|
833
|
+
'only one device"\n')
|
|
834
|
+
w(' set usb 0\n} else {\n')
|
|
835
|
+
if not self.args['list-usbs']:
|
|
836
|
+
w(' set maxusb [expr $num_targets - 1]\n')
|
|
837
|
+
w(' puts "\\[ERROR\\] OC_LOAD_BITFILE TCL: Need --usb <n> argument, <n>'
|
|
838
|
+
'being 0-$maxusb, use --list-usbs if needed"\n')
|
|
839
|
+
w(' exit\n}\n')
|
|
840
|
+
else:
|
|
841
|
+
w(f'set usb {self.args["usb"]}\n')
|
|
842
|
+
|
|
843
|
+
w('if { $num_targets <= $usb } {\n')
|
|
844
|
+
w(' puts "\\[ERROR\\] OC_LOAD_BITFILE TCL: hw_target #$usb doesn\'t exist!!"\n')
|
|
845
|
+
w(' exit\n}\n')
|
|
846
|
+
w('set hw_target [lindex $hw_targets $usb]\n')
|
|
847
|
+
w('current_hw_target $hw_target\n')
|
|
848
|
+
w('open_hw_target\n')
|
|
849
|
+
w('refresh_hw_target\n')
|
|
850
|
+
|
|
851
|
+
w('set hw_devices [get_hw_devices -quiet]\n')
|
|
852
|
+
w('set num_devices [llength $hw_devices]\n')
|
|
853
|
+
if self.args['list-devices']:
|
|
854
|
+
w('puts "\\[INFO\\] OC_LOAD_BITFILE TCL $num_devices devices found"\n')
|
|
855
|
+
w('for {set d 0} {$d < $num_devices} {incr d} {\n')
|
|
856
|
+
w(' puts "\\[INFO\\] OC_LOAD_BITFILE TCL: Device $d :'
|
|
857
|
+
'[lindex $hw_devices $d]"\n')
|
|
858
|
+
w('}\n')
|
|
859
|
+
|
|
860
|
+
if self.args['device'] == -1:
|
|
861
|
+
w('if { $num_devices > 1 } {\n')
|
|
862
|
+
w(' if { [lindex $hw_devices 0] eq "arm_dap_0" } {\n')
|
|
863
|
+
w(' set hw_device [lindex $hw_devices 1]\n } else {\n')
|
|
864
|
+
w(' set hw_device [lindex $hw_devices 0]\n }\n')
|
|
865
|
+
w('}\n')
|
|
866
|
+
else:
|
|
867
|
+
w(f'set hw_device [lindex $hw_devices {self.args["device"] }]\n')
|
|
702
868
|
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
869
|
+
w('puts "HW_DEVICE DID : [get_property DID $hw_device]"\n')
|
|
870
|
+
w('puts "HW_DEVICE PART : [get_property PART $hw_device]"\n')
|
|
871
|
+
w('current_hw_device $hw_device\n')
|
|
872
|
+
w('refresh_hw_device -update_hw_probes false -quiet $hw_device\n')
|
|
873
|
+
|
|
874
|
+
if bitfile is not None:
|
|
875
|
+
w('set_property PROGRAM.FILE {' + bitfile + '} $hw_device\n')
|
|
876
|
+
w('program_hw_devices [current_hw_device]\n')
|
|
877
|
+
|
|
878
|
+
w('close_hw_target\n')
|
|
879
|
+
|
|
880
|
+
except OSError as exc:
|
|
881
|
+
util.error(f"Cannot create {script_file}: {exc}")
|
|
882
|
+
|
|
883
|
+
if bitfile is None:
|
|
884
|
+
util.info("No bitfile provided or found")
|
|
713
885
|
else:
|
|
714
|
-
|
|
715
|
-
|
|
886
|
+
if os.path.isfile(bitfile):
|
|
887
|
+
util.info(f"Using bitfile {bitfile}")
|
|
888
|
+
else:
|
|
889
|
+
util.warning(f"Using bitfile {bitfile}, which doesn't exist (or is not a file)")
|
|
716
890
|
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
tcl_file = os.path.abspath(os.path.join(self.args['work-dir'], self.args['tcl-file']))
|
|
721
|
-
ltx_file = os.path.splitext(bit_file)[0] + ".ltx"
|
|
722
|
-
if not os.path.exists(ltx_file):
|
|
723
|
-
ltx_file = False
|
|
891
|
+
if self.args['test-mode']:
|
|
892
|
+
util.info(f"test-mode set, upload skipped, {script_file=}")
|
|
893
|
+
return
|
|
724
894
|
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
"refresh_hw_server -force_poll",
|
|
729
|
-
"set hw_targets [get_hw_targets */xilinx_tcf/Xilinx/*]",
|
|
730
|
-
f"if {{ [llength $hw_targets] <= {target} }} {{",
|
|
731
|
-
f" puts \"ERROR: There is no target number {target}\"",
|
|
732
|
-
"}}",
|
|
733
|
-
f"current_hw_target [lindex $hw_targets {target}]",
|
|
734
|
-
"open_hw_target",
|
|
735
|
-
"refresh_hw_target",
|
|
736
|
-
"current_hw_device [lindex [get_hw_devices] 0]",
|
|
737
|
-
"refresh_hw_device [current_hw_device]",
|
|
738
|
-
f"set_property PROGRAM.FILE {bit_file} [current_hw_device]",
|
|
739
|
-
]
|
|
740
|
-
if ltx_file:
|
|
741
|
-
tcl_lines += [
|
|
742
|
-
f"set_property PROBES.FILE {ltx_file} [current_hw_device]",
|
|
743
|
-
]
|
|
744
|
-
tcl_lines += [
|
|
745
|
-
"program_hw_devices [current_hw_device]",
|
|
895
|
+
# ── Execute Vivado ───────────────────────────────────────────────────────
|
|
896
|
+
command_list = [
|
|
897
|
+
self.vivado_exe, '-mode', 'batch', '-source', str(script_file), '-log', str(log_file)
|
|
746
898
|
]
|
|
747
|
-
if
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
"close_hw_target",
|
|
755
|
-
"exit",
|
|
756
|
-
]
|
|
899
|
+
if not util.args['verbose']:
|
|
900
|
+
command_list.append('-notrace')
|
|
901
|
+
self.exec(Path(util.getcwd()), command_list)
|
|
902
|
+
|
|
903
|
+
util.info("Upload done")
|
|
904
|
+
|
|
905
|
+
|
|
757
906
|
|
|
758
|
-
with open( tcl_file, 'w', encoding='utf-8' ) as fo:
|
|
759
|
-
fo.write('\n'.join(tcl_lines))
|
|
760
907
|
|
|
761
|
-
# execute Vivado
|
|
762
|
-
command_list = [ self.vivado_exe, '-source', tcl_file, '-log', "fpga.upload.log" ]
|
|
763
|
-
if not self.args['gui']:
|
|
764
|
-
command_list.append('-mode')
|
|
765
|
-
command_list.append('batch')
|
|
766
|
-
self.exec(self.args['work-dir'], command_list)
|
|
767
908
|
|
|
768
909
|
class CommandOpenVivado(CommandOpen, ToolVivado):
|
|
769
910
|
'''CommandOpenVivado command handler class used by: eda open --tool vivado'''
|
opencos/tools/yosys.py
CHANGED
|
@@ -66,12 +66,7 @@ class ToolYosys(Tool):
|
|
|
66
66
|
self.defines.update({
|
|
67
67
|
'OC_TOOL_YOSYS': None
|
|
68
68
|
})
|
|
69
|
-
if self.
|
|
70
|
-
self.defines.update({
|
|
71
|
-
'OC_LIBRARY_ULTRASCALE_PLUS': None,
|
|
72
|
-
'OC_LIBRARY': "1"
|
|
73
|
-
})
|
|
74
|
-
else:
|
|
69
|
+
if 'OC_LIBRARY' not in self.defines:
|
|
75
70
|
self.defines.update({
|
|
76
71
|
'OC_LIBRARY_BEHAVIORAL': None,
|
|
77
72
|
'OC_LIBRARY': "0"
|
opencos/util.py
CHANGED
|
@@ -451,6 +451,8 @@ def get_oc_root(error_on_fail:bool=False):
|
|
|
451
451
|
print_didnt_find_it(f'Unable to get a OC_ROOT directory using git rev-parse')
|
|
452
452
|
else:
|
|
453
453
|
_oc_root = cp.stdout.strip()
|
|
454
|
+
if sys.platform == 'win32':
|
|
455
|
+
_oc_root = _oc_root.replace('/', '\\') # git gives us /, but we need \
|
|
454
456
|
|
|
455
457
|
# there is no sense running through this code more than once
|
|
456
458
|
_oc_root_set = True
|
|
@@ -580,6 +582,8 @@ def write_shell_command_file(dirpath : str, filename : str, command_lists : list
|
|
|
580
582
|
assert type(command_lists) is list, f'{command_lists=}'
|
|
581
583
|
fullpath = os.path.join(dirpath, filename)
|
|
582
584
|
with open(fullpath, 'w') as f:
|
|
585
|
+
if not bash_path:
|
|
586
|
+
bash_path = "/bin/bash" # we may not get far, but we'll try
|
|
583
587
|
f.write('#!' + bash_path + '\n\n')
|
|
584
588
|
for obj in command_lists:
|
|
585
589
|
assert isinstance(obj, list), f'{obj=} (obj must be list/ShellCommandList) {command_lists=}'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opencos-eda
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.32
|
|
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
|