opencos-eda 0.2.38__py3-none-any.whl → 0.2.40__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/multi.py CHANGED
@@ -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:
opencos/commands/sweep.py CHANGED
@@ -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,
opencos/eda_base.py CHANGED
@@ -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
@@ -177,6 +178,7 @@ class Command:
177
178
  "job-name" : "", # this is used to create a certain dir under "eda_dir"
178
179
  "work-dir" : "", # this can be used to run the job in a certain dir, else it will be <eda-dir>/<job-name> else <eda-dir>/<target>_<command>
179
180
  "sub-work-dir" : "", # this can be used to name the dir built under <eda-dir>, which seems to be same function as job-name??
181
+ "work-dir-use-target-dir": False,
180
182
  "suffix" : "",
181
183
  "design" : "", # not sure how this relates to top
182
184
  'export': False,
@@ -184,24 +186,31 @@ class Command:
184
186
  'export-json': False, # generates an export.json suitable for a testrunner, if possible for self.command.
185
187
  'enable-tags': [],
186
188
  'disable-tags': [],
189
+ 'test-mode': False,
187
190
  })
188
191
  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/',
192
+ 'stop-before-compile': ('stop this run before any compile (if possible for tool) and'
193
+ ' save .sh scripts in eda-dir/'),
191
194
  'eda-dir': 'relative directory where eda logs are saved',
192
195
  'export': 'export results for these targets in eda-dir',
193
196
  'export-run': 'export, and run, results for these targets in eda-dir',
194
197
  '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.'
198
+ 'work-dir': ('Optional override for working directory, often defaults to'
199
+ ' ./eda.work/<top>.<command>'),
200
+ "work-dir-use-target-dir": ('Set the work-dir to be the same as the in-place location'
201
+ ' where the target (DEPS) exists'),
202
+ 'enable-tags': ('DEPS markup tag names to be force enabled for this'
203
+ ' command (mulitple appends to list).'),
204
+ 'diable-tags': ('DEPS markup tag names to be disabled (even if they'
205
+ ' match the criteria) for this command (mulitple appends to list).'
206
+ ' --disable-tags has higher precedence than --enable-tags.'),
207
+ 'test-mode': ('command and tool dependent, usually stops the command early without'
208
+ ' executing.'),
201
209
  })
202
210
  self.modified_args = {}
203
211
  self.config = copy.deepcopy(config) # avoid external modifications.
204
212
  self.target = ""
213
+ self.target_path = ""
205
214
  self.status = 0
206
215
 
207
216
  def error(self, *args, **kwargs):
@@ -223,8 +232,18 @@ class Command:
223
232
 
224
233
  def create_work_dir(self):
225
234
  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'])
235
+ if self.args['work-dir-use-target-dir']:
236
+ if not self.target_path:
237
+ self.target_path = '.'
238
+ util.info(f"create_work_dir: --work-dir-use-target-dir: using:",
239
+ f"{os.path.abspath(self.target_path)}",
240
+ f'target={self.target}')
241
+ self.args['work-dir'] = self.target_path
242
+ self.args['sub-work-dir'] = ''
243
+ return self.args['work-dir']
244
+
245
+ if not os.path.exists(self.args['eda-dir']):
246
+ util.safe_mkdir(self.args['eda-dir'])
228
247
  util.info(f"create_work_dir: created {self.args['eda-dir']}")
229
248
  if self.args['design'] == "":
230
249
  if ('top' in self.args) and (self.args['top'] != ""):
@@ -250,14 +269,35 @@ class Command:
250
269
  if (os.path.exists(self.args['work-dir'])):
251
270
  if os.path.exists(keep_file) and not self.args['force']:
252
271
  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"]}')
272
+ elif os.path.abspath(self.args['work-dir']) in os.getcwd():
273
+ # This effectively checks if
274
+ # --work-dir=.
275
+ # --work-dir=$PWD
276
+ # --work-dir=/some/path/almost/here
277
+ # Allow it, but preserve the existing directory, we don't want to blow away
278
+ # files up-heir from us.
279
+ # Enables support for --work-dir=.
280
+ util.info(f"Not removing existing work-dir: '{self.args['work-dir']}' is within {os.getcwd()=}")
281
+ elif str(Path(self.args['work-dir'])).startswith(str(Path('/'))):
282
+ # Do not allow other absolute path work dirs if it already exists.
283
+ # This prevents you from --work-dir=~ and eda wipes out your home dir.
284
+ self.error(f'Cannot use work-dir={self.args["work-dir"]} starting with absolute path "/"')
285
+ elif str(Path('..')) in str(Path(self.args['work-dir'])):
286
+ # Do not allow other ../ work dirs if it already exists.
287
+ self.error(f'Cannot use work-dir={self.args["work-dir"]} with up-hierarchy ../ paths')
288
+ else:
289
+ # If we made it this far, on a directory that exists, that appears safe
290
+ # to delete and re-create:
291
+ util.info(f"Removing previous '{self.args['work-dir']}'")
292
+ shutil.rmtree(self.args['work-dir'])
293
+ util.safe_mkdir(self.args['work-dir'])
294
+ util.debug(f'create_work_dir: created {self.args["work-dir"]}')
295
+ else:
296
+ util.safe_mkdir(self.args['work-dir'])
297
+ util.debug(f'create_work_dir: created {self.args["work-dir"]}')
257
298
  if (self.args['keep']):
258
299
  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"]}')
300
+ util.debug(f'create_work_dir: created {keep_file=}')
261
301
  return self.args['work-dir']
262
302
 
263
303
  def exec(self, work_dir, command_list, background=False, stop_on_error=True,
@@ -858,7 +898,7 @@ class CommandDesign(Command):
858
898
  # self.target is a name we grab for the job (i.e. for naming work dir etc). we don't want the path prefix.
859
899
  # TODO: too messy -- there's also a self.target, args['job-name'], args['work-dir'], args['design'], args['top'], args['sub-work-dir'] ...
860
900
 
861
- self.target = os.path.basename(target)
901
+ self.target_path, self.target = os.path.split(target)
862
902
 
863
903
  if target in self.targets_dict:
864
904
  # If we're encountered this target before, stop. We're not traversing again.
@@ -1361,6 +1401,8 @@ class CommandParallel(Command):
1361
1401
  fancy_mode = util.args['fancy'] and (num_parallel > 1) and (num_parallel <= (lines-6))
1362
1402
  multi_cwd = util.getcwd() + os.sep
1363
1403
 
1404
+ self.patch_jobs_for_duplicate_target_names()
1405
+
1364
1406
  if run_parallel:
1365
1407
  # we are doing this multi-threaded
1366
1408
  util.info(f"Parallel: Running multi-threaded, starting {num_parallel} workers")
@@ -1519,6 +1561,10 @@ class CommandParallel(Command):
1519
1561
  self.status = 0 if len(self.jobs_status) == 0 else max(self.jobs_status)
1520
1562
  util.fancy_stop()
1521
1563
 
1564
+ @staticmethod
1565
+ def get_name_from_target(target: str) -> str:
1566
+ return target.replace('../', '').lstrip('./')
1567
+
1522
1568
 
1523
1569
  def update_args_list(self, args: list, tool: str) -> None:
1524
1570
  '''Modfies list args, using allow-listed known top-level args:
@@ -1572,3 +1618,58 @@ class CommandParallel(Command):
1572
1618
  # Remove unparsed args starting with '+', since those are commonly sent downstream to
1573
1619
  # single job (example, CommandSim plusargs).
1574
1620
  return [x for x in single_cmd_unparsed if not x.startswith('+')]
1621
+
1622
+
1623
+ def patch_jobs_for_duplicate_target_names(self) -> None:
1624
+ '''Examines list self.jobs, and if leaf target names are duplicate will
1625
+ patch each command's job-name to:
1626
+ --job-name=path.leaf.command[.tool]
1627
+ '''
1628
+
1629
+ def get_job_name(job_dict: dict) -> str:
1630
+ '''Fishes the job-name out of an entry in self.jobs'''
1631
+ for i, item in enumerate(job_dict['command_list']):
1632
+ if item.startswith('--job-name='):
1633
+ _, name = item.split('--job-name=')
1634
+ return name
1635
+ elif item == '--job-name':
1636
+ return job_dict['command_list'][i + 1]
1637
+ return ''
1638
+
1639
+ def replace_job_name(job_dict: dict, new_job_name: str) -> dict:
1640
+ '''Replaces the job-name in an entry in self.jobs'''
1641
+ for i, item in enumerate(job_dict['command_list']):
1642
+ if item.startswith('--job-name='):
1643
+ job_dict['command_list'][i] = '--job-name=' + new_job_name
1644
+ return job_dict
1645
+ elif item == '--job-name':
1646
+ job_dict['command_list'][i + 1] = new_job_name
1647
+ return job_dict
1648
+ return job_dict
1649
+
1650
+
1651
+ job_names_count_dict = {}
1652
+ for job_dict in self.jobs:
1653
+
1654
+ key = get_job_name(job_dict)
1655
+ if not key:
1656
+ self.error(f'{job_dict=} needs to have a --job-name= arg attached')
1657
+ if key not in job_names_count_dict:
1658
+ job_names_count_dict[key] = 1
1659
+ else:
1660
+ job_names_count_dict[key] += 1
1661
+
1662
+ for i, job_dict in enumerate(self.jobs):
1663
+ key = get_job_name(job_dict)
1664
+ if job_names_count_dict[key] < 2:
1665
+ continue
1666
+
1667
+ tpath, _ = os.path.split(job_dict['target'])
1668
+
1669
+ # prepend path information to job-name:
1670
+ patched_sub_work_dir = False
1671
+ patched_target_path = os.path.relpath(tpath).replace(os.sep, '_')
1672
+ new_job_name = f'{patched_target_path}.{key}'
1673
+ new_job_dict = replace_job_name(job_dict, new_job_name)
1674
+ self.jobs[i] = new_job_dict
1675
+ util.debug(f'Patched job {job_dict["name"]}: --job-name={new_job_name}')
opencos/tools/iverilog.py CHANGED
@@ -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
 
opencos/tools/vivado.py CHANGED
@@ -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.40
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
@@ -4,7 +4,7 @@ opencos/_waves_pkg.sv,sha256=1lbhQOVGc3t_R8czYjP40hssP0I3FlZOpHTkI7yKFbI,1251
4
4
  opencos/deps_helpers.py,sha256=Pgo3dO_QBHzGB0lE2B0uf2vWWDy3dSDN0pvW-eA6ocs,56939
5
5
  opencos/deps_schema.py,sha256=MhytzXwp071F14RwxqHt78ak8Qruoe4FeK5XSzkO2f0,14658
6
6
  opencos/eda.py,sha256=k0_7ppBBPFsQ8Jd0mJGOnc6llUNo2hryHwx8DZ_B_jU,18832
7
- opencos/eda_base.py,sha256=8kDrKM5YpwSmSqnSIItiV6R9FDr5QjraiEF3PeXe7Lw,77580
7
+ opencos/eda_base.py,sha256=I5BnL50SfJniU-I4_7kKvhBqNpev-MZcX9SMhSsDPrU,82373
8
8
  opencos/eda_config.py,sha256=FVp-dg9IVq78LZoh43kFYo9WXKfFxsMQMo6JGulEbEM,8818
9
9
  opencos/eda_config_defaults.yml,sha256=0tqs4paxCYZJshb2WW2GfaZyeh_l9ZUKWMh8hh17AWk,10235
10
10
  opencos/eda_config_max_verilator_waivers.yml,sha256=lTAU4IOEbUWVlPzuer1YYhIyxpPINeA4EJqcRIT-Ymk,840
@@ -26,11 +26,11 @@ opencos/commands/build.py,sha256=jI5ul53qfwn6X-yfSdSQIcLBhGtzZUk7r_wKBBmKJI0,142
26
26
  opencos/commands/elab.py,sha256=m6Gk03wSzX8UkcmReooK7turF7LpqO0IcdOZwJ8XiyI,1596
27
27
  opencos/commands/export.py,sha256=uGDI5_lUhyNB54gFjm9cWv9g_3waEOJN4wOC01oFlCY,3535
28
28
  opencos/commands/flist.py,sha256=rylcisH3X6UZGQY8WkSGHHIYWKi6o-JwtITz7gflsbY,8460
29
- opencos/commands/multi.py,sha256=__UF5If4WIY_9044gcGEQiU8MTGPro-q3kzQ4v0PMdI,26283
29
+ opencos/commands/multi.py,sha256=1IH5Bk5xnKsNvtEsYy8a6bFmcyHSfrMVK-lLNdj6vlg,26449
30
30
  opencos/commands/open.py,sha256=unrpGckzg0FE5W3oARq8x0jX7hhV_uM9Oh5FgISHFAg,724
31
31
  opencos/commands/proj.py,sha256=MdHTOtQYG93_gT97dWuSyAgUxX2vi9FRhL0dtc-rM98,1096
32
32
  opencos/commands/sim.py,sha256=phATz_wR0BAH6B_IJ4zyzg_Hptp5hSEOe_-9NLaL_bY,14058
33
- opencos/commands/sweep.py,sha256=L4AYF3vQHR-fi0871f1CwrD0y4tydrsNpWSDjVf1xIA,8719
33
+ opencos/commands/sweep.py,sha256=O0VSpzHHlE_1hM-Edp4d80PAnh2P2HCIwsGLnhkRHWM,9107
34
34
  opencos/commands/synth.py,sha256=quB-HWS4LKYTiFBHiYarQi4pMnRmt12wQTZpi14VvlE,4355
35
35
  opencos/commands/targets.py,sha256=_jRNhm2Fqj0fmMvTw6Ba39DCsRHf_r_uZCy_R064kpA,1472
36
36
  opencos/commands/upload.py,sha256=nlb4nlxrDCQPcabEmH3nP19g4PFILDqFDab4LwJ95Z4,796
@@ -57,20 +57,20 @@ opencos/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
57
  opencos/tools/invio.py,sha256=q9E9n6xsozDfar-1rLvJEZbCpPb_bQEy6WKEI3KS3dk,3163
58
58
  opencos/tools/invio_helpers.py,sha256=1au4CYmV5aC7DHjaZBNemydH6Eq0i-Yt5L3HyKfQOfY,7638
59
59
  opencos/tools/invio_yosys.py,sha256=4zWBeFKXHSyb5WSnf6ZpVG2UwoKF0SC-00I1_VqgXZM,6016
60
- opencos/tools/iverilog.py,sha256=1SmkJAtG096ozIY6N19UtpD-YT1UKJAcMLJ9blfraP0,6413
61
- opencos/tools/modelsim_ase.py,sha256=x5xFWBNaln2lVLixN0Od0uNaLKN_Bt1q6a91QmhKoNA,13162
60
+ opencos/tools/iverilog.py,sha256=oPaR654-3EHjyb6_r9Nj9VVaHrDAX7kSKztBAQRvNHU,6502
61
+ opencos/tools/modelsim_ase.py,sha256=Y2Y-xC3ktby6z-dE3iipuqPkNl8eCmdi2Hb9mcwJTHA,13218
62
62
  opencos/tools/questa.py,sha256=AX_3USyf6eMcssH4b-8WLbCzz-cXYnQzlHvCyL9C7Og,7505
63
63
  opencos/tools/slang.py,sha256=74EDAAnN7mrrYxgxaPDaoRJZK7Se9B_HsW8Ioi2Nw44,7425
64
64
  opencos/tools/slang_yosys.py,sha256=mw4AfutGjKyCj7NLrHDy2j3p0XC2H7uuBf9RkVQJYoQ,9856
65
65
  opencos/tools/surelog.py,sha256=JOMs8SqnzJ_ZL5mEdyyn3Z1r1Kc8hfbV3Pnen1YzxWA,4980
66
66
  opencos/tools/tabbycad_yosys.py,sha256=h9kkAi479cZzYfb4R9WBNY_JmR6BgVFj4s3VShnGpoA,7813
67
- opencos/tools/verilator.py,sha256=0ZHAkkUqnsM1A4B8-u6tff3lhl-cgfDUx-Dq7DaRwkI,18080
68
- opencos/tools/vivado.py,sha256=cL5IZdudqquddvZqHQGDVmaHSxgBZsMUmAq18q8AgoM,39134
67
+ opencos/tools/verilator.py,sha256=lxR7BSmeTc6YcL0UuXzIfJk7umVm8RfbU8rtYtbKUBg,18192
68
+ opencos/tools/vivado.py,sha256=1dbQ-5oUUaUNIeMp07HArWG15spG81OuCwJ88qRNXU0,39102
69
69
  opencos/tools/yosys.py,sha256=aZnRFbsODYRe4BHbfxl6vfWeEP7WJYJk50gCZcn8Fu0,8902
70
- opencos_eda-0.2.38.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
71
- opencos_eda-0.2.38.dist-info/licenses/LICENSE.spdx,sha256=8gn1610RMP6eFgT3Hm6q9VKXt0RvdTItL_oxMo72jII,189
72
- opencos_eda-0.2.38.dist-info/METADATA,sha256=kKhYeLRFFBsjoHaLMNW-xyGGbQejy0hEnW00rsC6puQ,604
73
- opencos_eda-0.2.38.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
74
- opencos_eda-0.2.38.dist-info/entry_points.txt,sha256=V8OE1lySAFcFQpDNJuVxVZteeSmDH-joLMhGvrxrvmg,164
75
- opencos_eda-0.2.38.dist-info/top_level.txt,sha256=J4JDP-LpRyJqPNeh9bSjx6yrLz2Mk0h6un6YLmtqql4,8
76
- opencos_eda-0.2.38.dist-info/RECORD,,
70
+ opencos_eda-0.2.40.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
71
+ opencos_eda-0.2.40.dist-info/licenses/LICENSE.spdx,sha256=8gn1610RMP6eFgT3Hm6q9VKXt0RvdTItL_oxMo72jII,189
72
+ opencos_eda-0.2.40.dist-info/METADATA,sha256=A0MWU-i412C_zVRQpgDL34s64OLNavbupGPmlgBowks,604
73
+ opencos_eda-0.2.40.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
74
+ opencos_eda-0.2.40.dist-info/entry_points.txt,sha256=V8OE1lySAFcFQpDNJuVxVZteeSmDH-joLMhGvrxrvmg,164
75
+ opencos_eda-0.2.40.dist-info/top_level.txt,sha256=J4JDP-LpRyJqPNeh9bSjx6yrLz2Mk0h6un6YLmtqql4,8
76
+ opencos_eda-0.2.40.dist-info/RECORD,,