opencos-eda 0.3.13__py3-none-any.whl → 0.3.15__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/_version.py CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  import sys
4
4
 
5
+ # pylint: disable=invalid-name
6
+
5
7
  NAME = 'opencos-eda'
6
8
 
7
9
  # Use standard library metadata module starting Python 3.8
@@ -19,4 +21,4 @@ else:
19
21
  ver = "unknown" # Or raise an error, or handle differently
20
22
 
21
23
 
22
- VERSION = ver # pylint: disable=invalid-name
24
+ VERSION = ver
opencos/_waves_pkg.sv CHANGED
@@ -26,27 +26,25 @@ package _waves_pkg;
26
26
  automatic string trace_str_value = "";
27
27
  void'($value$plusargs("trace=%s", trace_str_value));
28
28
  if (trace_str_value.tolower() == "vcd") begin
29
- $display("%t %m: Starting tracing to ./dump.vcd, plusarg +trace=%s",
30
- $realtime, trace_str_value);
29
+ $display("%t %m: Starting tracing to ./dump.vcd, plusarg +trace=vcd", $realtime);
31
30
  $dumpfile("dump.vcd");
32
31
  $dumpvars();
33
- return 1;
32
+ end else begin
33
+ $display("%t %m: Starting tracing to ./dump.fst", $realtime);
34
+ $dumpfile("dump.fst");
35
+ $dumpvars();
34
36
  end
35
37
  end
36
38
 
37
- $display("%t %m: Starting tracing to ./dump.fst", $realtime);
38
- $dumpfile("dump.fst");
39
- $dumpvars();
40
39
  return 1;
41
40
 
42
41
  endfunction : init_trace
43
42
 
44
- `elsif RIVIERA
43
+ `elsif IVERILOG
45
44
 
46
45
  bit trace_en_init = 0;
47
46
  bit trace_en = init_trace();
48
47
 
49
- // Note: must be non-automatic function for --tool=riviera
50
48
  function bit init_trace();
51
49
 
52
50
  if (trace_en_init) // only do this once.
@@ -55,26 +53,59 @@ package _waves_pkg;
55
53
  trace_en_init = 1;
56
54
 
57
55
  if ($test$plusargs("trace") != 0) begin
58
- automatic string trace_str_value = "";
56
+ $display("%t %m: Starting tracing to ./dump.vcd, plusarg +trace present", $realtime);
57
+ $dumpfile("dump.vcd");
58
+ $dumpvars();
59
+ return 1;
60
+ end
61
+
62
+ endfunction : init_trace
63
+
64
+ `endif
65
+ `endif
66
+ `endif
67
+
68
+ endpackage : _waves_pkg
69
+
70
+ //
71
+ // For RIVIERA (and SIMULATION, and not disabled):
72
+ // - it will not run system calls from a package function, unless that package was
73
+ // used by the testbench
74
+ // - so we have to
75
+ // - create a side module _waves_module. Fortunately the $dumpvars() in riviera
76
+ // dumps all module hier, not just that from _waves_module.
77
+ // - We will have to include work._waves_module in the vsim call (in riviera.py)
78
+ //
79
+
80
+ // TODO(drew): please test this on a file that doesn't involve ocsim_pkg.sv
81
+
82
+ `ifdef SIMULATION
83
+ `ifndef _WAVES_PKG_DISABLE_DUMPFILE // hook to disable this if user chooses
84
+ `ifdef RIVIERA
85
+
86
+ module _waves_module;
87
+
88
+ string trace_str_value = "";
89
+
90
+ initial begin
91
+
92
+ if ($test$plusargs("trace") != 0) begin
59
93
  void'($value$plusargs("trace=%s", trace_str_value));
60
94
  if (trace_str_value.tolower() == "vcd") begin
61
- $display("%t %m: Starting tracing to ./dump.vcd, plusarg +trace=%s",
62
- $realtime, trace_str_value);
95
+ $display("%t %m: Starting tracing to ./dump.vcd, plusarg +trace=vcd", $realtime);
63
96
  $dumpfile("dump.vcd");
64
97
  $dumpvars();
65
- return 1;
98
+ end else begin
99
+ $display("%t %m: Starting tracing to ./dump.fst", $realtime);
100
+ $dumpfile("dump.fst");
101
+ $dumpvars();
66
102
  end
67
103
  end
68
104
 
69
- $display("%t %m: Starting tracing to ./dump.fst", $realtime);
70
- $dumpfile("dump.fst");
71
- $dumpvars();
72
- return 1;
105
+ end
73
106
 
74
- endfunction : init_trace
107
+ endmodule : _waves_module
75
108
 
76
109
  `endif
77
110
  `endif
78
111
  `endif
79
-
80
- endpackage : _waves_pkg
opencos/commands/shell.py CHANGED
@@ -9,7 +9,7 @@ Not intended to be overriden by Tool based classes.'''
9
9
  # These also share a lot with CommandSim.* methods, so consider refactoring to share code,
10
10
  # for example, CommandShell.do_export could move to CommandDesign, and derived classes
11
11
  # set the allow-listed args to pass to export.
12
- # pylint: disable=too-many-arguments,too-many-positional-arguments
12
+ # pylint: disable=too-many-arguments
13
13
 
14
14
  import os
15
15
 
opencos/commands/sim.py CHANGED
@@ -9,17 +9,22 @@ Note that CommandSim is also a base class for opencos.commands.elab.CommandElab.
9
9
  # pylint: disable=R0801
10
10
 
11
11
  # TODO(drew): clean up CommandSim.check_logs_for_errors and CommandSim.run_commands_check_logs
12
- # pylint: disable=too-many-arguments,too-many-positional-arguments
12
+ # pylint: disable=too-many-arguments
13
13
 
14
14
  import os
15
15
  import shlex
16
16
 
17
+ from pathlib import Path
18
+
17
19
  from opencos import util, export_helper
18
20
  from opencos.eda_base import CommandDesign, Tool
19
21
  from opencos.utils import status_constants
20
22
 
21
23
  from opencos.utils.str_helpers import strip_outer_quotes
22
24
 
25
+ THISPATH = os.path.dirname(__file__)
26
+ WAVES_PKG_SV_FNAME = str((Path(THISPATH) / '..' / '_waves_pkg.sv').resolve())
27
+
23
28
  def parameters_dict_get_command_list(
24
29
  params: dict, arg_prefix: str = '-G',
25
30
  hier_delimiter: str = '.',
@@ -84,6 +89,7 @@ class CommandSim(CommandDesign): # pylint: disable=too-many-public-methods
84
89
  error_on_no_files_or_targets = True
85
90
  error_on_missing_top = True
86
91
  tool_config = {} # Children with Tool parent classes will set on Tool constructor.
92
+ library_map_supported = False
87
93
 
88
94
  command_name = 'sim'
89
95
 
@@ -114,6 +120,8 @@ class CommandSim(CommandDesign): # pylint: disable=too-many-public-methods
114
120
  'verilate-args': [],
115
121
  'ext-defines-sv-fname': '',
116
122
  'license-queue': False,
123
+ 'library-map': [],
124
+ 'add-top-library': [],
117
125
  })
118
126
  self.args_help.update({
119
127
  'pre-sim-tcl': (
@@ -168,6 +176,17 @@ class CommandSim(CommandDesign): # pylint: disable=too-many-public-methods
168
176
  'license-queue': (
169
177
  'Set to enable env vars LICENSE_QUEUE=1 which has effects on certain simulators'
170
178
  ),
179
+ 'library-map': (
180
+ 'list arg (can set multiple) with values LibName:Path, only supported'
181
+ ' by certain simulation tools.'
182
+ ' The Path search is relative to the tool exe, one level above the tool exe,'
183
+ ' or can be absolute path.'
184
+ ),
185
+ 'add-top-library': (
186
+ 'Add additional top levels, for example if you added the "unisim" library'
187
+ ' you may need to --add-top-library=unisim.glbl for it to work with Xilinx'
188
+ ' based projects that require "glbl" to be present at simulation $root scope.'
189
+ ),
171
190
 
172
191
  })
173
192
 
@@ -175,6 +194,9 @@ class CommandSim(CommandDesign): # pylint: disable=too-many-public-methods
175
194
  'uvm-version': { 'choices': ['1.2'] },
176
195
  })
177
196
 
197
+ # only used if self.library_map_supported=True:
198
+ self.library_map = {} # lib-name: path-to.lib dict from self.args['library-map']
199
+
178
200
 
179
201
 
180
202
  def process_parameters_get_list(
@@ -425,7 +447,7 @@ class CommandSim(CommandDesign): # pylint: disable=too-many-public-methods
425
447
  cmds2 = self.get_simulate_command_lists()
426
448
  cmds3 = self.get_post_simulate_command_lists()
427
449
  '''
428
- return
450
+ self.update_library_map()
429
451
 
430
452
 
431
453
  def check_logs_for_errors( # pylint: disable=dangerous-default-value,too-many-locals,too-many-branches
@@ -619,8 +641,7 @@ class CommandSim(CommandDesign): # pylint: disable=too-many-public-methods
619
641
  break
620
642
 
621
643
  if not found_dumpfile:
622
- thispath = os.path.dirname(__file__)
623
- file_to_add = os.path.join(thispath, '..', '_waves_pkg.sv')
644
+ file_to_add = WAVES_PKG_SV_FNAME
624
645
  util.info(f'--waves arg present, no $dumpfile found, adding SV file: {file_to_add}')
625
646
  self.add_file(file_to_add)
626
647
 
@@ -686,3 +707,56 @@ class CommandSim(CommandDesign): # pylint: disable=too-many-public-methods
686
707
 
687
708
  if 'LICENSE_QUEUE' not in os.environ:
688
709
  os.environ['LICENSE_QUEUE'] = '1'
710
+
711
+ def update_library_map( # pylint: disable=dangerous-default-value
712
+ self, base_search_paths: list = []
713
+ ) -> None:
714
+ '''
715
+ Returns None, uses self.args['library-map'] to update:
716
+
717
+ - self.library_map (dict)
718
+ - self.args['sim-library']
719
+ '''
720
+ if not self.args['library-map']:
721
+ return
722
+
723
+ if not self.library_map_supported:
724
+ tool = self.config.get('tool', None)
725
+ util.warning(f'Command: sim, --tool={tool}, args for --library-map are not supported:',
726
+ f'{self.args["library-map"]}')
727
+ return
728
+
729
+ for libmap in self.args['library-map']:
730
+ parts = libmap.split(':')
731
+ lib_name = parts[0]
732
+ lib_path = Path(':'.join(parts[1:]))
733
+ lib_abs_path = None
734
+
735
+ if not lib_name or not lib_path:
736
+ util.warning(f'library-map={libmap} could not parse {lib_name=} or {lib_path=}')
737
+ continue
738
+
739
+ if lib_name in self.library_map:
740
+ util.warning(
741
+ f'We have already mapped "{lib_name}" to {self.library_map[lib_name]}'
742
+ )
743
+
744
+ # We have to go looking for lib_path though
745
+ search_files = [lib_path]
746
+ if base_search_paths:
747
+ for x in base_search_paths:
748
+ search_files.append(Path(x) / lib_path)
749
+ for x in search_files:
750
+ if x.exists():
751
+ lib_abs_path = x.resolve()
752
+ util.info(f'library-map={libmap} found "{lib_name}" in: {lib_abs_path}')
753
+ break
754
+ util.debug(f'library-map={libmap} searching for "{lib_name}" in: {x}')
755
+
756
+
757
+ if lib_abs_path:
758
+ self.library_map[lib_name] = lib_abs_path
759
+ if lib_name not in self.args['sim-library']:
760
+ self.args['sim-library'].append(lib_name)
761
+ else:
762
+ util.warning(f'library-map={libmap}, for "{lib_name}" could not find {lib_path=}')
@@ -123,7 +123,7 @@ class CommandUpload(Command):
123
123
  def get_list_bitfiles(self, display: bool = True) -> list:
124
124
  '''Returns a list of bit files (ending with self.SUPPORTED_BIT_EXT)'''
125
125
 
126
- bitfiles: list[Path] = []
126
+ bitfiles = [] # list[Path]
127
127
 
128
128
  targets, files = self.get_targets_or_files_from_unparsed_args()
129
129
  targets.extend(files)
@@ -136,7 +136,7 @@ class CommandUpload(Command):
136
136
  if os.path.isfile(fullpath) and fullpath not in bitfiles:
137
137
  bitfiles.append(fullpath)
138
138
 
139
- matched: list[Path] = []
139
+ matched = [] # list[Path]
140
140
  for cand in bitfiles:
141
141
  debug(f"Looking for {cand=} in {targets=}")
142
142
  passing = all(re.search(t, str(cand)) for t in targets)
@@ -412,7 +412,8 @@ tools:
412
412
  -acdb -acdb_cov sbfectapm
413
413
  simulate-coverage-tcl:
414
414
  - acdb save
415
- - acdb report -db work.acdb -txt -o cov.txt
415
+ - acdb report -i work.acdb -txt -o cov.txt
416
+ - acdb report -i work.acdb -txt -o covg.txt -show covergroups
416
417
 
417
418
 
418
419
  modelsim_ase:
@@ -111,8 +111,8 @@ def get_handler_tool_version(tool: str, eda_command: str, config: dict) -> str:
111
111
 
112
112
 
113
113
 
114
- def get_handler_info_with_versions( # pylint: disable=too-many-branches
115
- config: dict | None = None,
114
+ def get_handler_info_with_versions( # pylint: disable=too-many-branches,dangerous-default-value
115
+ config: dict = {},
116
116
  include_commands: bool = True,
117
117
  sort: bool = True
118
118
  ) -> str:
@@ -202,8 +202,8 @@ def get_handler_info_with_versions( # pylint: disable=too-many-branches
202
202
  return info
203
203
 
204
204
 
205
- def pretty_info_handler_tools(
206
- info: dict | None = None, config: dict | None = None, command: str | None = ''
205
+ def pretty_info_handler_tools( # pylint: disable=dangerous-default-value
206
+ info: dict = {}, config: dict = {}, command: str = ''
207
207
  ) -> None:
208
208
  '''Pretty print (via util.info) the result from get_handler_info_with_versions()
209
209
 
opencos/tools/iverilog.py CHANGED
@@ -70,6 +70,7 @@ class CommandSimIverilog(CommandSim, ToolIverilog):
70
70
  # We do not override CommandSim.do_it()
71
71
  def prepare_compile(self):
72
72
  self.set_tool_defines()
73
+ self.update_library_map()
73
74
 
74
75
  self.iverilog_command_lists = self.get_compile_command_lists()
75
76
  self.iverilog_exec_command_lists = self.get_simulate_command_lists()
@@ -150,6 +150,8 @@ class CommonSimQuesta(CommandSim, ToolQuesta):
150
150
 
151
151
  def prepare_compile(self):
152
152
  self.set_tool_defines()
153
+ self.update_library_map()
154
+ self.add_waves_pkg_file()
153
155
  self.write_vlog_dot_f()
154
156
  self.write_vsim_dot_do(dot_do_to_write='all')
155
157
 
@@ -388,6 +390,10 @@ class CommonSimQuesta(CommandSim, ToolQuesta):
388
390
  + f" -sv_seed {self.args['seed']} {sim_plusargs_str} {vsim_suppress_list_str}" \
389
391
  + f" {voptargs_str} {vsim_ext_args} work.{self.args['top']}"
390
392
 
393
+ # If there are additional top level libs, we wont' add them to the vopt step, add
394
+ # to vsim only (after work.TOP):
395
+ for l in self.args['add-top-library']:
396
+ vsim_one_liner += f' {l}'
391
397
 
392
398
  vsim_one_liner = vsim_one_liner.replace('\n', ' ')
393
399
 
opencos/tools/riviera.py CHANGED
@@ -9,9 +9,12 @@ Contains classes for ToolRiviera, CommandSimRiviera, CommandElabRiviera.
9
9
  import os
10
10
  import subprocess
11
11
 
12
+ from pathlib import Path
13
+
12
14
  from opencos import util
13
15
  from opencos.commands import CommandFList
14
16
  from opencos.files import safe_shutil_which
17
+ from opencos.commands.sim import WAVES_PKG_SV_FNAME
15
18
  from opencos.tools.questa_common import ToolQuesta, CommonSimQuesta
16
19
  from opencos.utils.str_helpers import sanitize_defines_for_sh
17
20
  from opencos.utils import status_constants
@@ -65,6 +68,8 @@ class ToolRiviera(ToolQuesta):
65
68
  class CommandSimRiviera(CommonSimQuesta, ToolRiviera):
66
69
  '''CommandSimRiviera is a command handler for: eda sim --tool=riviera'''
67
70
 
71
+ library_map_supported = True
72
+
68
73
  def __init__(self, config: dict):
69
74
  CommonSimQuesta.__init__(self, config=config)
70
75
 
@@ -123,8 +128,6 @@ class CommandSimRiviera(CommonSimQuesta, ToolRiviera):
123
128
  def compile(self):
124
129
  '''Override for CommandSimModelsimAse.compile() so we can set our own must_strings'''
125
130
 
126
- self.add_waves_pkg_file()
127
-
128
131
  if self.args['stop-before-compile']:
129
132
  # don't run anything, save everyting we've already run in _prep_compile()
130
133
  return
@@ -190,6 +193,9 @@ class CommandSimRiviera(CommonSimQuesta, ToolRiviera):
190
193
  '-dbg'
191
194
  ])
192
195
 
196
+ # Note, in Riviera we have to put sim libs in vsim call (with -L) and in vlog (with -l)
197
+ vlog_dot_f_lines.extend([f'-l {x}' for x in self.args['sim-library']])
198
+
193
199
  for value in self.incdirs:
194
200
  vlog_dot_f_lines += [ f"+incdir+{value}" ]
195
201
 
@@ -233,7 +239,7 @@ class CommandSimRiviera(CommonSimQuesta, ToolRiviera):
233
239
 
234
240
 
235
241
 
236
- def write_vsim_dot_do( # pylint: disable=too-many-branches,too-many-locals
242
+ def write_vsim_dot_do( # pylint: disable=too-many-branches,too-many-locals,too-many-statements
237
243
  self, dot_do_to_write: list
238
244
  ) -> None:
239
245
  '''Writes files(s) based on dot_do_to_write(list of str)
@@ -278,7 +284,10 @@ class CommandSimRiviera(CommonSimQuesta, ToolRiviera):
278
284
  )
279
285
  )
280
286
 
281
- vsim_libs = ' '.join([f'-l {x}' for x in self.args['sim-library']])
287
+ # Note, in Riviera we have to put sim libs in vsim call (with -L) and in vlog (with -l)
288
+ # we previously updated self.args['sim-library'] with self.update_library_map()
289
+ vmap_lines_str = self.get_vmap_lines_str()
290
+ vsim_libs = ' '.join([f'-L {x}' for x in self.args['sim-library']])
282
291
 
283
292
  vsim_one_liner = (
284
293
  "vsim"
@@ -286,11 +295,20 @@ class CommandSimRiviera(CommonSimQuesta, ToolRiviera):
286
295
  f" {voptargs_str} {vsim_ext_args} {vsim_libs} work.{self.args['top']}"
287
296
  )
288
297
 
298
+ if self.args['waves'] and WAVES_PKG_SV_FNAME in self.files:
299
+ # kind of a hack, but add _waves_module (from _waves_pkg.sv) if that file
300
+ # was in our files list.
301
+ vsim_one_liner += ' work._waves_module'
302
+
303
+ for l in self.args['add-top-library']:
304
+ vsim_one_liner += f' {l}'
305
+
289
306
  vsim_one_liner = vsim_one_liner.replace('\n', ' ') # needs to be a one-liner
290
307
 
291
308
  vsim_vlogonly_dot_do_lines = [
292
309
  "if {[file exists work]} { vdel -all work; }",
293
310
  "vlib work;",
311
+ vmap_lines_str,
294
312
  "if {[catch {vlog -f vlog.f} result]} {",
295
313
  " echo \"Caught $result \";",
296
314
  " if {[batch_mode]} {",
@@ -306,6 +324,7 @@ class CommandSimRiviera(CommonSimQuesta, ToolRiviera):
306
324
  "if {[file exists work]} { vdel -all work; }",
307
325
  "vlib work;",
308
326
  "set qc 30;",
327
+ vmap_lines_str,
309
328
  "if {[catch {vlog -f vlog.f} result]} {",
310
329
  " echo \"Caught $result \";",
311
330
  " if {[batch_mode]} {",
@@ -327,6 +346,7 @@ class CommandSimRiviera(CommonSimQuesta, ToolRiviera):
327
346
  "if {[file exists work]} { vdel -all work; }",
328
347
  "vlib work;",
329
348
  "set qc 30;",
349
+ vmap_lines_str,
330
350
  "if {[catch {vlog -f vlog.f} result]} {",
331
351
  " echo \"Caught $result \";",
332
352
  " if {[batch_mode]} {",
@@ -407,6 +427,38 @@ class CommandSimRiviera(CommonSimQuesta, ToolRiviera):
407
427
 
408
428
  return ' '.join(vsim_suppress_list)
409
429
 
430
+ def update_library_map( # pylint: disable=dangerous-default-value
431
+ self, base_search_paths: list = []
432
+ ) -> None:
433
+ '''Override from sim::CommandSim
434
+
435
+ We add some common places to look relative to the Riviera install paths
436
+ '''
437
+ bsp = [] + base_search_paths
438
+ bsp += [
439
+ Path(self.sim_exe_base_path),
440
+ Path(self.sim_exe_base_path) / '..',
441
+ Path(self.sim_exe_base_path) / '..' / 'vlib',
442
+ ]
443
+ super().update_library_map(base_search_paths=bsp)
444
+
445
+ def get_vmap_lines_str(self) -> str:
446
+ '''Returns an empty str, or single str in the form:
447
+
448
+ vmap -global LibraryName AbsolutePathToDotLibFile
449
+ vmap -global LibraryName2 AbsolutePathToAnotherDotLibFile
450
+ ...
451
+ uses self.args['library-map'], updates self.args['sim-library']
452
+ '''
453
+ if not self.library_map:
454
+ return ''
455
+
456
+ lines = []
457
+ for lib_name, lib_file_path in self.library_map.items():
458
+ lines.append(f'vmap -global {lib_name} {lib_file_path}')
459
+
460
+ return '\n'.join(lines)
461
+
410
462
 
411
463
  class CommandElabRiviera(CommandSimRiviera):
412
464
  '''CommandElabRiviera is a command handler for: eda elab --tool=riviera'''
@@ -147,6 +147,7 @@ class VerilatorSim(CommandSim, ToolVerilator):
147
147
  # We do not override CommandSim.do_it()
148
148
  def prepare_compile(self):
149
149
  self.set_tool_defines()
150
+ self.update_library_map()
150
151
 
151
152
  # If there are C++ files here, then we will run Verilator in --cc mode:
152
153
  if self.files_cpp:
@@ -249,6 +250,10 @@ class VerilatorSim(CommandSim, ToolVerilator):
249
250
  '-top', self.args['top'],
250
251
  ]
251
252
 
253
+ if self.args['add-top-library']:
254
+ util.warning('--add-top-library: currently not supported in eda --tool=verilator:',
255
+ f'{self.args["add-top-library"]}')
256
+
252
257
  if not lint_only:
253
258
  verilate_command_list += [
254
259
  '-o', 'sim.exe',
opencos/tools/vivado.py CHANGED
@@ -39,7 +39,10 @@ class ToolVivado(Tool):
39
39
  })
40
40
  self.args_help.update({
41
41
  'part': 'Device used for commands: synth, build.',
42
- 'add-glbl-v': '(for simulation) add glbl.v to filelist',
42
+ 'add-glbl-v': (
43
+ '(for simulation) add glbl.v to filelist, "glbl" to sim libraries, and "glbl"'
44
+ ' as an additional top level hier.'
45
+ ),
43
46
  })
44
47
 
45
48
 
@@ -124,6 +127,8 @@ class CommandSimVivado(CommandSim, ToolVivado):
124
127
  Note that we attempt to run a generated .tcl script within vivado, that will perform the
125
128
  3-step compile/elaborate/simulate steps'''
126
129
 
130
+ library_map_supported = True
131
+
127
132
  def __init__(self, config: dict):
128
133
  CommandSim.__init__(self, config)
129
134
  ToolVivado.__init__(self, config=self.config)
@@ -139,7 +144,16 @@ class CommandSimVivado(CommandSim, ToolVivado):
139
144
  'gui': 'Run Vivado XSim in GUI mode',
140
145
  'tcl-file': 'name of TCL file to be created for XSim',
141
146
  'fpga': 'FPGA device name, can be used for various Xilinx IP or XCIs',
142
- 'add-glbl-v': 'Use the glbl.v in xvlog for this version of Vivado',
147
+ 'add-glbl-v': (
148
+ 'Use the glbl.v in xvlog, xelab for this version of Vivado. Adds glbl.v to'
149
+ ' filelist(s), and add "glbl" as an additional top level hier to xelab.'
150
+ ),
151
+ 'library-map': (
152
+ 'list arg (can set multiple) with values LibName:Path, for example:'
153
+ ' --library-map=unisim:path/to/custom_lib_name.lib'
154
+ ' The Path search is relative to the tool exe, one level above the tool exe,'
155
+ ' or can be absolute path.'
156
+ )
143
157
  })
144
158
 
145
159
  self.sim_libraries = self.tool_config.get('sim-libraries', [])
@@ -165,6 +179,7 @@ class CommandSimVivado(CommandSim, ToolVivado):
165
179
 
166
180
  def prepare_compile(self):
167
181
  self.set_tool_defines()
182
+ self.update_library_map()
168
183
 
169
184
  # Don't use the return values, these will set values in self.vivado_tcl:
170
185
  self.get_compile_command_lists()
@@ -321,11 +336,13 @@ class CommandSimVivado(CommandSim, ToolVivado):
321
336
  command_list += ['-debug', 'wave']
322
337
  if util.args['verbose']:
323
338
  command_list += ['-v', '2']
324
- if self.args['sim-library'] or self.args['add-glbl-v']:
339
+ if self.args['sim-library']:
325
340
  self.sim_libraries += self.args['sim-library'] # Add any command line libraries
326
- for x in self.sim_libraries:
327
- command_list += ['-L', x]
328
- command_list += ['glbl']
341
+ for x in self.sim_libraries:
342
+ command_list += ['-L', x]
343
+ if self.args['add-top-library']:
344
+ command_list += self.args['add-top-library'] # list
345
+
329
346
  command_list += self.args['elab-args']
330
347
 
331
348
  # For Windows compatibility, we have some issues with command/Powershell passing args
@@ -447,6 +464,10 @@ class CommandSimVivado(CommandSim, ToolVivado):
447
464
  command_list += self.tool_config.get('compile-args', '').split()
448
465
  if util.args['verbose']:
449
466
  command_list += ['-v', '2']
467
+
468
+ # If there were any external .lib files from --library-map args, add those now:
469
+ command_list.extend(self._get_xvlog_library_map_list())
470
+
450
471
  for value in self.incdirs:
451
472
  command_list.append('-i')
452
473
  command_list.append(Path(value).as_posix())
@@ -491,13 +512,28 @@ class CommandSimVivado(CommandSim, ToolVivado):
491
512
  glbl_v = self.vivado_base_path.replace(
492
513
  'bin', os.path.join('data', 'verilog', 'src', 'glbl.v')
493
514
  )
494
- if any(x.endswith('glbl.v') for x in self.files_v):
515
+ if any(x and os.path.split(x)[1] == 'glbl.v' for x in self.files_v):
495
516
  util.warning(f'--add-glbl-v: Not adding {glbl_v=} b/c glbl.v already in',
496
517
  f'{self.files_v=}')
497
518
  elif not os.path.exists(glbl_v):
498
519
  self.error(f"Could not find file {glbl_v=}")
499
520
  else:
500
521
  self.files_v.insert(0, glbl_v)
522
+ # add to self.args['add-top-library']
523
+ if 'glbl' not in self.args['add-top-library']:
524
+ self.args['add-top-library'].append('glbl')
525
+
526
+ def _get_xvlog_library_map_list(self) -> list:
527
+ '''Returns list of lines used in vlog step for --library-map args
528
+
529
+ Note that Vivado does not do library name re-mapping, the name comes
530
+ from the .lib file internals.
531
+ '''
532
+
533
+ lines = []
534
+ for _, lib_file_path in self.library_map.items():
535
+ lines.append(f'-libmap {lib_file_path}')
536
+ return lines
501
537
 
502
538
 
503
539
  def artifacts_add(self, name: str, typ: str, description: str) -> None:
opencos/tools/yosys.py CHANGED
@@ -22,7 +22,7 @@ def get_commands_to_run_scriptfiles(
22
22
 
23
23
  list of yoysys script(s)'''
24
24
 
25
- if script_fnames_list:
25
+ if not script_fnames_list:
26
26
  return []
27
27
 
28
28
  yosys_cmdlists = []
@@ -142,7 +142,12 @@ class CommonSynthYosys(CommandSynth, ToolYosys):
142
142
  'yosys-scriptfile': (
143
143
  'Instead of using a built-in flow from eda, use your own scripts that are called'
144
144
  ' via: yosys --scriptfile <this-arg>. You can set multiple args for multiple'
145
- ' scriptfile (appends)'
145
+ ' scriptfile (appends). NOTE: the default for eda is to run in a work-dir such as'
146
+ ' ./eda.work/<target>.synth/, which means you may want to use absolute paths for'
147
+ ' source files (.sv, etc) in your custom scriptfile, or use ../.. to get back to '
148
+ ' the current directory. If you want to run in place and avoid'
149
+ ' ./eda.work/<target>.synth/ you can use arg --work-dir=. or to run in place from'
150
+ ' the DEPS target directory, use --work-dir-use-target-dir'
146
151
  ),
147
152
  'sta-scriptfile': (
148
153
  'Instead of using a built-in flow from eda, use your own script that is called'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opencos-eda
3
- Version: 0.3.13
3
+ Version: 0.3.15
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
@@ -1,16 +1,16 @@
1
1
  opencos/__init__.py,sha256=RwJA9oc1uUlvNX7v5zoqwjnSRNq2NZwRlHqtS-ICJkI,122
2
- opencos/_version.py,sha256=KaWIjS0c08g-C0fgYY1kXwSPqhOFxaq5pYEeoZhOR_I,617
3
- opencos/_waves_pkg.sv,sha256=TL5YT9lT-fn2FD54MbVVZROmZ7vtW3ScA_rM2eRzKmU,2068
2
+ opencos/_version.py,sha256=FLlmTepF7P0hC-506fgEvv3NSxGxtWgeR7g2UkNK7PI,618
3
+ opencos/_waves_pkg.sv,sha256=yWojzRYVIqV2H5xa5e0v34LgK4oLMu3k9_N8EYXy2f0,2852
4
4
  opencos/deps_schema.py,sha256=wKRMuFzOIapwpCPFGvWGM8Mcwdh9yngHOiDRMmvUaIg,17394
5
5
  opencos/eda.py,sha256=2vJLMYMW9muWieNaOJz-U5EIVchmVyhTfmEcnZwQtvg,37382
6
6
  opencos/eda_base.py,sha256=-nguHrrYVb8a853HEMfFrOoXlsEEeRnDdFR66nTwX0s,124332
7
7
  opencos/eda_config.py,sha256=EPW0rhnbrpfV9h0OtKrp7By19FcEyDXT2-ud7y4jbRU,17266
8
- opencos/eda_config_defaults.yml,sha256=xRJWps4On748MAFIfOIvLNOv5cyON7xAeaW5XquJSp0,21534
8
+ opencos/eda_config_defaults.yml,sha256=0rq6DNw2U0OjuoZPmYVDgPwu_WoaGUQmaNE3l7sP4wA,21601
9
9
  opencos/eda_config_reduced.yml,sha256=BOKGfe-OmVIF0SKhTTglPIzfAoGuCZ8n-f2KpoLF8dk,883
10
10
  opencos/eda_deps_bash_completion.bash,sha256=o1yZvGUQSbN-AYq95sDTzMFw7gNHCUSlv9tASEHnACA,2763
11
11
  opencos/eda_deps_sanitize.py,sha256=SQjvrte9Hv9JesRY0wljvbdC6pAmLCikI-Wdzzy-D04,1939
12
12
  opencos/eda_extract_targets.py,sha256=POlxZfqf2dNH2nc1CEw5B_53vSHAicSTkpU9_-2_6Zw,2851
13
- opencos/eda_tool_helper.py,sha256=NoVUvUeqvM18Svx1Oy4R8xM4Numq_YZneKyHSDnMMnY,8546
13
+ opencos/eda_tool_helper.py,sha256=7KY-E7wnWCNRHXeekDg1tFivcZw86-MsrmXiw7Fc6h0,8578
14
14
  opencos/export_helper.py,sha256=zDkvsUS6FVrpXl1UTy53QG3CuhYp5FFplI9rRzAE2g8,25395
15
15
  opencos/export_json_convert.py,sha256=tSIMbLFtc_Fo66EhFovMii1v_qJYyFZJrPNnoPdW7L0,4182
16
16
  opencos/files.py,sha256=-vHrddbFrwxEHU47VzeyLOU93q8XSXAmPiopClfV-bs,2296
@@ -29,12 +29,12 @@ opencos/commands/lint.py,sha256=piPb0l0zE3sAtNJkFQ-oNpuHxnaV_RNXkXtEj_9mwGs,1594
29
29
  opencos/commands/multi.py,sha256=urm-IDllnMZWScH7e6Pg4ukHGHILBd4NbPlPmHU3vsw,27624
30
30
  opencos/commands/open.py,sha256=XckvKUNwvc5KHbYGV-eQ2i0WG4X-yckroDaMC610MB4,804
31
31
  opencos/commands/proj.py,sha256=cExW9ZZkw6nkpVyNfeQzJADzmPtbYgBgWml82tqO6jY,1158
32
- opencos/commands/shell.py,sha256=upHpFs8Gdtzi-boVXwsC-QzEsnvtoZNMAu4oN10kdxw,7801
33
- opencos/commands/sim.py,sha256=ifdSpOVmxMWkQ65-9lhwMNZM4F3MXokjJJBm4puyVX4,28573
32
+ opencos/commands/shell.py,sha256=WPKS27fTr0MG4Gqz_RzSwv4n8AINuQ_ntSmJtHeat_I,7771
33
+ opencos/commands/sim.py,sha256=-dBxyHWMlUeLllsyhHa82jYKcLWxZA9qntS_vbeV3V0,31569
34
34
  opencos/commands/sweep.py,sha256=62XmDHT-prdxJNy-6MbK6wEGJm1YC9caOaJapoekQ8s,9325
35
35
  opencos/commands/synth.py,sha256=Qs6FP9Ge_gp9TH3EFzVXKFlrrqrMwIbr38VYVlZvmeA,4557
36
36
  opencos/commands/targets.py,sha256=_jRNhm2Fqj0fmMvTw6Ba39DCsRHf_r_uZCy_R064kpA,1472
37
- opencos/commands/upload.py,sha256=D5ln2gXsRHbPkOcy8S9jcwv-x6N4SK3m49urr1CLKo0,7915
37
+ opencos/commands/upload.py,sha256=OGMI4By0942jL9LK7xBy5_WjvVzRbAr_RB3rS5fNobI,7917
38
38
  opencos/commands/waves.py,sha256=LYF1UcxkHFYYtYoebnh9iE_on80PbbmzIpaSk-XtZcI,9232
39
39
  opencos/deps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
40
  opencos/deps/defaults.py,sha256=Z6mIVJEV0zQ9rC-HkQFMBFAkixjqKS1TATPSc27wOeA,1502
@@ -61,21 +61,21 @@ opencos/tools/cocotb.py,sha256=mkhdbBbkOcPPct1TZcKH6wPPT7pjzRH_6wCNH2qgXOM,19660
61
61
  opencos/tools/invio.py,sha256=pxrS5oaNTcEv-ToXdhFBJZF5XhTmZnJz9CQ8NnLoty8,3155
62
62
  opencos/tools/invio_helpers.py,sha256=86WOGmSf4m_lEqBtK3DLjWqI0jnqAWzBEBRYfBUGiSY,8804
63
63
  opencos/tools/invio_yosys.py,sha256=zPVX5Bv-mR4zaUZiH0QqGF4Vbm_LXAf75mDW6ywse5c,6026
64
- opencos/tools/iverilog.py,sha256=7R4wL1udfn0WdckPDsYM75GgYW9DeCfPUQEOe-8SGVM,6755
64
+ opencos/tools/iverilog.py,sha256=aehXQV22U7MIaH8XuEI9ApWztsez0NaW960_Z01oZWc,6789
65
65
  opencos/tools/modelsim_ase.py,sha256=NEzAXJtiVWkKb3N-O3PYxSnnFmrq8LNrqjxFNBwzfKI,2254
66
66
  opencos/tools/quartus.py,sha256=gtswIhpnHjUTmw5g1BRxhjB6tofXEsx-I6IySjwyF94,32303
67
67
  opencos/tools/questa.py,sha256=QP0JCt8rWf0-snncNP0_Pi6oRY6_Z9Hwix1IYlRdGEc,2057
68
- opencos/tools/questa_common.py,sha256=oVytNlwLK-W6yUYqOwlWjPrDd0kWJV4-FnWgppkSX8k,21647
68
+ opencos/tools/questa_common.py,sha256=JYF4MrAcELurcA-t3Hzjb9KKtzHBEEYmXWKWAt8Gi0c,21931
69
69
  opencos/tools/questa_fe.py,sha256=yYNlUnA2pQ8-gELLajnvJgqg6ZXb6F26YRmyvrlNFOA,2155
70
70
  opencos/tools/questa_fse.py,sha256=CjOAn1Ik-3Hd-vyUH_WyTTJxH2yPfhNEfXbedCir7J4,2116
71
- opencos/tools/riviera.py,sha256=LgLartBXWwJIoI4zRFL7X2wk6hu2wa0CIJCNBZOGxUc,17509
71
+ opencos/tools/riviera.py,sha256=SsBOQ-xQQeBr_jPKI50bGzFHXKQeAa7WX3Ql6AC-3wE,19535
72
72
  opencos/tools/slang.py,sha256=MxRwu4laSbv7oa3lO-BKg4McL7KAckSA003sL-9sY3U,9682
73
73
  opencos/tools/slang_yosys.py,sha256=z8gUcNSGDl5S6Ufxdx54WWe5v73w0UydErBKFWBR6ZI,10154
74
74
  opencos/tools/surelog.py,sha256=QaXS1EWI2b1TqBoekpXndoHxS6t2e8SD-I2Ryi-gHGs,6666
75
75
  opencos/tools/tabbycad_yosys.py,sha256=J4RgfuzYLiBK1U8odXiovXZhgkcDFPlbxt73SppksVA,7657
76
- opencos/tools/verilator.py,sha256=cx4q1WrterA5Kcn8bt8ukqthS0030swGOFOsoMRBYvw,25131
77
- opencos/tools/vivado.py,sha256=c8iHVK76de_25iOqN-PJ7O6n1lRopvO_XCM0HZV3c04,48702
78
- opencos/tools/yosys.py,sha256=DZyqAnrHT-6Wv6TlIwzuv4qw7HZs4vOXPpxZzErRsnY,28292
76
+ opencos/tools/verilator.py,sha256=uxJs5VpE6pHIR3c5bJbQbjSoymIqNOG861ix2IR_c3Y,25363
77
+ opencos/tools/vivado.py,sha256=BHnfJ-TqUYwdKFC1zHJ3x6xkLOgn2xdQbxySbBEWFYk,50149
78
+ opencos/tools/yosys.py,sha256=8r3pxNod-ntWAHrDDL0HCT9mCkZ6qcNnOtLnIpOTi9g,28807
79
79
  opencos/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
80
  opencos/utils/dict_helpers.py,sha256=xCdfE8SE-D6hNu5dG_d46A2g6au6h1h7SFpzYmeyRtA,810
81
81
  opencos/utils/markup_helpers.py,sha256=F_Emh2kT2gETYf7C-Jy5yJjsiHiPUtBpQzONsCka6Eo,4604
@@ -84,10 +84,10 @@ opencos/utils/str_helpers.py,sha256=ctl0Zh0h0JW7OlReeSdGxB9wODQYzmMO-9-h55rSRv0,
84
84
  opencos/utils/subprocess_helpers.py,sha256=Wqqs8FKm3XIjmD9GUYM-HWVJH7TxWJJA37A07J4fQ4w,6619
85
85
  opencos/utils/vscode_helper.py,sha256=8epyEeYfXONwiSoc5KZjUfKc8vgLryct8yckJYie88U,1398
86
86
  opencos/utils/vsim_helper.py,sha256=-TJK4Dh8LZ4DCM8GrS9Wka4HE_WMGG_aKwTZtKBrEOE,2994
87
- opencos_eda-0.3.13.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
88
- opencos_eda-0.3.13.dist-info/licenses/LICENSE.spdx,sha256=8gn1610RMP6eFgT3Hm6q9VKXt0RvdTItL_oxMo72jII,189
89
- opencos_eda-0.3.13.dist-info/METADATA,sha256=ryUfx_mmUFaZcwGr8lXFXrkY2whYhLB-HcQCfKSMtn8,1165
90
- opencos_eda-0.3.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
91
- opencos_eda-0.3.13.dist-info/entry_points.txt,sha256=QOlMZnQeqqwOzIaeKBcY_WlMR3idmOAEbGFh2dXlqJw,290
92
- opencos_eda-0.3.13.dist-info/top_level.txt,sha256=J4JDP-LpRyJqPNeh9bSjx6yrLz2Mk0h6un6YLmtqql4,8
93
- opencos_eda-0.3.13.dist-info/RECORD,,
87
+ opencos_eda-0.3.15.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
88
+ opencos_eda-0.3.15.dist-info/licenses/LICENSE.spdx,sha256=8gn1610RMP6eFgT3Hm6q9VKXt0RvdTItL_oxMo72jII,189
89
+ opencos_eda-0.3.15.dist-info/METADATA,sha256=eMegaTVGReQYdwr58zGGkc8fmhuJywlujQ1wawgA4dA,1165
90
+ opencos_eda-0.3.15.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
91
+ opencos_eda-0.3.15.dist-info/entry_points.txt,sha256=QOlMZnQeqqwOzIaeKBcY_WlMR3idmOAEbGFh2dXlqJw,290
92
+ opencos_eda-0.3.15.dist-info/top_level.txt,sha256=J4JDP-LpRyJqPNeh9bSjx6yrLz2Mk0h6un6YLmtqql4,8
93
+ opencos_eda-0.3.15.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5