opencos-eda 0.2.49__py3-none-any.whl → 0.2.51__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/util.py CHANGED
@@ -1,18 +1,23 @@
1
1
  '''opencos.util -- support global logging, argparser for printing (colors)'''
2
2
 
3
- import sys
4
- import subprocess
3
+ import argparse
4
+ import atexit
5
5
  import datetime
6
+ import json
6
7
  import os
7
- import time
8
- import atexit
8
+ import re
9
9
  import shutil
10
+ import subprocess
11
+ import sys
12
+ import time
10
13
  import traceback
11
- import argparse
12
- import re
13
14
 
15
+ from enum import Enum
16
+ from pathlib import Path
14
17
  from importlib import import_module
15
18
 
19
+ from opencos.utils import status_constants
20
+
16
21
  global_exit_allowed = False # pylint: disable=invalid-name
17
22
  progname = "UNKNOWN" # pylint: disable=invalid-name
18
23
  progname_in_message = True # pylint: disable=invalid-name
@@ -26,8 +31,11 @@ args = { # pylint: disable=invalid-name
26
31
  'fancy' : sys.stdout.isatty(),
27
32
  'warnings' : 0,
28
33
  'errors' : 0,
34
+ 'artifacts-json': True,
29
35
  }
30
36
 
37
+ max_error_code = 0 # pylint: disable=invalid-name
38
+
31
39
  class Colors:
32
40
  '''Namespace class for color printing help'''
33
41
  red = "\x1B[31m"
@@ -70,6 +78,141 @@ def yellow_text(text: str) -> str:
70
78
  return Colors.yellow + text + Colors.normal
71
79
  return text
72
80
 
81
+ class ArtifactTypes(Enum):
82
+ '''Types that are allow-listed for artifacts.add* methods. If you don't use one of
83
+ these, you'll get a warning'''
84
+ TEXT = 0
85
+ JSON = 1
86
+ YAML = 2
87
+ WAVEFORM = 3
88
+ DOTF = 4
89
+ TCL = 5
90
+ SHELL = 6
91
+
92
+ class Artifacts:
93
+ '''Class to hold file artifacts, for logs generated by EDA, or other artifcats created
94
+ by a specific tool.
95
+
96
+ If enabled, will write out an artifacts.json file upon util.exit()
97
+ '''
98
+
99
+ data = {}
100
+ unresolved_data = {}
101
+ enabled = True
102
+ artifacts_json_filepath = os.path.join('eda.work', 'artifacts.json')
103
+
104
+ def _get_type_str(self, typ: str) -> (bool, str):
105
+ '''Gets the name from ArtifactTypes, and returns tuple of (True, str)
106
+
107
+ if the ArtifactTypes exists, else (False, str.upper())'''
108
+ ret = getattr(ArtifactTypes, typ.upper(), '')
109
+ if ret:
110
+ return True, ret.name.lower()
111
+ return False, typ.lower()
112
+
113
+ def add(self, name: str, typ: str, description: str = '') -> None:
114
+ '''Adds file to artifacts'''
115
+
116
+ if not self.enabled:
117
+ return # artifacts dumping disabled.
118
+
119
+ _, shortname = os.path.split(name)
120
+ if shortname in self.data:
121
+ return # artifact already registered
122
+
123
+ type_exists, type_str = self._get_type_str(typ)
124
+ if not type_exists:
125
+ warning(f'Unknown artifacts {typ=} add for {name=} {description=}')
126
+
127
+ self.data[shortname] = {
128
+ 'name': name,
129
+ 'type': type_str,
130
+ 'size': 0, # will be filled in when JSON written upon exit.
131
+ 'description': description,
132
+ }
133
+
134
+ def add_extension(
135
+ self, search_paths: list, file_extension: str, typ: str, description: str = ''
136
+ ) -> None:
137
+ '''Adds a placeholder for file extensions to add to artifacts
138
+
139
+ For example, when saving a Simulation waves, we may know it's a .fst or .vcd file,
140
+ but we do not know what the testbench SV file has set in $dumpfile(filepath)
141
+ '''
142
+ type_exists, type_str = self._get_type_str(typ)
143
+ if not type_exists:
144
+ warning(f'Unknown artifacts {typ=} add_extension for {search_paths=}',
145
+ f'{file_extension=} {description=}')
146
+
147
+ if isinstance(search_paths, str):
148
+ sp = [search_paths]
149
+ else:
150
+ sp = search_paths
151
+ self.unresolved_data[file_extension] = {
152
+ 'search_paths': sp,
153
+ 'type': type_str,
154
+ 'description': description
155
+ }
156
+
157
+ def set_artifacts_json_dir(self, dirpath: str) -> None:
158
+ '''Sets the artifacts_json_filepath'''
159
+ _, right = os.path.split(self.artifacts_json_filepath)
160
+ self.artifacts_json_filepath = os.path.join(dirpath, right)
161
+
162
+ def reset(self, enable: bool = True) -> None:
163
+ '''Clears internal data (dict). Called by util.process_tokens()'''
164
+ self.data = {}
165
+ self.unresolved_data = {}
166
+ self.enabled = enable or args['artifacts-json']
167
+ self.artifacts_json_filepath = os.path.join('eda.work', 'artifacts.json')
168
+
169
+ def _resolve_unresolved_data(self, ext: str) -> None:
170
+ '''Find files for this extension that were registered using add_extension(...)
171
+
172
+ adds to self.data'''
173
+ entry = self.unresolved_data[ext]
174
+ if not entry:
175
+ return
176
+
177
+ for search_path in entry['search_paths']:
178
+ p = Path(search_path)
179
+ for posix_filename in p.glob(f'*.{ext}'):
180
+ self.add(
181
+ name=str(posix_filename), typ=entry['type'], description=entry['description']
182
+ )
183
+
184
+ def write_json(self) -> None:
185
+ '''Write out the artifacts.json file, called by util.exit()'''
186
+
187
+ if not self.enabled:
188
+ return # artifacts dumping disabled.
189
+
190
+ if self.unresolved_data:
191
+ for ext in self.unresolved_data:
192
+ self._resolve_unresolved_data(ext)
193
+
194
+ if not self.data:
195
+ return # do nothing if we have no artifacts
196
+
197
+ # Update all file sizes:
198
+ remove_keys = set()
199
+ for key, entry in self.data.items():
200
+ if os.path.isfile(entry['name']):
201
+ entry['size'] = os.path.getsize(entry['name'])
202
+ else:
203
+ # file doesn't exist, remove it from artifacts.
204
+ warning(f'Removing {key} ({entry["name"]}) from artifacts (file does not exist)')
205
+ remove_keys.add(key)
206
+ for key in remove_keys:
207
+ del self.data[key]
208
+
209
+ with open(self.artifacts_json_filepath, 'w', encoding='utf-8') as f:
210
+ json.dump(self.data, f, indent=4)
211
+ info(f'Wrote artifacts JSON: {self.artifacts_json_filepath}')
212
+
213
+
214
+ artifacts = Artifacts()
215
+
73
216
 
74
217
  class UtilLogger:
75
218
  '''Class for the util.global_log'''
@@ -81,6 +224,7 @@ class UtilLogger:
81
224
  # util's argparser: --no-default-log, --logfile=<name>, or --force-logfile=<name>
82
225
  default_log_enabled = False
83
226
  default_log_filepath = os.path.join('eda.work', 'eda.log')
227
+ enable = True
84
228
 
85
229
  def clear(self) -> None:
86
230
  '''Resets internals'''
@@ -98,6 +242,9 @@ class UtilLogger:
98
242
 
99
243
  def start(self, filename: str, force: bool = False) -> None:
100
244
  '''Starts (opens) log'''
245
+ if not self.enable:
246
+ self.file = None
247
+ return
101
248
  if not filename:
102
249
  error('Trying to start a logfile, but filename is missing')
103
250
  return
@@ -115,6 +262,8 @@ class UtilLogger:
115
262
  debug(f"Opened logfile '{filename}' for writing")
116
263
  self.filepath = filename
117
264
  self.write_timestamp(f'start - {self.filepath}')
265
+ # add to global artifacts:
266
+ artifacts.add(name=filename, typ='text', description='EDA stdout logfile')
118
267
  except Exception as e:
119
268
  error(f"Error opening '{filename}' for writing, {e}")
120
269
  self.clear()
@@ -213,6 +362,8 @@ def get_argparser() -> argparse.ArgumentParser:
213
362
  parser.add_argument('--no-respawn', action='store_true',
214
363
  help=('Legacy mode (default respawn disabled) for respawning eda.py'
215
364
  ' using $OC_ROOT/bin'))
365
+ parser.add_argument('--artifacts-json', **bool_action_kwargs,
366
+ help='Store a work-dir/artifacts.json file of known tool output files')
216
367
  return parser
217
368
 
218
369
 
@@ -265,18 +416,24 @@ def process_tokens(tokens:list) -> (argparse.Namespace, list):
265
416
 
266
417
  debug(f'util.process_tokens: {parsed=} {unparsed=} from {tokens=}')
267
418
 
419
+ # clear existing artifacts dicts (mostly for pytests repeatedly calling eda.main),
420
+ # set artifacts.enabled based on args['artifacts-json']
421
+ artifacts.reset(enable=parsed.artifacts_json)
422
+
268
423
  if parsed.force_logfile:
269
424
  start_log(parsed.force_logfile, force=True)
270
425
  elif parsed.logfile:
271
426
  start_log(parsed.logfile, force=False)
272
427
  elif parsed.default_log and \
428
+ not any(x in unparsed for x in ('help', '-h', '--help')) and \
273
429
  (parsed.force_logfile is None and parsed.logfile is None):
274
430
  # Use a forced logfile in the eda.work/eda.log:
431
+ # avoid this if someone has --help arg not yet parsed.
275
432
  start_log(global_log.default_log_filepath, force=True)
276
433
 
277
-
278
434
  parsed_as_dict = vars(parsed)
279
435
  for key,value in parsed_as_dict.items():
436
+ key = key.replace('_', '-')
280
437
  if value is not None:
281
438
  args[key] = value # only update with non-None values to our global 'args' dict
282
439
 
@@ -468,7 +625,9 @@ def warning(*text, start: object = None, end: str = '\n') -> None:
468
625
 
469
626
 
470
627
  def error(
471
- *text, error_code: int = 255, do_exit: bool = True, start: object = None, end: str = '\n'
628
+ *text,
629
+ error_code: int = status_constants.EDA_DEFAULT_ERROR,
630
+ do_exit: bool = True, start: object = None, end: str = '\n'
472
631
  ) -> int:
473
632
  '''Print error messaging (in red if possible).
474
633
 
@@ -481,9 +640,12 @@ def error(
481
640
 
482
641
  Note these messages append to global logging. Increments global args['errors'] int.
483
642
  '''
643
+ global max_error_code # pylint: disable=global-statement
644
+
484
645
  if start is None:
485
646
  start = "ERROR: " + (f"[{progname}] " if progname_in_message else "")
486
647
  args['errors'] += 1
648
+ max_error_code = max(max_error_code, error_code)
487
649
  print_red(f"{start}{' '.join(list(text))}", end=end)
488
650
  if do_exit:
489
651
  if args['debug']:
@@ -496,10 +658,23 @@ def error(
496
658
  return abs(int(error_code))
497
659
 
498
660
 
661
+ def get_return_code() -> int:
662
+ '''Checks global max_error_code and args['errors']'''
663
+ if args['errors']:
664
+ if max_error_code == 0:
665
+ return 255
666
+ return max_error_code
667
+ return 0
668
+
669
+
499
670
  def exit( # pylint: disable=redefined-builtin
500
671
  error_code: int = 0, quiet: bool = False
501
672
  ) -> int:
502
673
  '''sys.exit(int) wrapper, returns the error_code if global_exit_allowed=False'''
674
+
675
+ # Save out artifacts file:
676
+ artifacts.write_json()
677
+
503
678
  if global_exit_allowed:
504
679
  if not quiet:
505
680
  info(f"Exiting with {args['warnings']} warnings, {args['errors']} errors")
@@ -1,5 +1,7 @@
1
1
  ''' opencos.utils.markup_helpers - function helpers for YAML, TOML reading and writing'''
2
2
 
3
+ import json
4
+ import os
3
5
  import re
4
6
  import shutil
5
7
  import subprocess
@@ -89,10 +91,37 @@ def yaml_safe_load(filepath: str, only_root_line_numbers:bool = False) -> dict:
89
91
 
90
92
 
91
93
  def yaml_safe_writer(data: dict, filepath: str) -> None:
92
- '''Warpper for yaml.dump, enforces file extension otherwise warning'''
93
- if filepath.endswith('.yml') or filepath.endswith('.yaml'):
94
+ '''Wrapper for yaml.dump, enforces file extension otherwise warning'''
95
+ _, ext = os.path.splitext(filepath)
96
+ if ext.lower() in ('.yml', '.yaml'):
94
97
  with open(filepath, 'w', encoding='utf-8') as f:
95
98
  yaml.dump(data, f, allow_unicode=True,
96
99
  default_flow_style=False, sort_keys=False, encoding='utf-8')
97
100
  else:
98
101
  warning(f'{filepath=} to be written for this extension not implemented.')
102
+
103
+ def json_writer(data: dict, filepath: str) -> None:
104
+ '''Wrapper for json.dump'''
105
+ with open(filepath, 'w', encoding='utf-8') as f:
106
+ json.dump(data, f, indent=4)
107
+
108
+
109
+ def markup_writer(data: dict, filepath: str) -> None:
110
+ '''Wrapper for yaml_safe_writer or json_writer'''
111
+ _, ext = os.path.splitext(filepath)
112
+ if ext.lower in ('.yml', '.yaml'):
113
+ yaml_safe_writer(data, filepath)
114
+ else:
115
+ json_writer(data, filepath)
116
+
117
+
118
+ def markup_dumper(data: dict, as_yaml: bool = False) -> str:
119
+ '''Returns JSON str; if as_yaml=True returns YAML str, from data'''
120
+ if as_yaml:
121
+ return yaml.dump(
122
+ data=data, allow_unicode=True,
123
+ default_flow_style=False, sort_keys=False
124
+ )
125
+
126
+ # else return JSON:
127
+ return str(json.dumps(data, indent=4))
@@ -0,0 +1,27 @@
1
+ '''opencos.utils.status_constants is a module containing known Error return codes
2
+
3
+ (0 pass, > 0 fail) from eda or other opencos executables.
4
+ '''
5
+
6
+ NO_ERROR = 0
7
+
8
+ PYTHON_EXCEPTION = 1
9
+
10
+ EDA_DEPS_FILE_NOT_FOUND = 10
11
+ EDA_DEPS_TARGET_NOT_FOUND = 11
12
+
13
+ EDA_COMMAND_OR_ARGS_ERROR = 20
14
+ EDA_CONFIG_ERROR = 21
15
+ EDA_COMMAND_MISSING_TOP = 22
16
+
17
+ EDA_SIM_LOG_HAS_BAD_STRING = 30
18
+ EDA_SIM_LOG_MISSING_MUST_STRING = 31
19
+
20
+ EDA_SHELL_LOG_HAS_BAD_STRING = 38
21
+ EDA_SHELL_LOG_MISSING_MUST_STRING = 39
22
+
23
+ EDA_EXEC_NONZERO_RETURN_CODE1 = 41
24
+ EDA_EXEC_NONZERO_RETURN_CODE2 = 42
25
+ EDA_EXEC_NONZERO_RETURN_CODE255 = 255
26
+
27
+ EDA_DEFAULT_ERROR = 255
@@ -0,0 +1,55 @@
1
+ '''Because so many tools use the exe vsim, I don't want to run `vsim -version` N times for N
2
+ tools each to figure out if it's full-Questa, Modelsim, QuestaFSE, or Riviera.
3
+
4
+ Instead, eda.py can call this once, and then query if this tool exists when running
5
+ opencos.eda.auto_tool_setup(..)
6
+ '''
7
+
8
+ import shutil
9
+ import subprocess
10
+
11
+ from opencos.util import debug
12
+
13
+ vsim_path = shutil.which('vsim')
14
+
15
+ INIT_HAS_RUN = False
16
+ TOOL_IS = {
17
+ 'riviera': False,
18
+ 'modelsim_ase': False,
19
+ 'questa' : False,
20
+ 'questa_fse': False
21
+ }
22
+
23
+
24
+ def init() -> None:
25
+ '''Sets INIT_HAS_RUN=True (only runs once) and one of TOOL_IS[tool] = True'''
26
+ global INIT_HAS_RUN # pylint: disable=global-statement
27
+
28
+ if INIT_HAS_RUN:
29
+ return
30
+
31
+ INIT_HAS_RUN = True
32
+
33
+ if not vsim_path:
34
+ return
35
+
36
+ proc = None
37
+ try:
38
+ proc = subprocess.run([vsim_path, '-version'], capture_output=True, check=False)
39
+ except Exception as e:
40
+ debug(f'vsim -version: exception {e}')
41
+
42
+ if proc is None or proc.returncode != 0:
43
+ return
44
+
45
+
46
+ stdout_str_lower = proc.stdout.decode('utf-8', errors='replace').lower()
47
+
48
+ if all(x in stdout_str_lower for x in ('starter', 'modelsim', 'fpga')):
49
+ TOOL_IS['modelsim_ase'] = True
50
+ elif all(x in stdout_str_lower for x in ('starter', 'questa', 'fpga')):
51
+ TOOL_IS['questa_fse'] = True
52
+ elif all(x in stdout_str_lower for x in ('riviera', 'aldec')):
53
+ TOOL_IS['riviera'] = True
54
+ elif 'questa' in stdout_str_lower:
55
+ TOOL_IS['questa'] = True
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opencos-eda
3
- Version: 0.2.49
3
+ Version: 0.2.51
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,13 +2,14 @@ opencos/__init__.py,sha256=RwJA9oc1uUlvNX7v5zoqwjnSRNq2NZwRlHqtS-ICJkI,122
2
2
  opencos/_version.py,sha256=XiHFZjCofkkZvI9befTFKsRt5zLouUo1CIwhW4srWU0,582
3
3
  opencos/_waves_pkg.sv,sha256=1lbhQOVGc3t_R8czYjP40hssP0I3FlZOpHTkI7yKFbI,1251
4
4
  opencos/deps_schema.py,sha256=pdJpKmfXxCYZsfXTxsnACw-s6Mzk55QH06ZSA5uqPV0,15454
5
- opencos/eda.py,sha256=y53bScMokPfpbZfqzpSg9Q08U6GVF_BjW2P0bPiEBE0,20424
6
- opencos/eda_base.py,sha256=GOgJN68SlW4R8f6tTpG6eiI5lyZpd1jLE0gbs0yeZeo,93660
7
- opencos/eda_config.py,sha256=3xdaTdOx59myfqxAJV5Ji_jodRU_MhIqyQdiQXuX2Ls,11246
8
- opencos/eda_config_defaults.yml,sha256=AteZbwRJ6wviinks47-e5TX0DoU0culJfBw6L3xYOOA,11535
5
+ opencos/eda.py,sha256=rYBt4Qu2y45zdwD4jDx_p3l2u5LMS1nsaGQCP2ZYdwY,20883
6
+ opencos/eda_base.py,sha256=q0uKEzAMzLmqb4jMBcGv7rTpdKnfrhnMZo7MyB8YN8Y,95706
7
+ opencos/eda_config.py,sha256=Xma8w7kBLCNPCSrCKpceieU7GUBv4i54XZlHjnZ95X4,11353
8
+ opencos/eda_config_defaults.yml,sha256=PdR3xHWQIdGeIyCTr2c3W9Vfq9RC1E9HbqiSydyDYZE,12417
9
9
  opencos/eda_config_max_verilator_waivers.yml,sha256=lTAU4IOEbUWVlPzuer1YYhIyxpPINeA4EJqcRIT-Ymk,840
10
10
  opencos/eda_config_reduced.yml,sha256=cQ9jY4J7EvAbeHTiP6bvpDSVJAYiitjLZPSxxLKIEbk,1440
11
11
  opencos/eda_deps_bash_completion.bash,sha256=jMkQKY82HBgOnQeMdA1hMrXguRFtB52SMBxUemKovL4,1958
12
+ opencos/eda_deps_sanitize.py,sha256=SQjvrte9Hv9JesRY0wljvbdC6pAmLCikI-Wdzzy-D04,1939
12
13
  opencos/eda_extract_targets.py,sha256=dvBjc2qFBJkwlW6Fm-66Y_vlr0VZL1QwfIosMR_bgbY,4814
13
14
  opencos/eda_tool_helper.py,sha256=_YgobDLEWW6Fzdr976LxaCDZ4DKRyuMs5CrYQHaTPrU,2558
14
15
  opencos/export_helper.py,sha256=ArsM8qxBc08gj9S-UholGU417POfBYb_cHkBQZEfqfI,22046
@@ -17,18 +18,18 @@ opencos/files.py,sha256=aoq0O2KfISzZb-Vi_q_0TTGBER9xJc--FkVZf0ga7pA,1549
17
18
  opencos/names.py,sha256=iC37PV7Pz0PicTDg09vbQ9NXAj-5m6RKrWHkkcHB8As,1145
18
19
  opencos/peakrdl_cleanup.py,sha256=vHNGtalTrIVP335PhRjPt9RhoccgpK1HJAi-E4M8Kc8,736
19
20
  opencos/seed.py,sha256=IL9Yg-r9SLSRseMVWaEHmuw2_DNi_eyut11EafoNTsU,942
20
- opencos/util.py,sha256=w7nZIzvb25aezemAlMWaUgaYg6IshikpfLEGEOrmM3g,27874
21
+ opencos/util.py,sha256=hnE66Mu7Uu-OGdAE5gkJ8nsKc_zUNMptXcuBFkm30wU,33975
21
22
  opencos/commands/__init__.py,sha256=DtOA56oWJu68l-_1_7Gdv0N-gtXVB3-p9IhGzAYex8U,1014
22
23
  opencos/commands/build.py,sha256=jI5ul53qfwn6X-yfSdSQIcLBhGtzZUk7r_wKBBmKJI0,1425
23
24
  opencos/commands/elab.py,sha256=m6Gk03wSzX8UkcmReooK7turF7LpqO0IcdOZwJ8XiyI,1596
24
25
  opencos/commands/export.py,sha256=juzxJL5-RpEnU5DmwF0fiG5pUrB2BbUbvCp2OasEd88,3494
25
26
  opencos/commands/flist.py,sha256=OUu_ewTDLkZqdW4547iRrwOhT4ghm8oMYHsA63yChvo,8551
26
- opencos/commands/lec.py,sha256=gN6nQ4GURhPC8nu8Zuj08s1fmNzuiuaS9vJgtNZyX28,3647
27
- opencos/commands/multi.py,sha256=mBpsx6GaYyT_1KrOgiLu7303uYO5wyLVl56nrw1eiLw,27231
27
+ opencos/commands/lec.py,sha256=mIrMKFEZrFYIzvBdffcIyVULx04Cu4-480FB4Y1EiTA,3863
28
+ opencos/commands/multi.py,sha256=dCo4rMIkGT3BtlBhUIAd7r31w8qxeJvybpl4H7DR77o,27225
28
29
  opencos/commands/open.py,sha256=unrpGckzg0FE5W3oARq8x0jX7hhV_uM9Oh5FgISHFAg,724
29
30
  opencos/commands/proj.py,sha256=MdHTOtQYG93_gT97dWuSyAgUxX2vi9FRhL0dtc-rM98,1096
30
- opencos/commands/shell.py,sha256=senuqSGOc5nVGU5voZNJO4_hzVAK0ELtu0wmRZgwv3k,7463
31
- opencos/commands/sim.py,sha256=oZyc4thCWZAk4668bbehRBzbOOVQDhyoDyemlDwYPFg,14059
31
+ opencos/commands/shell.py,sha256=0SNxiNRPD1BO6dK0yxU_iV-8S9UyF4GOWGLL1A_KeVs,7583
32
+ opencos/commands/sim.py,sha256=WPkn_lZqgMPSQTxxT4Qa0qHKMmdHAkt1GXCDw4iD6kI,14723
32
33
  opencos/commands/sweep.py,sha256=ni4XFgnFF8HLXtwPhETyLWfvc2kgtm4bcxFcKzUhkf0,9343
33
34
  opencos/commands/synth.py,sha256=quB-HWS4LKYTiFBHiYarQi4pMnRmt12wQTZpi14VvlE,4355
34
35
  opencos/commands/targets.py,sha256=_jRNhm2Fqj0fmMvTw6Ba39DCsRHf_r_uZCy_R064kpA,1472
@@ -37,7 +38,7 @@ opencos/commands/waves.py,sha256=dsWwtjpDgH-YsiIjJgqTvteY3OZ48UnEAWc3blV2Fog,705
37
38
  opencos/deps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
39
  opencos/deps/defaults.py,sha256=4VgTRXf0hSJrj4tMk0t-mmvgEaaQQFDIYrxWrcKfYWk,1241
39
40
  opencos/deps/deps_commands.py,sha256=OlqueYFK8U83loasok3xJGzUDpNcj2DPk37332DfmRo,17039
40
- opencos/deps/deps_file.py,sha256=QvJ1fMyoQOXNbvHjWevkYF2kx0zvbRgFZ3GAPWw8jqk,12997
41
+ opencos/deps/deps_file.py,sha256=29UkOT-UYw5XYYRK7DySmZkgdTj4wnxVQ5SgZVnrrds,15199
41
42
  opencos/deps/deps_processor.py,sha256=NYGBrBAmk7ltrvxsEhv76Kpp76GBRJqeNNY_ckWf5mE,33028
42
43
  opencos/hw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
44
  opencos/hw/oc_cli.py,sha256=QBmf05VooB9kQFzgliak7PEvqVLTSEI3v6deV1OZQEs,132252
@@ -49,10 +50,10 @@ opencos/tests/test_build.py,sha256=FQAxOpLVQShAHD_L5rqJctPeSAoqoOCNFI0RXflLuY0,3
49
50
  opencos/tests/test_deps_helpers.py,sha256=f9GJXvzcdE3SGkKJ7q-YBTgRagZcIzeRa6nMVCCiEvI,7848
50
51
  opencos/tests/test_deps_schema.py,sha256=T3P9KjaMyKsk8b7snNVvNSsom2hIJcg6Z9apYiXoH9Y,941
51
52
  opencos/tests/test_eda.py,sha256=bg7SjSVCJSJ2lk51ddfjuVckMOps6_HU-3tCwAIRO7c,39198
52
- opencos/tests/test_eda_elab.py,sha256=ftW6eQG2KcqndpHK586gXZZs8mEKQedQw12tJ7tYGwQ,2640
53
+ opencos/tests/test_eda_elab.py,sha256=VyYiaLLyfJi26FkoN9p_Kb9cMHfY-0u_0Mx1iVpsg-I,2657
53
54
  opencos/tests/test_eda_synth.py,sha256=LOM8CKpNyjka_sKS2c00YObOAQeVgpRmuM12Bn-PHqU,5234
54
55
  opencos/tests/test_oc_cli.py,sha256=w-F-LjSSWVql3D2WG8tcV4_C52i-hL_2WT3oDpKQn9s,734
55
- opencos/tests/test_tools.py,sha256=-Wfvt6ARt2WLJ-9Yr88NlwmGWZhnw06Mfrv0100IGS8,5267
56
+ opencos/tests/test_tools.py,sha256=HEjKm86OMcrZznJMiiDFsDBN8FlBf4LR9egGO1pOh5c,5285
56
57
  opencos/tests/deps_files/command_order/DEPS.yml,sha256=vloOzWZ5qU3yGNFaDlrAJdEzYxK6qf8gfac3zqF-0FI,438
57
58
  opencos/tests/deps_files/error_msgs/DEPS.yml,sha256=fYvHouIscOlr8V28bqx9SoxRBpDBLX4AG-AkVXh8qbo,717
58
59
  opencos/tests/deps_files/iverilog_test/DEPS.yml,sha256=vDylEuLt642lhRSvOr3F5ziB5lhPSwkaUGN4_mWJw-c,40
@@ -65,24 +66,27 @@ opencos/tools/invio.py,sha256=q9E9n6xsozDfar-1rLvJEZbCpPb_bQEy6WKEI3KS3dk,3163
65
66
  opencos/tools/invio_helpers.py,sha256=1au4CYmV5aC7DHjaZBNemydH6Eq0i-Yt5L3HyKfQOfY,7638
66
67
  opencos/tools/invio_yosys.py,sha256=asSjbdPjBXB76KxNZIhoDRn2DoXKsZEQ1YDX_WBzKiA,6019
67
68
  opencos/tools/iverilog.py,sha256=KQV5tiRdM0ZuJOO0q3ZeUmhRyEc-oJggOc6RKIjoH84,6482
68
- opencos/tools/modelsim_ase.py,sha256=KQtvqBN7HdtsMl2MoMjaS29-_P5RsiB-ooVu1bC37LQ,13289
69
- opencos/tools/questa.py,sha256=AX_3USyf6eMcssH4b-8WLbCzz-cXYnQzlHvCyL9C7Og,7505
69
+ opencos/tools/modelsim_ase.py,sha256=rW5YrzLIhZKdbIT2UM60DGmDEHDK3XMlndpBz906cmA,14229
70
+ opencos/tools/questa.py,sha256=bXH_ajMUBBHNUeWTBNWDp2gGyza2vf8xIC6vz5EWiz8,7619
71
+ opencos/tools/questa_fse.py,sha256=WLNvkD57ggI7lQgxYr6h_xmXenh50J_m8o8amhECmpk,1855
70
72
  opencos/tools/riviera.py,sha256=0FKAUvgyUHvJ5z0LOjHV9p3dGF8LI5kj5WLOZXgCDas,10695
71
- opencos/tools/slang.py,sha256=bK1_EBA-3ZiUtlRMrMTVH58bhMpeipI87TIdB5O1NII,7456
73
+ opencos/tools/slang.py,sha256=mFw58vhnCTRR9yaQ2zHPlNB5HKSf3Y078XcaVnpLaAc,7798
72
74
  opencos/tools/slang_yosys.py,sha256=3fyLRRdTXhSppNtUhhUl00oG-cT9TyyPTH6JvasS9ZE,9804
73
75
  opencos/tools/surelog.py,sha256=dtj3ApAKoQasnGdg42n9DPgeqoJ5nCuurIkIO3G5ZCY,5011
74
76
  opencos/tools/tabbycad_yosys.py,sha256=2LePPgYXBVdsy7YcffPIWN-I0B7queLQ_f_pme2SCGw,7803
75
- opencos/tools/verilator.py,sha256=k5FMDyohNcJepElMRAoPSdq7r-zmZ6xG_cZb2XmCFb8,18411
76
- opencos/tools/vivado.py,sha256=a7bUINQDh74WGWUtfGEEH6M_7RgNyC8Yk4lBrkBXl2o,40168
77
- opencos/tools/yosys.py,sha256=5zn9CeJc6UUuBI1Gk7HD8Y_l4GPa4KcLB7NNYxIQBjY,25648
77
+ opencos/tools/verilator.py,sha256=h5VScZyJYxk2cXDRrTTD47C_yAVHuyXv9_p7UL1o5mk,19486
78
+ opencos/tools/vivado.py,sha256=roM0MxrHoNIT_DsUiql1vQFlez2ql4qhwAfB-rGH4Qg,40485
79
+ opencos/tools/yosys.py,sha256=UKWzvc2rSi3J9U2TROqRbmePdBmjskap664giumeRBk,26323
78
80
  opencos/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
79
- opencos/utils/markup_helpers.py,sha256=tDaDtV4INEg04Diks1ZXlfOwzyCOGnWqc5aeHnwLoOk,3727
81
+ opencos/utils/markup_helpers.py,sha256=A8Ev5UJ4EVKjdcF2g85SQbjdPZR4jGpNqCLaBy_4v7Q,4569
82
+ opencos/utils/status_constants.py,sha256=aQui30ohPCEaWNDh2iujJQ_KQa3plry_rk7uDzS3vWk,603
80
83
  opencos/utils/str_helpers.py,sha256=DOkwfKJR6aENM3U2BkJ41ELDU5Uj_zyhEfxuaQEcpEY,3352
81
84
  opencos/utils/subprocess_helpers.py,sha256=xemAGPey6M0sWY_FElvr-Z0phCfdjaC-znP8FKihPaE,3535
82
- opencos_eda-0.2.49.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
83
- opencos_eda-0.2.49.dist-info/licenses/LICENSE.spdx,sha256=8gn1610RMP6eFgT3Hm6q9VKXt0RvdTItL_oxMo72jII,189
84
- opencos_eda-0.2.49.dist-info/METADATA,sha256=gZQ8X2NXImdrTE6GBmQsaRHvrb5q99bVu2O9VnIpbd8,604
85
- opencos_eda-0.2.49.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
86
- opencos_eda-0.2.49.dist-info/entry_points.txt,sha256=hi6SZHiGGgLrI3KnBCOXDpYOGXYpw-zWBWe5Di39OCw,167
87
- opencos_eda-0.2.49.dist-info/top_level.txt,sha256=J4JDP-LpRyJqPNeh9bSjx6yrLz2Mk0h6un6YLmtqql4,8
88
- opencos_eda-0.2.49.dist-info/RECORD,,
85
+ opencos/utils/vsim_helper.py,sha256=2voGRZI2iAQ2Pv2ZI5g2why6xpgig-To8im-LVXtuDU,1517
86
+ opencos_eda-0.2.51.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
87
+ opencos_eda-0.2.51.dist-info/licenses/LICENSE.spdx,sha256=8gn1610RMP6eFgT3Hm6q9VKXt0RvdTItL_oxMo72jII,189
88
+ opencos_eda-0.2.51.dist-info/METADATA,sha256=XAX9j35DEWh0nLU7Gt8unosqGzK9dGeqHtGcj8IgK-8,604
89
+ opencos_eda-0.2.51.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
90
+ opencos_eda-0.2.51.dist-info/entry_points.txt,sha256=6n1T5NwVYDhN5l1h5zmyT197G4pE0SySDreB0QJzJR0,218
91
+ opencos_eda-0.2.51.dist-info/top_level.txt,sha256=J4JDP-LpRyJqPNeh9bSjx6yrLz2Mk0h6un6YLmtqql4,8
92
+ opencos_eda-0.2.51.dist-info/RECORD,,
@@ -1,5 +1,6 @@
1
1
  [console_scripts]
2
2
  eda = opencos.eda:main_cli
3
+ eda_deps_sanitize = opencos.eda_deps_sanitize:main
3
4
  eda_deps_schema = opencos.deps_schema:main
4
5
  eda_targets = opencos.eda_extract_targets:main
5
6
  oc_cli = opencos.hw.oc_cli:main