opencos-eda 0.2.38__tar.gz → 0.2.39__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. {opencos_eda-0.2.38/opencos_eda.egg-info → opencos_eda-0.2.39}/PKG-INFO +1 -1
  2. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/commands/multi.py +7 -3
  3. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/commands/sweep.py +12 -4
  4. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/eda_base.py +103 -16
  5. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tools/iverilog.py +4 -2
  6. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tools/modelsim_ase.py +4 -3
  7. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tools/verilator.py +10 -8
  8. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tools/vivado.py +0 -1
  9. {opencos_eda-0.2.38 → opencos_eda-0.2.39/opencos_eda.egg-info}/PKG-INFO +1 -1
  10. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/pyproject.toml +1 -1
  11. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/LICENSE +0 -0
  12. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/LICENSE.spdx +0 -0
  13. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/README.md +0 -0
  14. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/__init__.py +0 -0
  15. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/_version.py +0 -0
  16. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/_waves_pkg.sv +0 -0
  17. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/commands/__init__.py +0 -0
  18. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/commands/build.py +0 -0
  19. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/commands/elab.py +0 -0
  20. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/commands/export.py +0 -0
  21. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/commands/flist.py +0 -0
  22. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/commands/open.py +0 -0
  23. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/commands/proj.py +0 -0
  24. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/commands/sim.py +0 -0
  25. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/commands/synth.py +0 -0
  26. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/commands/targets.py +0 -0
  27. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/commands/upload.py +0 -0
  28. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/commands/waves.py +0 -0
  29. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/deps_helpers.py +0 -0
  30. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/deps_schema.py +0 -0
  31. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/eda.py +0 -0
  32. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/eda_config.py +0 -0
  33. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/eda_config_defaults.yml +0 -0
  34. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/eda_config_max_verilator_waivers.yml +0 -0
  35. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/eda_config_reduced.yml +0 -0
  36. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/eda_deps_bash_completion.bash +0 -0
  37. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/eda_extract_targets.py +0 -0
  38. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/eda_tool_helper.py +0 -0
  39. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/export_helper.py +0 -0
  40. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/export_json_convert.py +0 -0
  41. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/files.py +0 -0
  42. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/names.py +0 -0
  43. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/oc_cli.py +0 -0
  44. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/pcie.py +0 -0
  45. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/peakrdl_cleanup.py +0 -0
  46. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/seed.py +0 -0
  47. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/__init__.py +0 -0
  48. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/custom_config.yml +0 -0
  49. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/deps_files/command_order/DEPS.yml +0 -0
  50. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/deps_files/error_msgs/DEPS.yml +0 -0
  51. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/deps_files/iverilog_test/DEPS.yml +0 -0
  52. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/deps_files/no_deps_here/DEPS.yml +0 -0
  53. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/deps_files/non_sv_reqs/DEPS.yml +0 -0
  54. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/deps_files/tags_with_tools/DEPS.yml +0 -0
  55. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/deps_files/test_err_fatal/DEPS.yml +0 -0
  56. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/helpers.py +0 -0
  57. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/test_build.py +0 -0
  58. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/test_deps_helpers.py +0 -0
  59. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/test_deps_schema.py +0 -0
  60. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/test_eda.py +0 -0
  61. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/test_eda_elab.py +0 -0
  62. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/test_eda_synth.py +0 -0
  63. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/test_oc_cli.py +0 -0
  64. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tests/test_tools.py +0 -0
  65. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tools/__init__.py +0 -0
  66. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tools/invio.py +0 -0
  67. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tools/invio_helpers.py +0 -0
  68. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tools/invio_yosys.py +0 -0
  69. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tools/questa.py +0 -0
  70. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tools/slang.py +0 -0
  71. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tools/slang_yosys.py +0 -0
  72. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tools/surelog.py +0 -0
  73. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tools/tabbycad_yosys.py +0 -0
  74. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/tools/yosys.py +0 -0
  75. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos/util.py +0 -0
  76. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos_eda.egg-info/SOURCES.txt +0 -0
  77. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos_eda.egg-info/dependency_links.txt +0 -0
  78. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos_eda.egg-info/entry_points.txt +0 -0
  79. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos_eda.egg-info/requires.txt +0 -0
  80. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/opencos_eda.egg-info/top_level.txt +0 -0
  81. {opencos_eda-0.2.38 → opencos_eda-0.2.39}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opencos-eda
3
- Version: 0.2.38
3
+ Version: 0.2.39
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
@@ -392,7 +392,9 @@ class CommandMulti(CommandParallel):
392
392
  # Special case for 'multi' --export-jsonl, run reach child with --export-json
393
393
  command_list.append('--export-json')
394
394
  if tool and len(all_multi_tools) > 1:
395
- command_list.append(f'--sub-work-dir={short_target}.{command}.{tool}')
395
+ command_list.append(f'--job-name={short_target}.{command}.{tool}')
396
+ else:
397
+ command_list.append(f'--job-name={short_target}.{command}')
396
398
 
397
399
  def append_jobs_from_targets(self, args:list):
398
400
  '''Helper method in CommandMulti to apply 'args' (list) to all self.targets,
@@ -430,13 +432,15 @@ class CommandMulti(CommandParallel):
430
432
  type(self.args['single-timeout']) in [int, str]:
431
433
  command_list = ['timeout', str(self.args['single-timeout'])] + command_list
432
434
 
433
- name = target
435
+ name = self.get_name_from_target(target)
434
436
  if tool and (len(all_multi_tools) > 1 or self.command_name == 'tools-multi'):
435
- name = f'{short_target} ({tool})'
437
+ name += f' ({tool})'
436
438
 
437
439
  this_job_dict = {
438
440
  'name' : name,
439
441
  'index' : len(self.jobs),
442
+ 'command': command,
443
+ 'target': target,
440
444
  'command_list' : command_list
441
445
  }
442
446
  if tool:
@@ -113,6 +113,9 @@ class CommandSweep(CommandDesign, CommandParallel):
113
113
  util.debug(f"Sweep: arg_tokens: '{arg_tokens}'")
114
114
  util.debug(f"Sweep: target: '{self.sweep_target}'")
115
115
 
116
+ if not self.sweep_target:
117
+ self.error(f"Sweep can only take one target, found none, args: {unparsed}")
118
+
116
119
  # now create the list of jobs, support one axis
117
120
  self.jobs = []
118
121
 
@@ -197,15 +200,20 @@ class CommandSweep(CommandDesign, CommandParallel):
197
200
  f"target={self.sweep_target}, arg_tokens={arg_tokens},",
198
201
  f"sweep_axis_list={sweep_axis_list}")
199
202
  if not sweep_axis_list:
200
- # we aren't sweeping anything, create one job
201
- snapshot_name = self.sweep_target.replace('../','').replace('/','_') + sweep_string
203
+ # we aren't sweeping anything, create one job:
204
+ # name {target}.{command}[.sweep_value,.sweep_value,...]
205
+ snapshot_name = self.get_name_from_target(self.sweep_target)
206
+ snapshot_name = snapshot_name.replace(os.sep, '_') \
207
+ + f'.{self.single_command}{sweep_string}'
202
208
  eda_path = get_eda_exec('sweep')
203
209
  self.jobs.append({
204
210
  'name' : snapshot_name,
205
211
  'index' : len(self.jobs),
212
+ 'command': self.single_command,
213
+ 'target': self.sweep_target,
206
214
  'command_list' : (
207
215
  [eda_path, self.single_command, self.sweep_target,
208
- '--job_name', snapshot_name] + arg_tokens
216
+ f'--job-name={snapshot_name}'] + arg_tokens
209
217
  )
210
218
  })
211
219
  return
@@ -221,7 +229,7 @@ class CommandSweep(CommandDesign, CommandParallel):
221
229
  this_arg_tokens.append(f'{lhs}{operator}{v}')
222
230
 
223
231
  v_string = f"{v}".replace('.','p')
224
- this_sweep_string = sweep_string + f"_{lhs_trimmed}_{v_string}"
232
+ this_sweep_string = sweep_string + f".{lhs_trimmed}_{v_string}"
225
233
 
226
234
  self.expand_sweep_axis(
227
235
  arg_tokens=this_arg_tokens,
@@ -11,6 +11,7 @@ import signal
11
11
  import sys
12
12
  import threading
13
13
  import time
14
+ from pathlib import Path
14
15
 
15
16
  import opencos
16
17
  from opencos import seed, deps_helpers, util, files
@@ -184,20 +185,24 @@ class Command:
184
185
  'export-json': False, # generates an export.json suitable for a testrunner, if possible for self.command.
185
186
  'enable-tags': [],
186
187
  'disable-tags': [],
188
+ 'test-mode': False,
187
189
  })
188
190
  self.args_help.update({
189
- 'stop-before-compile': 'stop this run before any compile (if possible for tool) and' \
190
- + ' save .sh scripts in eda-dir/',
191
+ 'stop-before-compile': ('stop this run before any compile (if possible for tool) and'
192
+ ' save .sh scripts in eda-dir/'),
191
193
  'eda-dir': 'relative directory where eda logs are saved',
192
194
  'export': 'export results for these targets in eda-dir',
193
195
  'export-run': 'export, and run, results for these targets in eda-dir',
194
196
  'export-json': 'export, and save a JSON file per target',
195
- 'work-dir': 'Optional override for working directory, often defaults to ./eda.work/<top>.<command>',
196
- 'enable-tags': 'DEPS markup tag names to be force enabled for this' \
197
- + ' command (mulitple appends to list).',
198
- 'diable-tags': 'DEPS markup tag names to be disabled (even if they' \
199
- + ' match the criteria) for this command (mulitple appends to list).' \
200
- + ' --disable-tags has higher precedence than --enable-tags.'
197
+ 'work-dir': ('Optional override for working directory, often defaults to'
198
+ ' ./eda.work/<top>.<command>'),
199
+ 'enable-tags': ('DEPS markup tag names to be force enabled for this'
200
+ ' command (mulitple appends to list).'),
201
+ 'diable-tags': ('DEPS markup tag names to be disabled (even if they'
202
+ ' match the criteria) for this command (mulitple appends to list).'
203
+ ' --disable-tags has higher precedence than --enable-tags.'),
204
+ 'test-mode': ('command and tool dependent, usually stops the command early without'
205
+ ' executing.'),
201
206
  })
202
207
  self.modified_args = {}
203
208
  self.config = copy.deepcopy(config) # avoid external modifications.
@@ -223,8 +228,8 @@ class Command:
223
228
 
224
229
  def create_work_dir(self):
225
230
  util.debug(f"create_work_dir: {self.args['eda-dir']=} {self.args['work-dir']=}")
226
- if (not os.path.exists(self.args['eda-dir'])): # use os.path.isfile / isdir also
227
- os.mkdir(self.args['eda-dir'])
231
+ if not os.path.exists(self.args['eda-dir']):
232
+ util.safe_mkdir(self.args['eda-dir'])
228
233
  util.info(f"create_work_dir: created {self.args['eda-dir']}")
229
234
  if self.args['design'] == "":
230
235
  if ('top' in self.args) and (self.args['top'] != ""):
@@ -250,14 +255,35 @@ class Command:
250
255
  if (os.path.exists(self.args['work-dir'])):
251
256
  if os.path.exists(keep_file) and not self.args['force']:
252
257
  self.error(f"Cannot remove old work dir due to '{keep_file}'")
253
- util.info(f"Removing previous '{self.args['work-dir']}'")
254
- shutil.rmtree(self.args['work-dir'])
255
- os.mkdir(self.args['work-dir'])
256
- util.debug(f'create_work_dir: created {self.args["work-dir"]}')
258
+ elif os.path.abspath(self.args['work-dir']) in os.getcwd():
259
+ # This effectively checks if
260
+ # --work-dir=.
261
+ # --work-dir=$PWD
262
+ # --work-dir=/some/path/almost/here
263
+ # Allow it, but preserve the existing directory, we don't want to blow away
264
+ # files up-heir from us.
265
+ # Enables support for --work-dir=.
266
+ util.info(f"Not removing existing work-dir: '{self.args['work-dir']}' is within {os.getcwd()=}")
267
+ elif str(Path(self.args['work-dir'])).startswith(str(Path('/'))):
268
+ # Do not allow other absolute path work dirs if it already exists.
269
+ # This prevents you from --work-dir=~ and eda wipes out your home dir.
270
+ self.error(f'Cannot use work-dir={self.args["work-dir"]} starting with absolute path "/"')
271
+ elif str(Path('..')) in str(Path(self.args['work-dir'])):
272
+ # Do not allow other ../ work dirs if it already exists.
273
+ self.error(f'Cannot use work-dir={self.args["work-dir"]} with up-hierarchy ../ paths')
274
+ else:
275
+ # If we made it this far, on a directory that exists, that appears safe
276
+ # to delete and re-create:
277
+ util.info(f"Removing previous '{self.args['work-dir']}'")
278
+ shutil.rmtree(self.args['work-dir'])
279
+ util.safe_mkdir(self.args['work-dir'])
280
+ util.debug(f'create_work_dir: created {self.args["work-dir"]}')
281
+ else:
282
+ util.safe_mkdir(self.args['work-dir'])
283
+ util.debug(f'create_work_dir: created {self.args["work-dir"]}')
257
284
  if (self.args['keep']):
258
285
  open(keep_file, 'w').close()
259
- util.debug(f'create_work_dir: created {keep_file}')
260
- util.info(f'create_work_dir: created {self.args["work-dir"]}')
286
+ util.debug(f'create_work_dir: created {keep_file=}')
261
287
  return self.args['work-dir']
262
288
 
263
289
  def exec(self, work_dir, command_list, background=False, stop_on_error=True,
@@ -1361,6 +1387,8 @@ class CommandParallel(Command):
1361
1387
  fancy_mode = util.args['fancy'] and (num_parallel > 1) and (num_parallel <= (lines-6))
1362
1388
  multi_cwd = util.getcwd() + os.sep
1363
1389
 
1390
+ self.patch_jobs_for_duplicate_target_names()
1391
+
1364
1392
  if run_parallel:
1365
1393
  # we are doing this multi-threaded
1366
1394
  util.info(f"Parallel: Running multi-threaded, starting {num_parallel} workers")
@@ -1519,6 +1547,10 @@ class CommandParallel(Command):
1519
1547
  self.status = 0 if len(self.jobs_status) == 0 else max(self.jobs_status)
1520
1548
  util.fancy_stop()
1521
1549
 
1550
+ @staticmethod
1551
+ def get_name_from_target(target: str) -> str:
1552
+ return target.replace('../', '').lstrip('./')
1553
+
1522
1554
 
1523
1555
  def update_args_list(self, args: list, tool: str) -> None:
1524
1556
  '''Modfies list args, using allow-listed known top-level args:
@@ -1572,3 +1604,58 @@ class CommandParallel(Command):
1572
1604
  # Remove unparsed args starting with '+', since those are commonly sent downstream to
1573
1605
  # single job (example, CommandSim plusargs).
1574
1606
  return [x for x in single_cmd_unparsed if not x.startswith('+')]
1607
+
1608
+
1609
+ def patch_jobs_for_duplicate_target_names(self) -> None:
1610
+ '''Examines list self.jobs, and if leaf target names are duplicate will
1611
+ patch each command's job-name to:
1612
+ --job-name=path.leaf.command[.tool]
1613
+ '''
1614
+
1615
+ def get_job_name(job_dict: dict) -> str:
1616
+ '''Fishes the job-name out of an entry in self.jobs'''
1617
+ for i, item in enumerate(job_dict['command_list']):
1618
+ if item.startswith('--job-name='):
1619
+ _, name = item.split('--job-name=')
1620
+ return name
1621
+ elif item == '--job-name':
1622
+ return job_dict['command_list'][i + 1]
1623
+ return ''
1624
+
1625
+ def replace_job_name(job_dict: dict, new_job_name: str) -> dict:
1626
+ '''Replaces the job-name in an entry in self.jobs'''
1627
+ for i, item in enumerate(job_dict['command_list']):
1628
+ if item.startswith('--job-name='):
1629
+ job_dict['command_list'][i] = '--job-name=' + new_job_name
1630
+ return job_dict
1631
+ elif item == '--job-name':
1632
+ job_dict['command_list'][i + 1] = new_job_name
1633
+ return job_dict
1634
+ return job_dict
1635
+
1636
+
1637
+ job_names_count_dict = {}
1638
+ for job_dict in self.jobs:
1639
+
1640
+ key = get_job_name(job_dict)
1641
+ if not key:
1642
+ self.error(f'{job_dict=} needs to have a --job-name= arg attached')
1643
+ if key not in job_names_count_dict:
1644
+ job_names_count_dict[key] = 1
1645
+ else:
1646
+ job_names_count_dict[key] += 1
1647
+
1648
+ for i, job_dict in enumerate(self.jobs):
1649
+ key = get_job_name(job_dict)
1650
+ if job_names_count_dict[key] < 2:
1651
+ continue
1652
+
1653
+ tpath, _ = os.path.split(job_dict['target'])
1654
+
1655
+ # prepend path information to job-name:
1656
+ patched_sub_work_dir = False
1657
+ patched_target_path = os.path.relpath(tpath).replace(os.sep, '_')
1658
+ new_job_name = f'{patched_target_path}.{key}'
1659
+ new_job_dict = replace_job_name(job_dict, new_job_name)
1660
+ self.jobs[i] = new_job_dict
1661
+ util.debug(f'Patched job {job_dict["name"]}: --job-name={new_job_name}')
@@ -156,8 +156,10 @@ class CommandSimIverilog(CommandSim, ToolIverilog):
156
156
  # +define+{k}={v}, but also for SystemVerilog plusargs
157
157
  command_list += [ '-D', f'{k}={sanitize_defines_for_sh(v)}' ]
158
158
 
159
- assert len(self.files_sv) + len(self.files_v) > 0, \
160
- f'{self.target=} {self.files_sv=} and {self.files_v=} are empty, cannot call iverilog'
159
+ if not self.files_sv and not self.files_v:
160
+ if not self.args['stop-before-compile']:
161
+ self.error(f'{self.target=} {self.files_sv=} and {self.files_v=} are empty,',
162
+ 'cannot call iverilog')
161
163
 
162
164
  command_list += list(self.files_sv) + list(self.files_v)
163
165
 
@@ -178,9 +178,10 @@ class CommandSimModelsimAse(CommandSim, ToolModelsimAse):
178
178
  '-source',
179
179
  ] + list(self.files_sv) + list(self.files_v)
180
180
 
181
- if len(self.files_sv) + len(self.files_v) == 0:
182
- self.error(f'{self.target=} {self.files_sv=} and {self.files_v=} are empty,',
183
- 'cannot create a valid vlog.f')
181
+ if not self.files_sv and not self.files_v:
182
+ if not self.args['stop-before-compile']:
183
+ self.error(f'{self.target=} {self.files_sv=} and {self.files_v=} are empty,',
184
+ 'cannot create a valid vlog.f')
184
185
 
185
186
  with open(vlog_dot_f_fpath, 'w', encoding='utf-8') as f:
186
187
  f.writelines(line + "\n" for line in vlog_dot_f_lines)
@@ -82,11 +82,12 @@ class VerilatorSim(CommandSim, ToolVerilator):
82
82
  })
83
83
 
84
84
  self.args_help.update({
85
- 'waves': 'Include waveforms, if possible for Verilator by applying' \
86
- + ' simulation runtime arg +trace. User will need SV code to interpret the plusarg' \
87
- + ' and apply $dumpfile("dump.fst").',
88
- 'dump-vcd': 'If using --waves, apply simulation runtime arg +trace=vcd. User' \
89
- + ' will need SV code to interpret the plusarg and apply $dumpfile("dump.vcd").',
85
+ 'waves': ('Include waveforms, if possible for Verilator by applying'
86
+ ' simulation runtime arg +trace. User will need SV code to interpret the'
87
+ 'plusarg and apply $dumpfile("dump.fst").'),
88
+ 'dump-vcd': ('If using --waves, apply simulation runtime arg +trace=vcd. User'
89
+ ' will need SV code to interpret the plusarg and apply'
90
+ ' $dumpfile("dump.vcd").'),
90
91
  'lint-only': 'Run verilator with --lint-only, instead of --binary',
91
92
  'gui': 'Not supported for Verilator',
92
93
  'cc-mode': 'Run verilator with --cc, requires a sim_main.cpp or similar sources',
@@ -227,9 +228,10 @@ class VerilatorSim(CommandSim, ToolVerilator):
227
228
  # +define+{k}={v}, but also for SystemVerilog plusargs
228
229
  verilate_command_list += [ f'+define+{k}={sanitize_defines_for_sh(v)}' ]
229
230
 
230
- if (len(self.files_sv) + len(self.files_v)) == 0:
231
- self.error(f'{self.target=} {self.files_sv=} and {self.files_v=} are empty,',
232
- 'cannot call verilator')
231
+ if not self.files_sv and not self.files_v:
232
+ if not self.args['stop-before-compile']:
233
+ self.error(f'{self.target=} {self.files_sv=} and {self.files_v=} are empty,',
234
+ 'cannot call verilator')
233
235
 
234
236
  verilate_command_list += list(self.files_sv) + list(self.files_v)
235
237
 
@@ -720,7 +720,6 @@ class CommandUploadVivado(CommandUpload, ToolVivado):
720
720
  'host': "localhost",
721
721
  'port': 3121,
722
722
  'tcl-file': "upload.tcl",
723
- 'test-mode': False,
724
723
  })
725
724
  # TODO(drew): Add self.args_help.update({...})
726
725
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opencos-eda
3
- Version: 0.2.38
3
+ Version: 0.2.39
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
@@ -2,7 +2,7 @@
2
2
 
3
3
  [project]
4
4
  name = "opencos-eda"
5
- version = "0.2.38"
5
+ version = "0.2.39"
6
6
  dependencies = [
7
7
  # opencos/eda.py dependencies
8
8
  "mergedeep >= 1.3.4",
File without changes
File without changes
File without changes
File without changes