opencos-eda 0.2.57__py3-none-any.whl → 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
opencos/_version.py CHANGED
@@ -9,11 +9,14 @@ if sys.version_info >= (3, 8):
9
9
 
10
10
  from importlib import metadata
11
11
  try:
12
- VERSION = metadata.version(NAME)
12
+ ver = metadata.version(NAME)
13
13
  except metadata.PackageNotFoundError:
14
14
  # Handle case where the package is not installed (e.g., running from source checkout)
15
- VERSION = "0.0.0"
15
+ ver = "0.0.0"
16
16
 
17
17
  else:
18
18
  # This package only supports >= 3.8, so not doing the importlib_metadata method.
19
- VERSION = "unknown" # Or raise an error, or handle differently
19
+ ver = "unknown" # Or raise an error, or handle differently
20
+
21
+
22
+ VERSION = ver # pylint: disable=invalid-name
opencos/_waves_pkg.sv CHANGED
@@ -15,7 +15,7 @@ package _waves_pkg;
15
15
  bit trace_en_init = 0;
16
16
  bit trace_en = init_trace();
17
17
 
18
- function automatic bit init_trace();
18
+ function bit init_trace();
19
19
 
20
20
  if (trace_en_init) // only do this once.
21
21
  return trace_en;
@@ -41,7 +41,39 @@ package _waves_pkg;
41
41
 
42
42
  endfunction : init_trace
43
43
 
44
- `endif // #verilator
44
+ `elsif RIVIERA
45
+
46
+ bit trace_en_init = 0;
47
+ bit trace_en = init_trace();
48
+
49
+ // Note: must be non-automatic function for --tool=riviera
50
+ function bit init_trace();
51
+
52
+ if (trace_en_init) // only do this once.
53
+ return trace_en;
54
+
55
+ trace_en_init = 1;
56
+
57
+ if ($test$plusargs("trace") != 0) begin
58
+ automatic string trace_str_value = "";
59
+ void'($value$plusargs("trace=%s", trace_str_value));
60
+ if (trace_str_value.tolower() == "vcd") begin
61
+ $display("%t %m: Starting tracing to ./dump.vcd, plusarg +trace=%s",
62
+ $realtime, trace_str_value);
63
+ $dumpfile("dump.vcd");
64
+ $dumpvars();
65
+ return 1;
66
+ end
67
+ end
68
+
69
+ $display("%t %m: Starting tracing to ./dump.fst", $realtime);
70
+ $dumpfile("dump.fst");
71
+ $dumpvars();
72
+ return 1;
73
+
74
+ endfunction : init_trace
75
+
76
+ `endif
45
77
  `endif
46
78
  `endif
47
79
 
opencos/commands/build.py CHANGED
@@ -40,6 +40,7 @@ class CommandBuild(CommandDesign):
40
40
  self.create_work_dir()
41
41
  self.run_dep_commands()
42
42
  self.do_it()
43
+ self.run_post_tool_dep_commands()
43
44
  else:
44
45
  util.warning(f'CommandBuild: {self.command_name=} not run due to lack of',
45
46
  f'{self.args["top"]=} value')
@@ -50,6 +50,7 @@ class CommandExport(CommandDesign):
50
50
  self.create_work_dir()
51
51
  self.run_dep_commands()
52
52
  self.do_it()
53
+ self.run_post_tool_dep_commands()
53
54
  else:
54
55
  util.warning(f'CommandExport: {self.command_name=} not run due to lack of',
55
56
  f'{self.args["top"]=} value')
opencos/commands/flist.py CHANGED
@@ -227,3 +227,4 @@ class CommandFList(CommandDesign):
227
227
  util.info(f"Created file: {self.args['out']}")
228
228
 
229
229
  self.write_eda_config_and_args()
230
+ self.run_post_tool_dep_commands()
opencos/commands/lec.py CHANGED
@@ -100,6 +100,7 @@ class CommandLec(CommandDesign):
100
100
  self.create_work_dir()
101
101
  self.run_dep_commands()
102
102
  self.do_it()
103
+ self.run_post_tool_dep_commands()
103
104
  return unparsed
104
105
 
105
106
 
opencos/commands/proj.py CHANGED
@@ -37,5 +37,6 @@ class CommandProj(CommandDesign):
37
37
  self.create_work_dir()
38
38
  self.run_dep_commands()
39
39
  self.do_it()
40
+ self.run_post_tool_dep_commands()
40
41
 
41
42
  return unparsed
opencos/commands/shell.py CHANGED
@@ -58,6 +58,10 @@ class CommandShell(CommandDesign):
58
58
  self.create_work_dir()
59
59
  self.run_dep_commands()
60
60
  self.do_it()
61
+ self.run_post_tool_dep_commands()
62
+ else:
63
+ util.warning(f'CommandShell: {self.command_name=} not run due to lack of',
64
+ f'{self.args["top"]=} value')
61
65
  return unparsed
62
66
 
63
67
 
opencos/commands/sim.py CHANGED
@@ -63,6 +63,8 @@ class CommandSim(CommandDesign):
63
63
  'sim-args': [],
64
64
  'sim-plusargs': [], # lists are handled by 'set_arg(k,v)' so they append.
65
65
  'sim-library': [],
66
+ 'compile-waivers': [],
67
+ 'sim-waivers': [],
66
68
  'coverage': False,
67
69
  'waves': False,
68
70
  'waves-start': 0,
@@ -142,6 +144,7 @@ class CommandSim(CommandDesign):
142
144
  self.create_work_dir()
143
145
  self.run_dep_commands()
144
146
  self.do_it()
147
+ self.run_post_tool_dep_commands()
145
148
  return unparsed
146
149
 
147
150
 
@@ -400,7 +403,7 @@ class CommandSim(CommandDesign):
400
403
  '''
401
404
 
402
405
  all_lists = [] # list - of - (command-list)
403
- if self.has_dep_shell_commands:
406
+ if self.has_pre_compile_dep_shell_commands:
404
407
  all_lists = [
405
408
  ['./pre_compile_dep_shell_commands.sh']
406
409
  ]
@@ -423,6 +426,11 @@ class CommandSim(CommandDesign):
423
426
  line_breaks=simulate_line_breaks)
424
427
  all_lists.append(['./' + simulate_sh_fname])
425
428
 
429
+ if self.has_post_tool_dep_shell_commands:
430
+ all_lists = [
431
+ ['./post_tool_dep_shell_commands.sh']
432
+ ]
433
+
426
434
  util.write_shell_command_file(dirpath=self.args['work-dir'], filename='all.sh',
427
435
  command_lists=all_lists)
428
436
 
@@ -459,3 +467,41 @@ class CommandSim(CommandDesign):
459
467
  def get_post_simulate_command_lists(self, **kwargs) -> list:
460
468
  ''' Returns a list of lists (list of command lists).'''
461
469
  raise NotImplementedError
470
+
471
+ def add_waves_pkg_file(self) -> None:
472
+ '''If --waves is present, and one of --waves-fst or --waves-vcd or --dump-vcd, and
473
+
474
+ the user is missing any $dumpfile(), then adds a pre-written
475
+ SystemVerilog package to their source code. Note that individual tools have
476
+ to call this prior to their compile step, CommandSim does not run this method for
477
+ you.
478
+ '''
479
+ if not self.args['waves']:
480
+ return
481
+ if not any(self.args.get(x, False) for x in ('waves-fst', 'waves-vcd', 'dump-vcd')):
482
+ return
483
+ found_dumpfile = False
484
+ for fname in self.files_v + self.files_sv:
485
+ if found_dumpfile:
486
+ break
487
+ with open(fname, encoding='utf-8') as f:
488
+ for line in f.readlines():
489
+ if '$dumpfile' in line:
490
+ found_dumpfile = True
491
+ break
492
+
493
+ if not found_dumpfile:
494
+ thispath = os.path.dirname(__file__)
495
+ file_to_add = os.path.join(thispath, '..', '_waves_pkg.sv')
496
+ util.info(f'--waves arg present, no $dumpfile found, adding SV file: {file_to_add}')
497
+ self.add_file(file_to_add)
498
+
499
+ # register .vcd or .fst artifacts:
500
+ util.artifacts.add_extension(
501
+ search_paths=self.args['work-dir'], file_extension='fst',
502
+ typ='waveform', description='Simulation Waveform FST (Fast Signal Trace) file'
503
+ )
504
+ util.artifacts.add_extension(
505
+ search_paths=self.args['work-dir'], file_extension='vcd',
506
+ typ='waveform', description='Simulation Waveform VCD (Value Change Dump) file'
507
+ )
opencos/commands/synth.py CHANGED
@@ -73,6 +73,10 @@ class CommandSynth(CommandDesign):
73
73
  self.create_work_dir()
74
74
  self.run_dep_commands()
75
75
  self.do_it()
76
+ self.run_post_tool_dep_commands()
77
+ else:
78
+ util.warning(f'CommandSynth: {self.command_name=} not run due to lack of',
79
+ f'{self.args["top"]=} value')
76
80
  return unparsed
77
81
 
78
82
  def do_export(self):
opencos/deps/defaults.py CHANGED
@@ -59,14 +59,22 @@ SUPPORTED_TAG_KEYS = set([
59
59
  'additive-config-tools',
60
60
  ])
61
61
 
62
+ COMMAND_ATTRIBUTES = {
63
+ # with default values
64
+ 'run-from-work-dir': True,
65
+ 'filepath-subst-target-dir': True,
66
+
67
+ 'run-after-tool': False, # default is to run before any tool compile step.
68
+ 'dirpath-subst-target-dir': False,
69
+ 'var-subst-args': False,
70
+ 'var-subst-os-env': False,
71
+ 'tee': None,
72
+ }
73
+
62
74
  SUPPORTED_COMMAND_KEYS = set([
63
75
  'shell',
64
- 'work-dir-add-srcs', 'work-dir-add-sources',
65
76
  'peakrdl',
66
- 'run-from-work-dir', # default True
67
- 'filepath-subst-target-dir', # default True
68
- 'dirpath-subst-target-dir', # default False
69
- 'var-subst-args',
70
- 'var-subst-os-env',
71
- 'tee',
77
+ 'work-dir-add-srcs', 'work-dir-add-sources'
72
78
  ])
79
+ for key in COMMAND_ATTRIBUTES:
80
+ SUPPORTED_COMMAND_KEYS.add(key)
@@ -16,14 +16,14 @@ import re
16
16
  import shutil
17
17
 
18
18
  from opencos.util import debug, error, warning, ShellCommandList
19
- from opencos.deps.defaults import SUPPORTED_COMMAND_KEYS
19
+ from opencos.deps.defaults import SUPPORTED_COMMAND_KEYS, COMMAND_ATTRIBUTES
20
20
 
21
21
  THISPATH = os.path.dirname(__file__)
22
22
  PEAKRDL_CLEANUP_PY = os.path.join(THISPATH, '..', 'peakrdl_cleanup.py')
23
23
 
24
24
  def path_substitutions_relative_to_work_dir(
25
25
  exec_list: list, info_str: str, target_path: str,
26
- enable_filepath_subst: bool, enable_dirpath_subst: bool
26
+ attributes: dict
27
27
  ) -> list:
28
28
  '''For shell commands, since eda.py Command objects operate out of a "work-dir", it can
29
29
  make shell commands confusing with additional ../.. to get to the calling directory, and
@@ -38,7 +38,8 @@ def path_substitutions_relative_to_work_dir(
38
38
  dirpath-subst-target-dir: True)
39
39
  '''
40
40
 
41
- if not enable_filepath_subst and not enable_dirpath_subst:
41
+ if not attributes.get('filepath-subst-target-dir', True) and \
42
+ not attributes.get('dirpath-subst-target-dir', False):
42
43
  return exec_list
43
44
 
44
45
  # Look for path substitutions, b/c we later "work" in self.args['work-dir'], but
@@ -53,13 +54,15 @@ def path_substitutions_relative_to_work_dir(
53
54
  # self.args['work-dir'] don't need this, and we can't assume dir levels in the work-dir.
54
55
  try:
55
56
  try_path = os.path.abspath(os.path.join(os.path.abspath(target_path), m.group(1)))
56
- if enable_filepath_subst and os.path.isfile(try_path):
57
+ if attributes.get('filepath-subst-target-dir', True) and \
58
+ os.path.isfile(try_path):
57
59
  # make the substitution
58
60
  exec_list[i] = word.replace(m.group(1), try_path)
59
61
  debug(f'file path substitution {info_str=} {target_path=}: replaced - {word=}'
60
62
  f'is now ={exec_list[i]}. This can be disabled in DEPS with:',
61
63
  '"filepath-subst-targetdir: false"')
62
- elif enable_dirpath_subst and os.path.isdir(try_path):
64
+ elif attributes.get('dirpath-subst-target-dir', False) and \
65
+ os.path.isdir(try_path):
63
66
  # make the substitution
64
67
  exec_list[i] = word.replace(m.group(1), try_path)
65
68
  debug(f'dir path substitution {info_str=} {target_path=}: replaced - {word=}'
@@ -84,12 +87,7 @@ def line_with_var_subst( # pylint: disable=dangerous-default-value
84
87
  if '{' not in line:
85
88
  return line
86
89
 
87
- if replace_vars_os_env:
88
- replace_dict = {}
89
- replace_dict.update(os.environ)
90
- replace_dict.update(replace_vars_dict)
91
- else:
92
- replace_dict = replace_vars_dict
90
+ replace_dict = replace_vars_dict
93
91
 
94
92
  words = line.split()
95
93
  for i,word in enumerate(words):
@@ -100,6 +98,13 @@ def line_with_var_subst( # pylint: disable=dangerous-default-value
100
98
  pass
101
99
 
102
100
  new_line = ' '.join(words)
101
+
102
+ if replace_vars_os_env:
103
+ try:
104
+ new_line = os.path.expandvars(new_line)
105
+ except Exception as e:
106
+ warning(f'{e}: trying to apply env vars to line: {new_line}')
107
+
103
108
  if new_line != line:
104
109
  debug(f'{target_node=} {target_path=} performed string format replacement,',
105
110
  f'{line=} {new_line=}')
@@ -112,8 +117,7 @@ def line_with_var_subst( # pylint: disable=dangerous-default-value
112
117
 
113
118
  def parse_deps_shell_str(
114
119
  line: str, target_path: str, target_node: str,
115
- enable_filepath_subst_target_dir: bool = True,
116
- enable_dirpath_subst_target_dir: bool = False,
120
+ attributes: dict,
117
121
  enable: bool = True
118
122
  ) -> dict:
119
123
  '''Returns None or a dict of a possible shell command from line (str)
@@ -146,20 +150,21 @@ def parse_deps_shell_str(
146
150
  # Note this can be disable in DEPS via path-subst-target-dir=False
147
151
  exec_list = path_substitutions_relative_to_work_dir(
148
152
  exec_list=exec_list, info_str='shell@', target_path=target_path,
149
- enable_filepath_subst=enable_filepath_subst_target_dir,
150
- enable_dirpath_subst=enable_dirpath_subst_target_dir
153
+ attributes=attributes
151
154
  )
152
155
 
153
156
  return {
154
157
  'target_path': os.path.abspath(target_path),
155
158
  'target_node': target_node,
156
- 'run_from_work_dir': True, # may be overriden later.
157
159
  'exec_list': exec_list,
160
+ 'attributes': attributes
158
161
  }
159
162
 
160
163
 
161
164
  def parse_deps_work_dir_add_srcs(
162
- line : str, target_path : str, target_node : str, enable : bool = True
165
+ line : str, target_path : str, target_node : str,
166
+ attributes: dict,
167
+ enable : bool = True
163
168
  ) -> dict:
164
169
  '''Returns None or a dict describing source files to add from the work-dir path
165
170
 
@@ -182,17 +187,19 @@ def parse_deps_work_dir_add_srcs(
182
187
  files_str = m.group(1)
183
188
  file_list = files_str.split()
184
189
 
185
- d = {'target_path': os.path.abspath(target_path),
186
- 'target_node': target_node,
187
- 'file_list': file_list,
188
- }
190
+ d = {
191
+ 'target_path': os.path.abspath(target_path),
192
+ 'target_node': target_node,
193
+ 'file_list': file_list,
194
+ 'attributes': attributes
195
+ }
189
196
  return d
190
197
 
191
198
 
192
199
  def parse_deps_peakrdl( # pylint: disable=too-many-locals
193
- line: str, target_path: str, target_node: str, enable: bool = True,
194
- enable_filepath_subst_target_dir: bool = True,
195
- enable_dirpath_subst_target_dir: bool = False
200
+ line: str, target_path: str, target_node: str,
201
+ attributes: dict,
202
+ enable: bool = True
196
203
  ) -> dict:
197
204
  '''Returns None or a dict describing a PeakRDL CSR register generator dependency
198
205
 
@@ -268,16 +275,16 @@ def parse_deps_peakrdl( # pylint: disable=too-many-locals
268
275
  line=(' shell@ ' + ' '.join(one_cmd_as_list)),
269
276
  target_path=target_path,
270
277
  target_node=target_node,
271
- enable_filepath_subst_target_dir=enable_filepath_subst_target_dir,
272
- enable_dirpath_subst_target_dir=enable_dirpath_subst_target_dir
278
+ attributes=attributes
273
279
  )
274
280
  )
275
281
 
276
282
  # Make the work_dir_add_srcs dict:
277
283
  ret_dict['work_dir_add_srcs'] = parse_deps_work_dir_add_srcs(
278
- line = ' work_dir_add_srcs@ ' + ' '.join(sv_files),
279
- target_path = target_path,
280
- target_node = target_node
284
+ line=' work_dir_add_srcs@ ' + ' '.join(sv_files),
285
+ target_path=target_path,
286
+ target_node=target_node,
287
+ attributes=attributes
281
288
  )
282
289
 
283
290
  return ret_dict
@@ -329,65 +336,69 @@ def deps_commands_handler( #pylint: disable=too-many-locals,too-many-branches
329
336
  error(f'deps_commands.process_commands - command {key=} not in',
330
337
  f'{SUPPORTED_COMMAND_KEYS=}')
331
338
 
339
+ # collect attributes for this command:
340
+ attributes = {}
341
+ for key, default_value in COMMAND_ATTRIBUTES.items():
342
+ attributes[key] = command.get(key, default_value)
343
+
332
344
  var_subst_dict = {} # this is per-command.
333
- if config['dep_command_enables'].get('var_subst_os_env', False) and \
334
- command.get('var-subst-os-env', False):
335
- var_subst_dict.update(dict(os.environ))
336
345
  if config['dep_command_enables'].get('var_subst_args', False) and \
337
- command.get('var-subst-args', False):
346
+ attributes['var-subst-args']:
338
347
  var_subst_dict = eda_args
339
348
 
340
- tee_fpath = command.get('tee', None)
341
-
342
- # These are both optional bools, default True, would have to explicitly be set to False
343
- # to take effect:
344
- run_from_work_dir = command.get('run-from-work-dir', True)
345
- filepath_subst_target_dir = command.get('filepath-subst-target-dir', True)
346
- dirpath_subst_target_dir = command.get('dirpath-subst-target-dir', False)
347
-
348
349
  for key,item in command.items():
349
350
 
350
351
  # skip the tee and var-subst-* keys, since these types are bools and not commands.
351
- if key in ['tee',
352
- 'var-subst-os-env',
353
- 'var-subst-args',
354
- 'run-from-work-dir',
355
- 'filepath-subst-target-dir',
356
- 'dirpath-subst-target-dir']:
352
+ if key in COMMAND_ATTRIBUTES:
357
353
  continue
358
354
 
359
355
  # Optional variable substituion in commands
360
356
  if isinstance(item, str):
361
- item = line_with_var_subst(item, replace_vars_dict=var_subst_dict,
362
- target_node=target_node, target_path=deps_file)
357
+ item = line_with_var_subst(
358
+ line=item,
359
+ replace_vars_dict=var_subst_dict,
360
+ replace_vars_os_env=attributes['var-subst-os-env'],
361
+ target_node=target_node,
362
+ target_path=deps_file
363
+ )
363
364
 
364
365
  if key == 'shell':
365
366
  # For now, piggyback on parse_deps_shell_str:
366
- ret_dict = parse_deps_shell_str(
367
- line=('shell@ ' + item),
368
- target_path=target_path,
369
- target_node=target_node,
370
- enable_filepath_subst_target_dir=filepath_subst_target_dir,
371
- enable_dirpath_subst_target_dir=dirpath_subst_target_dir,
372
- enable=config['dep_command_enables']['shell'],
373
- )
374
- # To support 'tee: <some-file>' need to append it to last
375
- # list item in ret_dict['exec_list'], and make it a util.ShellCommandList.
376
- if tee_fpath:
377
- ret_dict['exec_list'] = ShellCommandList(
378
- ret_dict['exec_list'], tee_fpath=tee_fpath
367
+
368
+ # If our shell commands have \n in them, split the commands.
369
+ item = item.replace('\\\n', ' ') # but not \ + newline
370
+
371
+ for shell_line in item.split('\n'):
372
+
373
+ shell_line = shell_line.strip()
374
+ if not shell_line:
375
+ continue
376
+
377
+ ret_dict = parse_deps_shell_str(
378
+ line=('shell@ ' + shell_line),
379
+ target_path=target_path,
380
+ target_node=target_node,
381
+ attributes=attributes,
382
+ enable=config['dep_command_enables']['shell'],
379
383
  )
380
- ret_dict['run_from_work_dir'] = run_from_work_dir
381
- assert ret_dict, f'shell command failed in {dep=} {target_node=} in {deps_file=}'
382
- shell_commands_list.append(ret_dict) # process this later, append to ret tuple
384
+ # To support 'tee: <some-file>' need to append it to last
385
+ # list item in ret_dict['exec_list'], and make it a util.ShellCommandList.
386
+ if attributes['tee']:
387
+ ret_dict['exec_list'] = ShellCommandList(
388
+ ret_dict['exec_list'], tee_fpath=attributes['tee']
389
+ )
390
+ assert ret_dict, \
391
+ f'shell command failed in {dep=} {target_node=} in {deps_file=}'
392
+ shell_commands_list.append(ret_dict) # process this later, append to ret tuple
383
393
 
384
394
  elif key in ['work-dir-add-srcs', 'work-dir-add-sources']:
385
395
  # For now, piggyback on parse_deps_work_dir_add_srcs:
386
396
  ret_dict = parse_deps_work_dir_add_srcs(
387
- line = 'work_dir_add_srcs@ ' + item,
388
- target_path = target_path,
389
- target_node = target_node,
397
+ line='work_dir_add_srcs@ ' + item,
398
+ target_path=target_path,
399
+ target_node=target_node,
390
400
  enable=config['dep_command_enables']['work_dir_add_srcs'],
401
+ attributes=attributes,
391
402
  )
392
403
  assert ret_dict, \
393
404
  f'work-dir-add-srcs command failed in {dep=} {target_node=} in {deps_file=}'
@@ -397,12 +408,11 @@ def deps_commands_handler( #pylint: disable=too-many-locals,too-many-branches
397
408
  elif key == 'peakrdl':
398
409
  # for now, piggyback on parse_deps_peakrdl:
399
410
  ret_dict = parse_deps_peakrdl(
400
- line = 'peakrdl@ ' + item,
401
- target_path = target_path,
402
- target_node = target_node,
403
- enable_filepath_subst_target_dir=filepath_subst_target_dir,
404
- enable_dirpath_subst_target_dir=dirpath_subst_target_dir,
405
- enable=config['dep_command_enables']['peakrdl']
411
+ line='peakrdl@ ' + item,
412
+ target_path=target_path,
413
+ target_node=target_node,
414
+ enable=config['dep_command_enables']['peakrdl'],
415
+ attributes=attributes
406
416
  )
407
417
  assert ret_dict, f'peakrdl command failed in {dep=} {target_node=} in {deps_file=}'
408
418
 
opencos/deps_schema.py CHANGED
@@ -85,6 +85,8 @@ my_target_name:
85
85
  directory path substitution relative to target dir
86
86
  (if substituted directory exists).
87
87
  tee: <---- string, filename to write logs to
88
+ run-after-tool: <---- bool, default false. Set to true to run after any
89
+ EDA tools, or any command handlers have completed.
88
90
  - work-dir-add-sources: <---- work-dir-add-sources, optional list (or string)
89
91
  - some_file_gen_from_sh.sv <---- string filename that we created with sh command
90
92
  - peakrdl: <---- string peakrdl command for CSR generation
@@ -171,6 +173,7 @@ DEPS_COMMANDS_LIST = [
171
173
  Optional('var-subst-args'): bool,
172
174
  Optional('var-subst-os-env'): bool,
173
175
  Optional('run-from-work-dir'): bool,
176
+ Optional('run-after-tool'): bool,
174
177
  Optional('filepath-subst-target-dir'): bool,
175
178
  Optional('dirpath-subst-target-dir'): bool,
176
179
  Optional('tee'): Or(str, type(None)),
opencos/eda.py CHANGED
@@ -520,7 +520,8 @@ def main(*args):
520
520
 
521
521
  original_args = args.copy() # save before any parsing.
522
522
 
523
- # Set global --debug, --quiet, --color early before parsing other args:
523
+ # Set global --debug, --quiet, --color, -f/--iput-file, --envfile
524
+ # early before parsing other args:
524
525
  util_parsed, unparsed = util.process_tokens(args)
525
526
 
526
527
  util.debug(f"main: file: {os.path.realpath(__file__)}")