opencos-eda 0.2.53__py3-none-any.whl → 0.2.54__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
opencos/commands/flist.py CHANGED
@@ -214,6 +214,6 @@ class CommandFList(CommandDesign):
214
214
  print() # don't need to close fo (None)
215
215
  else:
216
216
  fo.close()
217
- util.info(f"Created {self.args['out']}")
217
+ util.info(f"Created file: {self.args['out']}")
218
218
 
219
219
  self.write_eda_config_and_args()
opencos/commands/sim.py CHANGED
@@ -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:
opencos/eda_base.py CHANGED
@@ -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
- util.write_shell_command_file(
997
- dirpath=self.args['work-dir'], filename='pre_compile_dep_shell_commands.sh',
998
- command_lists=all_cmds_lists
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'], self.args['top-path'] = last_potential_top_target
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']} ({self.args['top-path']})")
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
- self.args['top-path'] = last_potential_top_file[1] # from tuple: (top, fpath)
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']} ({self.args['top-path']})")
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.warning(
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 ['top-path'] + remove_args:
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'''
opencos/tests/test_eda.py CHANGED
@@ -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
- [ './simulate_only.sh' ], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
173
+ [ './simulate.sh' ], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
174
174
  check=True
175
175
  )
176
176
  rc = res.returncode
opencos/tools/cocotb.py CHANGED
@@ -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
- util.write_shell_command_file(
126
- dirpath=self.args['work-dir'],
127
- filename='cocotb_test.sh',
128
- command_lists=self.cocotb_command_lists,
129
- line_breaks=True
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
 
opencos/tools/iverilog.py CHANGED
@@ -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
- util.write_shell_command_file(
89
- dirpath=self.args['work-dir'],
90
- filename='compile_only.sh',
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
- util.write_shell_command_file(
87
- dirpath=self.args['work-dir'],
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()
opencos/tools/quartus.py CHANGED
@@ -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': 'EP4SGX230KF40C2',
38
- 'family': 'Stratix IV',
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='project', description='Quartus Project File'
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='project', description='Quartus Settings File'
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='report', description='Quartus Synthesis Report'
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
- "execute_flow -analysis_and_elaboration",
266
- "execute_flow -compile",
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-path']=}")
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
- eda_path, 'flist',
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(cwd, command_list, tee_fpath=command_list.tee_fpath)
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(f'''# Quartus Build Script
341
- load_package flow
342
- project_new {self.args['design']} -overwrite
343
- set_global_assignment -name FAMILY "{self.args['family']}"
344
- set_global_assignment -name DEVICE {self.args['part']}
345
- set_global_assignment -name TOP_LEVEL_ENTITY {self.args['top']}
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=self.args['work-dir'], file_extension='sof',
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=self.args['work-dir'], file_extension='pof',
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=self.args['work-dir'], file_extension='fit.rpt',
376
- typ='report', description='Quartus Fitter Report'
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=self.args['work-dir'], file_extension='sta.rpt',
380
- typ='report', description='Quartus Timing Analyzer Report'
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.exec(cwd, command_list, tee_fpath=command_list.tee_fpath)
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,
opencos/tools/questa.py CHANGED
@@ -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
- util.write_shell_command_file(dirpath=self.args['work-dir'], filename='compile.sh',
106
- command_lists=self.vlog_commands)
107
- util.write_shell_command_file(dirpath=self.args['work-dir'], filename='elaborate.sh',
108
- command_lists=self.vopt_commands)
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']:
@@ -135,24 +135,18 @@ class VerilatorSim(CommandSim, ToolVerilator):
135
135
  paths = ['obj_dir', 'logs']
136
136
  util.safe_mkdirs(base=self.args['work-dir'], new_dirs=paths)
137
137
 
138
- util.write_shell_command_file(dirpath=self.args['work-dir'], filename='compile_only.sh',
139
- command_lists=self.verilate_command_lists, line_breaks=True)
140
-
141
138
  util.write_shell_command_file(dirpath=self.args['work-dir'], filename='lint_only.sh',
142
139
  command_lists=self.lint_only_command_lists, line_breaks=True)
143
140
 
144
- util.write_shell_command_file(dirpath=self.args['work-dir'], filename='simulate_only.sh',
145
- command_lists = self.verilated_exec_command_lists +
146
- (self.verilated_post_exec_coverage_command_lists
147
- if self.args.get('coverage', True) else [])
148
- )
149
-
150
- util.write_shell_command_file(dirpath=self.args['work-dir'], filename='all.sh',
151
- command_lists = [
152
- ['./pre_compile_dep_shell_commands.sh'],
153
- ['./compile_only.sh'],
154
- ['./simulate_only.sh'],
155
- ])
141
+ sim_cmd_lists = self.verilated_exec_command_lists + \
142
+ (self.verilated_post_exec_coverage_command_lists
143
+ if self.args.get('coverage', True) else [])
144
+
145
+ self.write_sh_scripts_to_work_dir(
146
+ compile_lists=self.verilate_command_lists,
147
+ elaborate_lists=[],
148
+ simulate_lists=sim_cmd_lists
149
+ )
156
150
 
157
151
 
158
152
  def compile(self):
opencos/tools/vivado.py CHANGED
@@ -5,6 +5,7 @@ upload, flist, open, proj.
5
5
  '''
6
6
 
7
7
  # pylint: disable=R0801 # (setting similar, but not identical, self.defines key/value pairs)
8
+ # pylint: disable=too-many-lines
8
9
 
9
10
  import os
10
11
  import re
@@ -152,22 +153,11 @@ class CommandSimVivado(CommandSim, ToolVivado):
152
153
  self.xvlog_commands = self.get_compile_command_lists()
153
154
  self.xelab_commands = self.get_elaborate_command_lists()
154
155
  self.xsim_commands = self.get_simulate_command_lists()
155
-
156
- util.write_shell_command_file(dirpath=self.args['work-dir'], filename='compile.sh',
157
- command_lists=self.xvlog_commands)
158
- util.write_shell_command_file(dirpath=self.args['work-dir'], filename='elaborate.sh',
159
- command_lists=self.xelab_commands)
160
- util.write_shell_command_file(dirpath=self.args['work-dir'], filename='simulate.sh',
161
- command_lists=self.xsim_commands)
162
- util.write_shell_command_file(dirpath=self.args['work-dir'], filename='all.sh',
163
- command_lists = [
164
- ['./pre_compile_dep_shell_commands.sh'],
165
- ['./compile.sh'],
166
- ['./elaborate.sh'],
167
- ['./simulate.sh'],
168
- ])
169
-
170
- self.write_eda_config_and_args()
156
+ self.write_sh_scripts_to_work_dir(
157
+ compile_lists=self.xvlog_commands,
158
+ elaborate_lists=self.xelab_commands,
159
+ simulate_lists=self.xsim_commands
160
+ )
171
161
 
172
162
  def compile(self):
173
163
  if self.args['stop-before-compile']:
@@ -652,14 +642,15 @@ class CommandBuildVivado(CommandBuild, ToolVivado):
652
642
  self.write_eda_config_and_args()
653
643
 
654
644
  # create FLIST
655
- flist_file = os.path.join(self.args['work-dir'],'build.flist')
656
- util.debug(f"CommandBuildVivado: {self.args['top-path']=}")
645
+ flist_file = os.path.abspath(os.path.join(self.args['work-dir'],'build.flist'))
646
+ util.debug(f"CommandBuildVivado: top={self.args['top']} target={self.target}",
647
+ f"design={self.args['design']}")
657
648
 
658
649
  eda_path = eda_base.get_eda_exec('flist')
659
650
  command_list = [
660
651
  eda_path, 'flist',
652
+ '--no-default-log',
661
653
  '--tool=' + self.args['tool'],
662
- self.args['top-path'],
663
654
  '--force',
664
655
  '--out=' + flist_file,
665
656
  #'--no-emit-incdir',
@@ -677,6 +668,14 @@ class CommandBuildVivado(CommandBuild, ToolVivado):
677
668
  '--prefix-v=' + shlex.quote("add_files -norecurse "),
678
669
  '--prefix-vhd=' + shlex.quote("add_files -norecurse "),
679
670
  ]
671
+
672
+ # create an eda.flist_input.f that we'll pass to flist:
673
+ with open(os.path.join(self.args['work-dir'], 'eda.flist_input.f'),
674
+ 'w', encoding='utf-8') as f:
675
+ f.write('\n'.join(self.files_v + self.files_sv + self.files_vhd + ['']))
676
+
677
+ command_list.append('--input-file=eda.flist_input.f')
678
+
680
679
  for key,value in self.defines.items():
681
680
  if value is None:
682
681
  command_list += [ f"+define+{key}" ]
@@ -691,7 +690,10 @@ class CommandBuildVivado(CommandBuild, ToolVivado):
691
690
  util.write_shell_command_file(dirpath=self.args['work-dir'], filename='run_eda_flist.sh',
692
691
  command_lists=[command_list], line_breaks=True)
693
692
 
694
- self.exec(cwd, command_list, tee_fpath=command_list.tee_fpath)
693
+ ###self.exec(cwd, command_list, tee_fpath=command_list.tee_fpath)
694
+ # Run this from work-dir
695
+ self.exec(work_dir=self.args['work-dir'], command_list=command_list,
696
+ tee_fpath=command_list.tee_fpath)
695
697
 
696
698
  if self.args['job-name'] == "":
697
699
  self.args['job-name'] = self.args['design']
@@ -724,6 +726,11 @@ class CommandBuildVivado(CommandBuild, ToolVivado):
724
726
  util.write_shell_command_file(dirpath=self.args['work-dir'], filename='run_vivado.sh',
725
727
  command_lists=[command_list], line_breaks=True)
726
728
 
729
+ if self.args['stop-before-compile']:
730
+ util.info(f"--stop-before-compile set: scripts in : {self.args['work-dir']}")
731
+ return
732
+
733
+ # Run this from current working dir (not work-dir)
727
734
  self.exec(cwd, command_list, tee_fpath=command_list.tee_fpath)
728
735
  util.info(f"Build done, results are in: {self.args['work-dir']}")
729
736
 
opencos/util.py CHANGED
@@ -88,6 +88,7 @@ class ArtifactTypes(Enum):
88
88
  DOTF = 4
89
89
  TCL = 5
90
90
  SHELL = 6
91
+ BITSTREAM = 7
91
92
 
92
93
  class Artifacts:
93
94
  '''Class to hold file artifacts, for logs generated by EDA, or other artifcats created
@@ -365,6 +366,10 @@ def get_argparser() -> argparse.ArgumentParser:
365
366
  ' using $OC_ROOT/bin'))
366
367
  parser.add_argument('--artifacts-json', **bool_action_kwargs,
367
368
  help='Store a work-dir/artifacts.json file of known tool output files')
369
+ parser.add_argument('-f', '--input-file', default=[], action='append',
370
+ help=(
371
+ 'Input .f file to be expanded as eda'
372
+ ' args/defines/incdirs/files/targets'))
368
373
  return parser
369
374
 
370
375
 
@@ -409,34 +414,86 @@ def process_token(arg: list) -> bool:
409
414
  return False
410
415
 
411
416
 
412
- def process_tokens(tokens:list) -> (argparse.Namespace, list):
417
+ def read_tokens_from_dot_f(filepath: str) -> list:
418
+ '''Returns list of tokens from a .f file'''
419
+ debug(f"Opening -f / --input-file '{filepath}' for contents")
420
+ if not os.path.isfile(filepath):
421
+ error(f'-f (or --input-file): {filepath} does not exist',
422
+ error_code=status_constants.EDA_GENERAL_FILE_NOT_FOUND)
423
+ return []
424
+ tokens = []
425
+ with open(filepath, encoding='utf-8') as f:
426
+ for line in f:
427
+ tokens.extend(line.split())
428
+ return tokens
429
+
430
+ def process_debug_args(parsed: argparse.Namespace) -> None:
431
+ '''Sets global debug_level based on parsed args'''
432
+ global debug_level # pylint: disable=global-statement
433
+
434
+ if parsed.debug_level:
435
+ set_debug_level(parsed.debug_level)
436
+ elif parsed.debug:
437
+ set_debug_level(1)
438
+ elif parsed.debug is False:
439
+ # not None, explicitly set to False via --no-debug
440
+ debug_level = 0
441
+
442
+
443
+ def process_tokens(tokens: list) -> (argparse.Namespace, list):
413
444
  '''Processes tokens (unparsed args list) on util's ArgumentParser
414
445
 
415
446
  Returns tuple of (parsed Namespace, unparsed args list)
416
447
  '''
417
448
  global debug_level # pylint: disable=global-statement
449
+ debug_level = 0
418
450
 
419
- parser = get_argparser()
451
+ # Deal with --debug, --debug-level, and expand all parsed.input_file (list) tokens first,
452
+ # for now put dot-f file contents in front of of tokens, do this in a separate custom
453
+ # argparser.
454
+ bool_action_kwargs = get_argparse_bool_action_kwargs()
455
+ parser = argparse.ArgumentParser(
456
+ prog='opencos -f/--input-file', add_help=False, allow_abbrev=False
457
+ )
458
+ parser.add_argument('--debug', **bool_action_kwargs,
459
+ help='Display additional debug messaging level 1 or higher')
460
+ parser.add_argument('--debug-level', type=int, default=0,
461
+ help='Set debug level messaging (default: 0)')
462
+ parser.add_argument('-f', '--input-file', default=[], action='append',
463
+ help=(
464
+ 'Input .f file to be expanded as eda'
465
+ ' args/defines/incdirs/files/targets'))
420
466
  try:
421
467
  parsed, unparsed = parser.parse_known_args(tokens + [''])
468
+ tokens2 = list(filter(None, unparsed))
469
+ except argparse.ArgumentError:
470
+ error(f'util -f/--input-file, problem attempting to parse_known_args for: {tokens}')
471
+
472
+ process_debug_args(parsed=parsed)
473
+ debug(f'util.process_tokens: {parsed=} {unparsed=} from: {tokens}')
474
+
475
+ for filepath in parsed.input_file:
476
+ tokens2[0:0] = read_tokens_from_dot_f(filepath)
477
+
478
+ # Continue with all normal parsing beyond --debug and -f/--input-file,
479
+ # Note that we re-parse everything in case there was --debug or --debug-level in
480
+ # the .f file(s), or anything else that this argparser would pick up.
481
+ parser = get_argparser()
482
+ try:
483
+ parsed, unparsed = parser.parse_known_args(tokens2 + [''])
422
484
  unparsed = list(filter(None, unparsed))
423
485
  except argparse.ArgumentError:
424
- error(f'problem attempting to parse_known_args for {tokens=}')
486
+ error(f'util: problem attempting to parse_known_args for tokens={tokens2}')
425
487
 
426
- if parsed.debug_level:
427
- set_debug_level(parsed.debug_level)
428
- elif parsed.debug:
429
- set_debug_level(1)
430
- else:
431
- debug_level = 0
488
+ process_debug_args(parsed=parsed)
432
489
 
433
- debug(f'util.process_tokens: {parsed=} {unparsed=} from {tokens=}')
490
+ if parsed.input_file:
491
+ warning(f'Skipping nested -f/--input-file(s) {parsed.input_file}')
434
492
 
435
493
  # clear existing artifacts dicts (mostly for pytests repeatedly calling eda.main),
436
494
  # set artifacts.enabled based on args['artifacts-json']
437
495
  artifacts.reset(enable=parsed.artifacts_json)
438
496
 
439
-
440
497
  if parsed.force_logfile:
441
498
  start_log(parsed.force_logfile, force=True)
442
499
  elif parsed.logfile:
@@ -451,9 +508,9 @@ def process_tokens(tokens:list) -> (argparse.Namespace, list):
451
508
  start_log(global_log.default_log_filepath, force=True)
452
509
 
453
510
  parsed_as_dict = vars(parsed)
454
- for key,value in parsed_as_dict.items():
511
+ for key, value in parsed_as_dict.items():
455
512
  key = key.replace('_', '-')
456
- if value is not None:
513
+ if key in args and value is not None:
457
514
  args[key] = value # only update with non-None values to our global 'args' dict
458
515
 
459
516
  return parsed, unparsed
@@ -9,6 +9,7 @@ PYTHON_EXCEPTION = 1
9
9
 
10
10
  EDA_DEPS_FILE_NOT_FOUND = 10
11
11
  EDA_DEPS_TARGET_NOT_FOUND = 11
12
+ EDA_GENERAL_FILE_NOT_FOUND = 12
12
13
 
13
14
  EDA_COMMAND_OR_ARGS_ERROR = 20
14
15
  EDA_CONFIG_ERROR = 21
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opencos-eda
3
- Version: 0.2.53
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
@@ -3,7 +3,7 @@ opencos/_version.py,sha256=XiHFZjCofkkZvI9befTFKsRt5zLouUo1CIwhW4srWU0,582
3
3
  opencos/_waves_pkg.sv,sha256=1lbhQOVGc3t_R8czYjP40hssP0I3FlZOpHTkI7yKFbI,1251
4
4
  opencos/deps_schema.py,sha256=5QLN2OQdhbfxHqbqt4Ty-Saskh-z_h9m9qfWqB8kZ9U,15691
5
5
  opencos/eda.py,sha256=kz4jSYBANXdbNGH3DmE9v_jU2p_NkI2tT6aBslcYtcQ,22248
6
- opencos/eda_base.py,sha256=rMXFTw8F38OsM_p662o5NyIcWf7LRfRhGXLaJ-gesNU,101696
6
+ opencos/eda_base.py,sha256=DX0RHiJq84T_4LpcC7zQD5cCuDHfLrWzk7lkXBWfeP8,101892
7
7
  opencos/eda_config.py,sha256=XgO2YKUWSL7TAFo-V4h4xqNO3Z1Ug4JI-W8LvzD-kGQ,11407
8
8
  opencos/eda_config_defaults.yml,sha256=-2ISGkktUo-O5hzju_KxNGr9oyRL9iYQ4OKRzImgCsQ,15284
9
9
  opencos/eda_config_max_verilator_waivers.yml,sha256=lTAU4IOEbUWVlPzuer1YYhIyxpPINeA4EJqcRIT-Ymk,840
@@ -18,19 +18,19 @@ opencos/files.py,sha256=aoq0O2KfISzZb-Vi_q_0TTGBER9xJc--FkVZf0ga7pA,1549
18
18
  opencos/names.py,sha256=iC37PV7Pz0PicTDg09vbQ9NXAj-5m6RKrWHkkcHB8As,1145
19
19
  opencos/peakrdl_cleanup.py,sha256=vHNGtalTrIVP335PhRjPt9RhoccgpK1HJAi-E4M8Kc8,736
20
20
  opencos/seed.py,sha256=IL9Yg-r9SLSRseMVWaEHmuw2_DNi_eyut11EafoNTsU,942
21
- opencos/util.py,sha256=DoJ-uwaP4gEabZW6mfEkBYtlCTNih0CynpLOUib-kgw,34845
21
+ opencos/util.py,sha256=03b2JP80NDXksNTwShMRamnTVb1C2gUfrPYBDL40pHA,37565
22
22
  opencos/commands/__init__.py,sha256=TtfbQgmdSTGDZzTrl1ASx7pxY3jaXyK6aTtOng0x-O8,1076
23
23
  opencos/commands/build.py,sha256=hvjrvg7AbEotuQze6-yz3DOYRMtagkvJ-6TFNJQTwrs,1441
24
24
  opencos/commands/deps_help.py,sha256=WDrU7H9sypzDAxe_CHqhW5B_scbQMzBEdf-v-Jcfd5Q,10682
25
25
  opencos/commands/elab.py,sha256=m6Gk03wSzX8UkcmReooK7turF7LpqO0IcdOZwJ8XiyI,1596
26
26
  opencos/commands/export.py,sha256=dpTcrtPjIt6TOw-i8LUWhb4ismFAE1QK-dNAHC1jxME,3510
27
- opencos/commands/flist.py,sha256=5m-sqs-YOmLMPsOiIOTixyPuCzeOy4JHhFJ20c_8ixM,8632
27
+ opencos/commands/flist.py,sha256=x3VVarCVlz2kFJI5rQ8UsZzzas32j4zQKgzXGIozKwE,8638
28
28
  opencos/commands/lec.py,sha256=bshOs_GkuB1nCGd_SntT43_XpSYQYJqNCjVZp6Q1Chc,3879
29
29
  opencos/commands/multi.py,sha256=dCo4rMIkGT3BtlBhUIAd7r31w8qxeJvybpl4H7DR77o,27225
30
30
  opencos/commands/open.py,sha256=XckvKUNwvc5KHbYGV-eQ2i0WG4X-yckroDaMC610MB4,804
31
31
  opencos/commands/proj.py,sha256=vCsZle3oUJ8xmIFuepgAD6G-YGl35xtTIcTeiVDshNo,1112
32
32
  opencos/commands/shell.py,sha256=dFXXtvsDs3Khme41du8LhKdV3qRosxjTfju6SJbOSKM,7599
33
- opencos/commands/sim.py,sha256=CYeAHOq2cTFPEvKdzNGefCBH2bWYAPa-Epv6YLzi4yY,16076
33
+ opencos/commands/sim.py,sha256=0FV7ODiHFyJJjVBEb3WuTKNubxB0DYGNqpZqnLP_-Hw,18038
34
34
  opencos/commands/sweep.py,sha256=ni4XFgnFF8HLXtwPhETyLWfvc2kgtm4bcxFcKzUhkf0,9343
35
35
  opencos/commands/synth.py,sha256=tuxWmxMNmE9hveWXGNfKDelzxi_wK7ZL7V2LiZV6Ypg,4371
36
36
  opencos/commands/targets.py,sha256=_jRNhm2Fqj0fmMvTw6Ba39DCsRHf_r_uZCy_R064kpA,1472
@@ -50,7 +50,7 @@ opencos/tests/helpers.py,sha256=HdsARZK0KsGou2SRV30fBALV674bsST37ldpT-gI6q8,9512
50
50
  opencos/tests/test_build.py,sha256=FQAxOpLVQShAHD_L5rqJctPeSAoqoOCNFI0RXflLuY0,387
51
51
  opencos/tests/test_deps_helpers.py,sha256=f9GJXvzcdE3SGkKJ7q-YBTgRagZcIzeRa6nMVCCiEvI,7848
52
52
  opencos/tests/test_deps_schema.py,sha256=T3P9KjaMyKsk8b7snNVvNSsom2hIJcg6Z9apYiXoH9Y,941
53
- opencos/tests/test_eda.py,sha256=YOnDHWeI3LY35_g1IDpHScIBw2IsNyZNalcEy087Ew0,39469
53
+ opencos/tests/test_eda.py,sha256=cdxfLCUZq0nNelCQiplZXkeF4eyzmyJlZJFDSo77qeI,39464
54
54
  opencos/tests/test_eda_elab.py,sha256=VyYiaLLyfJi26FkoN9p_Kb9cMHfY-0u_0Mx1iVpsg-I,2657
55
55
  opencos/tests/test_eda_synth.py,sha256=LOM8CKpNyjka_sKS2c00YObOAQeVgpRmuM12Bn-PHqU,5234
56
56
  opencos/tests/test_oc_cli.py,sha256=w-F-LjSSWVql3D2WG8tcV4_C52i-hL_2WT3oDpKQn9s,734
@@ -63,34 +63,34 @@ opencos/tests/deps_files/non_sv_reqs/DEPS.yml,sha256=VZkahO1AKhD9GUV5lK8VwUONEi5
63
63
  opencos/tests/deps_files/tags_with_tools/DEPS.yml,sha256=-5U1qfJElgpVhmkLEu3lYuvDYva8kDlt6JOdB9jidmc,1377
64
64
  opencos/tests/deps_files/test_err_fatal/DEPS.yml,sha256=GnXIUJvshQWR9PlYxX67T53ejf5KhDbtD8sUJB4Rwd0,95
65
65
  opencos/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
- opencos/tools/cocotb.py,sha256=RaIIdRWYnwEX23Xvzbzk2ffFSPlxfJglg53t63XdAuM,16986
66
+ opencos/tools/cocotb.py,sha256=vcp9wLlmgr6dLBnxEuJJyMjJIorIo96J0Z63tJwP-eE,16759
67
67
  opencos/tools/invio.py,sha256=q9E9n6xsozDfar-1rLvJEZbCpPb_bQEy6WKEI3KS3dk,3163
68
68
  opencos/tools/invio_helpers.py,sha256=1au4CYmV5aC7DHjaZBNemydH6Eq0i-Yt5L3HyKfQOfY,7638
69
69
  opencos/tools/invio_yosys.py,sha256=asSjbdPjBXB76KxNZIhoDRn2DoXKsZEQ1YDX_WBzKiA,6019
70
- opencos/tools/iverilog.py,sha256=KQV5tiRdM0ZuJOO0q3ZeUmhRyEc-oJggOc6RKIjoH84,6482
71
- opencos/tools/modelsim_ase.py,sha256=WgrX4orOoY5hAqhrlP6Qu2C44Zaw3Vpf7skctOM5WJ0,14952
72
- opencos/tools/quartus.py,sha256=LlG2X-IhX1SFJUAILx1z1gw2JYyp9vvVcJ5ny8iba-o,25345
73
- opencos/tools/questa.py,sha256=lg8EbPBQ26_blXZA5Utrp2wAaL13S6iSQgziWW5ssGE,10242
70
+ opencos/tools/iverilog.py,sha256=tnwhOT_WjnUKf4ioei-xmclM2xDTRnN0DrkxIKwsfnc,5926
71
+ opencos/tools/modelsim_ase.py,sha256=auBTdgBhbU2n92L0ezLUpppyE5z86Ci2-0hgDL_oNoc,14885
72
+ opencos/tools/quartus.py,sha256=Iu4zw34OCKlERMyJ9GRwaAuRDeBHG_ApvJATvyII-68,27516
73
+ opencos/tools/questa.py,sha256=5dr1LF7m5P1NmOPXU0hzMO0o0_RrXLDvc1gmhlwyEyU,9446
74
74
  opencos/tools/questa_fse.py,sha256=lqhW49YpbzhkOGWG-0EjITj-RMyy8IgWYoaW9UtjxK8,2194
75
75
  opencos/tools/riviera.py,sha256=D78anIJ_GnQ4aRwbWfR2QUslTgF38qiZod7v-EHLHg0,10716
76
76
  opencos/tools/slang.py,sha256=mFw58vhnCTRR9yaQ2zHPlNB5HKSf3Y078XcaVnpLaAc,7798
77
77
  opencos/tools/slang_yosys.py,sha256=3fyLRRdTXhSppNtUhhUl00oG-cT9TyyPTH6JvasS9ZE,9804
78
78
  opencos/tools/surelog.py,sha256=dtj3ApAKoQasnGdg42n9DPgeqoJ5nCuurIkIO3G5ZCY,5011
79
79
  opencos/tools/tabbycad_yosys.py,sha256=2LePPgYXBVdsy7YcffPIWN-I0B7queLQ_f_pme2SCGw,7803
80
- opencos/tools/verilator.py,sha256=dIhrvLH9hHiTV_DWQbMNlAjolKctCbBMO9u9V7yAHuE,21400
81
- opencos/tools/vivado.py,sha256=2j5fjr5Yh-rcgrJ1pNWL-5EOondLT1R8jFXLW05bXnI,40573
80
+ opencos/tools/verilator.py,sha256=ACmRXJyE8ZGlu7gGHdgEyk8A5gQeMFSR1pBd8zw9eQc,20767
81
+ opencos/tools/vivado.py,sha256=TEMIYSVCdEASu2fixFuKIwDbb3r_25Ns-8YyUVEz-eg,40611
82
82
  opencos/tools/yosys.py,sha256=UKWzvc2rSi3J9U2TROqRbmePdBmjskap664giumeRBk,26323
83
83
  opencos/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
84
84
  opencos/utils/markup_helpers.py,sha256=A8Ev5UJ4EVKjdcF2g85SQbjdPZR4jGpNqCLaBy_4v7Q,4569
85
- opencos/utils/status_constants.py,sha256=aQui30ohPCEaWNDh2iujJQ_KQa3plry_rk7uDzS3vWk,603
85
+ opencos/utils/status_constants.py,sha256=na6YsqlsCwIYzTXWE14dPadUYRNTrOS6YTXHCer2NbA,635
86
86
  opencos/utils/str_helpers.py,sha256=1VUBL9Q09eBDpTvLarhaQoJOLoi3IKOaFy2FHvKevEU,6270
87
87
  opencos/utils/subprocess_helpers.py,sha256=xemAGPey6M0sWY_FElvr-Z0phCfdjaC-znP8FKihPaE,3535
88
88
  opencos/utils/vscode_helper.py,sha256=2YPjcDH_vTlwJvcITyMfvx8dLzPSRKzAvFRJz7BaJk8,1332
89
89
  opencos/utils/vsim_helper.py,sha256=2voGRZI2iAQ2Pv2ZI5g2why6xpgig-To8im-LVXtuDU,1517
90
- opencos_eda-0.2.53.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
91
- opencos_eda-0.2.53.dist-info/licenses/LICENSE.spdx,sha256=8gn1610RMP6eFgT3Hm6q9VKXt0RvdTItL_oxMo72jII,189
92
- opencos_eda-0.2.53.dist-info/METADATA,sha256=Wrx0Wm6g3tWcbObzOWBv1j3pXTiHudFZslOxmnSQuQM,635
93
- opencos_eda-0.2.53.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
94
- opencos_eda-0.2.53.dist-info/entry_points.txt,sha256=6n1T5NwVYDhN5l1h5zmyT197G4pE0SySDreB0QJzJR0,218
95
- opencos_eda-0.2.53.dist-info/top_level.txt,sha256=J4JDP-LpRyJqPNeh9bSjx6yrLz2Mk0h6un6YLmtqql4,8
96
- opencos_eda-0.2.53.dist-info/RECORD,,
90
+ opencos_eda-0.2.54.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
91
+ opencos_eda-0.2.54.dist-info/licenses/LICENSE.spdx,sha256=8gn1610RMP6eFgT3Hm6q9VKXt0RvdTItL_oxMo72jII,189
92
+ opencos_eda-0.2.54.dist-info/METADATA,sha256=Gn37sKvN_THH6F5LkbyNTe0b1RSgTtQIYy9oCUyodyg,635
93
+ opencos_eda-0.2.54.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
94
+ opencos_eda-0.2.54.dist-info/entry_points.txt,sha256=6n1T5NwVYDhN5l1h5zmyT197G4pE0SySDreB0QJzJR0,218
95
+ opencos_eda-0.2.54.dist-info/top_level.txt,sha256=J4JDP-LpRyJqPNeh9bSjx6yrLz2Mk0h6un6YLmtqql4,8
96
+ opencos_eda-0.2.54.dist-info/RECORD,,