opencos-eda 0.3.0__py3-none-any.whl → 0.3.1__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/deps/deps_file.py +11 -5
- opencos/deps/deps_processor.py +79 -3
- opencos/eda_base.py +44 -18
- opencos/eda_config_defaults.yml +3 -0
- opencos/files.py +1 -0
- opencos/tests/helpers.py +2 -1
- opencos/util.py +52 -8
- {opencos_eda-0.3.0.dist-info → opencos_eda-0.3.1.dist-info}/METADATA +1 -1
- {opencos_eda-0.3.0.dist-info → opencos_eda-0.3.1.dist-info}/RECORD +14 -14
- {opencos_eda-0.3.0.dist-info → opencos_eda-0.3.1.dist-info}/WHEEL +0 -0
- {opencos_eda-0.3.0.dist-info → opencos_eda-0.3.1.dist-info}/entry_points.txt +0 -0
- {opencos_eda-0.3.0.dist-info → opencos_eda-0.3.1.dist-info}/licenses/LICENSE +0 -0
- {opencos_eda-0.3.0.dist-info → opencos_eda-0.3.1.dist-info}/licenses/LICENSE.spdx +0 -0
- {opencos_eda-0.3.0.dist-info → opencos_eda-0.3.1.dist-info}/top_level.txt +0 -0
opencos/deps/deps_file.py
CHANGED
|
@@ -287,7 +287,9 @@ class DepsFile:
|
|
|
287
287
|
f'{targets_str}'))
|
|
288
288
|
|
|
289
289
|
|
|
290
|
-
def lookup(
|
|
290
|
+
def lookup( # pylint: disable=too-many-branches
|
|
291
|
+
self, target_node: str, caller_info: str
|
|
292
|
+
) -> bool:
|
|
291
293
|
'''Returns True if the target_node is in the DEPS markup file. If not, error with
|
|
292
294
|
|
|
293
295
|
some caller_info(str). This is more useful for YAML or TOML markup where we have
|
|
@@ -295,16 +297,20 @@ class DepsFile:
|
|
|
295
297
|
'''
|
|
296
298
|
if target_node not in self.data:
|
|
297
299
|
found_target = False
|
|
298
|
-
# For error printing, prefer relative paths:
|
|
299
|
-
t_path = os.path.relpath(self.target_path) + os.path.sep
|
|
300
|
-
t_node = target_node
|
|
301
|
-
t_full = os.path.join(t_path, t_node)
|
|
302
300
|
|
|
303
301
|
if target_node.startswith('-'):
|
|
304
302
|
# likely an unparsed arg that made it this far.
|
|
305
303
|
util.warning(f"Ignoring unparsed argument '{target_node}'")
|
|
306
304
|
return False
|
|
307
305
|
|
|
306
|
+
# For error printing, prefer relative paths:
|
|
307
|
+
if self.target_path:
|
|
308
|
+
t_path = os.path.relpath(self.target_path) + os.path.sep
|
|
309
|
+
else:
|
|
310
|
+
t_path = ''
|
|
311
|
+
t_node = target_node
|
|
312
|
+
t_full = os.path.join(t_path, t_node)
|
|
313
|
+
|
|
308
314
|
if not is_valid_target_name(target_node):
|
|
309
315
|
util.warning(
|
|
310
316
|
f"In file {self.rel_deps_file}, {target_node} {VALID_TARGET_INFO_STR}"
|
opencos/deps/deps_processor.py
CHANGED
|
@@ -4,11 +4,13 @@ a DEPS markup files targets (applying deps, reqs, commands, tags, incdirs, defin
|
|
|
4
4
|
CommandDesign ref object
|
|
5
5
|
'''
|
|
6
6
|
|
|
7
|
+
import argparse
|
|
7
8
|
import os
|
|
8
9
|
|
|
9
10
|
from opencos import files
|
|
10
11
|
from opencos import eda_config
|
|
11
|
-
from opencos.util import debug, info, warning, error
|
|
12
|
+
from opencos.util import debug, info, warning, error, read_tokens_from_dot_f, \
|
|
13
|
+
patch_args_for_dir
|
|
12
14
|
from opencos.utils.str_helpers import dep_str2list
|
|
13
15
|
from opencos.deps.deps_file import deps_target_get_deps_list
|
|
14
16
|
from opencos.deps.deps_commands import deps_commands_handler
|
|
@@ -48,6 +50,7 @@ class DepsProcessor: # pylint: disable=too-many-instance-attributes
|
|
|
48
50
|
self.target_path = target_path
|
|
49
51
|
self.target_node = target_node # for debug
|
|
50
52
|
self.deps_file = deps_file # for debug
|
|
53
|
+
self.deps_dir, _ = os.path.split(deps_file)
|
|
51
54
|
self.caller_info = caller_info
|
|
52
55
|
|
|
53
56
|
assert isinstance(deps_entry, dict), \
|
|
@@ -150,7 +153,9 @@ class DepsProcessor: # pylint: disable=too-many-instance-attributes
|
|
|
150
153
|
return tokens
|
|
151
154
|
|
|
152
155
|
|
|
153
|
-
def apply_args(
|
|
156
|
+
def apply_args( # pylint: disable=too-many-locals,too-many-branches
|
|
157
|
+
self, args_list:list
|
|
158
|
+
) -> list:
|
|
154
159
|
'''Given args_list, applies them to our self.command_design_ref obj
|
|
155
160
|
|
|
156
161
|
This will return unparsed args that weren't in the self.command_design_ref.args keys
|
|
@@ -162,10 +167,54 @@ class DepsProcessor: # pylint: disable=too-many-instance-attributes
|
|
|
162
167
|
f"in {self.caller_info}")
|
|
163
168
|
tokens = dep_str2list(args_list)
|
|
164
169
|
|
|
170
|
+
# patch args relative to the DEPS (if self.deps_dir exists) so things like
|
|
171
|
+
# --build-tcl=<file> for relative <file> works when calling targets from any directory.
|
|
172
|
+
tokens = patch_args_for_dir(
|
|
173
|
+
tokens=tokens, patch_dir=self.deps_dir, caller_info=self.caller_info
|
|
174
|
+
)
|
|
175
|
+
|
|
165
176
|
# We're going to run an ArgumentParser here, which is not the most efficient
|
|
166
177
|
# thing to do b/c it runs on all of self.command_design_ref.args (dict) even
|
|
167
178
|
# if we're applying a single token.
|
|
168
179
|
|
|
180
|
+
# Since some args (util.py, eda_config.py, eda.py) can only be handled from command
|
|
181
|
+
# line, it would be nice if -f or --input-file is handled from DEPS, so we'll special
|
|
182
|
+
# case that now. Recursively resolve -f / --input-file.
|
|
183
|
+
parser = argparse.ArgumentParser(
|
|
184
|
+
prog='deps_processor -f/--input-file', add_help=False, allow_abbrev=False
|
|
185
|
+
)
|
|
186
|
+
parser.add_argument('-f', '--input-file', default=[], action='append',
|
|
187
|
+
help=(
|
|
188
|
+
'Input .f file to be expanded as eda args, defines, incdirs,'
|
|
189
|
+
' files, or targets.'
|
|
190
|
+
))
|
|
191
|
+
try:
|
|
192
|
+
parsed, unparsed = parser.parse_known_args(tokens + [''])
|
|
193
|
+
tokens2 = list(filter(None, unparsed))
|
|
194
|
+
except argparse.ArgumentError:
|
|
195
|
+
error('deps_processor -f/--input-file, problem attempting to parse_known_args for:',
|
|
196
|
+
f'{tokens}')
|
|
197
|
+
tokens2 = tokens
|
|
198
|
+
|
|
199
|
+
if parsed.input_file:
|
|
200
|
+
dotf_tokens = []
|
|
201
|
+
for filepath in parsed.input_file:
|
|
202
|
+
# Since this isn't command line, we have to assume the path is relative
|
|
203
|
+
# to this DEPS file.
|
|
204
|
+
if not os.path.isabs(filepath):
|
|
205
|
+
filepath = os.path.join(self.deps_dir, filepath)
|
|
206
|
+
dotf_tokens.extend(read_tokens_from_dot_f(
|
|
207
|
+
filepath=filepath, caller_info=self.caller_info, verbose=True
|
|
208
|
+
))
|
|
209
|
+
|
|
210
|
+
# put the .f files before the unparsed args.
|
|
211
|
+
tokens2 = dotf_tokens + tokens2
|
|
212
|
+
|
|
213
|
+
# recurse until we've resolved nested .f files.
|
|
214
|
+
return self.apply_args(args_list=tokens2)
|
|
215
|
+
|
|
216
|
+
tokens = tokens2 # if no --input-file values, keep parsing the remaining tokens2
|
|
217
|
+
|
|
169
218
|
# We have to special-case anything with --tool[=value] in tokens, otherwise
|
|
170
219
|
# the user may think they were allowed to set --tool, but in our flow the Command handler
|
|
171
220
|
# (self.command_design_ref) has already been chosen, so setting the tool can have
|
|
@@ -180,11 +229,38 @@ class DepsProcessor: # pylint: disable=too-many-instance-attributes
|
|
|
180
229
|
_, unparsed = self.command_design_ref.run_argparser_on_list(
|
|
181
230
|
tokens=tokens
|
|
182
231
|
)
|
|
232
|
+
|
|
183
233
|
# Annoying, but check for plusargs in unparsed, and have referenced CommandDesign
|
|
184
234
|
# or CommandSim class handle it with process_plusarg.
|
|
185
|
-
for arg in unparsed:
|
|
235
|
+
for arg in list(unparsed):
|
|
186
236
|
if arg.startswith('+'):
|
|
187
237
|
self.command_design_ref.process_plusarg(plusarg=arg, pwd=self.target_path)
|
|
238
|
+
unparsed.remove(arg)
|
|
239
|
+
|
|
240
|
+
# For any leftover files, or targets, attempt to process those too:
|
|
241
|
+
for arg in list(unparsed):
|
|
242
|
+
# Since this isn't command line, we have to assume for files, the path is relative
|
|
243
|
+
# to this DEPS file.
|
|
244
|
+
if os.path.isabs(arg):
|
|
245
|
+
target = arg
|
|
246
|
+
else:
|
|
247
|
+
target = os.path.join(self.deps_dir, arg)
|
|
248
|
+
|
|
249
|
+
file_exists, fpath, forced_extension = files.get_source_file(target)
|
|
250
|
+
if file_exists:
|
|
251
|
+
_, file_ext = os.path.splitext(fpath)
|
|
252
|
+
if forced_extension or file_ext:
|
|
253
|
+
self.command_design_ref.add_file(fpath, caller_info=self.caller_info,
|
|
254
|
+
forced_extension=forced_extension)
|
|
255
|
+
unparsed.remove(arg)
|
|
256
|
+
|
|
257
|
+
else:
|
|
258
|
+
if not os.path.isdir(target) and \
|
|
259
|
+
self.command_design_ref.resolve_target_core(
|
|
260
|
+
target=target, no_recursion=False, caller_info=self.caller_info,
|
|
261
|
+
error_on_not_found=False
|
|
262
|
+
):
|
|
263
|
+
unparsed.remove(arg)
|
|
188
264
|
|
|
189
265
|
if unparsed:
|
|
190
266
|
# This is only a warning - because things like CommandFlist may not have every
|
opencos/eda_base.py
CHANGED
|
@@ -230,6 +230,7 @@ class Command: # pylint: disable=too-many-public-methods
|
|
|
230
230
|
'enable-tags': [],
|
|
231
231
|
'disable-tags': [],
|
|
232
232
|
'test-mode': False,
|
|
233
|
+
'error-unknown-args': True,
|
|
233
234
|
})
|
|
234
235
|
self.args_help.update({
|
|
235
236
|
'stop-before-compile': ('stop this run before any compile (if possible for tool) and'
|
|
@@ -249,6 +250,7 @@ class Command: # pylint: disable=too-many-public-methods
|
|
|
249
250
|
' --disable-tags has higher precedence than --enable-tags.'),
|
|
250
251
|
'test-mode': ('command and tool dependent, usually stops the command early without'
|
|
251
252
|
' executing.'),
|
|
253
|
+
'error-unknown-args': 'Enable errors on unknown/unparsable args',
|
|
252
254
|
})
|
|
253
255
|
self.modified_args = {}
|
|
254
256
|
self.config = copy.deepcopy(config) # avoid external modifications.
|
|
@@ -495,9 +497,10 @@ class Command: # pylint: disable=too-many-public-methods
|
|
|
495
497
|
|
|
496
498
|
# Do some minimal type handling, preserving the type(self.args[key])
|
|
497
499
|
if key not in self.args:
|
|
498
|
-
self.
|
|
499
|
-
|
|
500
|
-
|
|
500
|
+
self.error_unknown_arg(
|
|
501
|
+
f'set_arg, {key=} not in self.args {value=}',
|
|
502
|
+
f'({self.command_name=}, {self.__class__.__name__=})'
|
|
503
|
+
)
|
|
501
504
|
|
|
502
505
|
cur_value = self.args[key]
|
|
503
506
|
|
|
@@ -692,9 +695,10 @@ class Command: # pylint: disable=too-many-public-methods
|
|
|
692
695
|
_, unparsed = self.run_argparser_on_list(tokens)
|
|
693
696
|
if process_all and unparsed:
|
|
694
697
|
self.warning_show_known_args()
|
|
695
|
-
self.
|
|
696
|
-
|
|
697
|
-
|
|
698
|
+
self.error_unknown_arg(
|
|
699
|
+
f"Didn't understand argument: '{unparsed=}' in",
|
|
700
|
+
f"{self.command_name=} context, {pwd=}"
|
|
701
|
+
)
|
|
698
702
|
|
|
699
703
|
return unparsed
|
|
700
704
|
|
|
@@ -910,6 +914,16 @@ class Command: # pylint: disable=too-many-public-methods
|
|
|
910
914
|
lines.append(self.pretty_str_known_args(command=commands[-1])) # use last command if > 1
|
|
911
915
|
util.warning("\n".join(lines))
|
|
912
916
|
|
|
917
|
+
def error_unknown_arg(self, *msg) -> None:
|
|
918
|
+
'''For errors involving an unknown --arg, they can be optionally disabled
|
|
919
|
+
|
|
920
|
+
using --no-error-unknown-args
|
|
921
|
+
'''
|
|
922
|
+
if self.args['error-unknown-args']:
|
|
923
|
+
self.error(*msg, error_code=status_constants.EDA_COMMAND_OR_ARGS_ERROR)
|
|
924
|
+
else:
|
|
925
|
+
util.warning(*msg)
|
|
926
|
+
|
|
913
927
|
|
|
914
928
|
class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
915
929
|
'''CommandDesign is the eda base class for command handlers that need to track files.
|
|
@@ -1392,7 +1406,8 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1392
1406
|
return self.resolve_target_core(target, no_recursion, caller_info)
|
|
1393
1407
|
|
|
1394
1408
|
def resolve_target_core( # pylint: disable=too-many-locals,too-many-branches
|
|
1395
|
-
self, target: str, no_recursion: bool, caller_info: str = ''
|
|
1409
|
+
self, target: str, no_recursion: bool, caller_info: str = '',
|
|
1410
|
+
error_on_not_found: bool = True
|
|
1396
1411
|
) -> bool:
|
|
1397
1412
|
'''Returns True if target is found. recursive point for resolving path or DEPS markup
|
|
1398
1413
|
target names.'''
|
|
@@ -1481,14 +1496,14 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1481
1496
|
self.add_file(try_file, caller_info=f'n/a::{target}::n/a')
|
|
1482
1497
|
found_target = True
|
|
1483
1498
|
break # move on to the next target
|
|
1484
|
-
if not found_target: # if STILL not found_this_target...
|
|
1499
|
+
if not found_target and error_on_not_found: # if STILL not found_this_target...
|
|
1485
1500
|
self.error(f"Unable to resolve {target=}",
|
|
1486
1501
|
error_code=status_constants.EDA_DEPS_TARGET_NOT_FOUND)
|
|
1487
1502
|
|
|
1488
1503
|
# if we've found any target since being called, it means we found the one we were called for
|
|
1489
1504
|
return found_target
|
|
1490
1505
|
|
|
1491
|
-
def add_file(
|
|
1506
|
+
def add_file( # pylint: disable=too-many-locals,too-many-branches
|
|
1492
1507
|
self, filename: str, use_abspath: bool = True, add_to_non_sources: bool = False,
|
|
1493
1508
|
caller_info: str = '', forced_extension: str = ''
|
|
1494
1509
|
) -> str:
|
|
@@ -1512,6 +1527,7 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1512
1527
|
vhdl_file_ext_list = known_file_ext_dict.get('vhdl', [])
|
|
1513
1528
|
cpp_file_ext_list = known_file_ext_dict.get('cpp', [])
|
|
1514
1529
|
sdc_file_ext_list = known_file_ext_dict.get('synth_constraints', [])
|
|
1530
|
+
dotf_file_ext_list = known_file_ext_dict.get('dotf', [])
|
|
1515
1531
|
|
|
1516
1532
|
if forced_extension:
|
|
1517
1533
|
# If forced_extension='systemverilog', then use the first known extension for
|
|
@@ -1544,6 +1560,13 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1544
1560
|
elif file_ext in sdc_file_ext_list:
|
|
1545
1561
|
self.files_sdc.append(file_abspath)
|
|
1546
1562
|
util.debug(f"Added SDC file {filename} as {file_abspath}")
|
|
1563
|
+
elif file_ext in dotf_file_ext_list:
|
|
1564
|
+
# a stray .f file as a source file, sure why not support it:
|
|
1565
|
+
dp = DepsProcessor(command_design_ref=self, deps_entry={}, target='',
|
|
1566
|
+
target_path='', target_node='', deps_file='',
|
|
1567
|
+
caller_info=caller_info)
|
|
1568
|
+
dp.apply_args(args_list=[f'-f={file_abspath}'])
|
|
1569
|
+
del dp
|
|
1547
1570
|
else:
|
|
1548
1571
|
# unknown file extension. In these cases we link the file to the working directory
|
|
1549
1572
|
# so it is available (for example, a .mem file that is expected to exist with relative
|
|
@@ -1637,9 +1660,10 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1637
1660
|
if process_all and possible_unparsed_args:
|
|
1638
1661
|
_tool = self.safe_which_tool()
|
|
1639
1662
|
self.warning_show_known_args()
|
|
1640
|
-
self.
|
|
1641
|
-
|
|
1642
|
-
|
|
1663
|
+
self.error_unknown_arg(
|
|
1664
|
+
f"Didn't understand unparsed args: {possible_unparsed_args}, for command",
|
|
1665
|
+
f"'{self.command_name}', tool '{_tool}'"
|
|
1666
|
+
)
|
|
1643
1667
|
|
|
1644
1668
|
remove_list = []
|
|
1645
1669
|
last_potential_top_file = ('', '') # (top, fpath)
|
|
@@ -1697,9 +1721,10 @@ class CommandDesign(Command): # pylint: disable=too-many-instance-attributes
|
|
|
1697
1721
|
# we were unable to figure out what this command line token is for...
|
|
1698
1722
|
if process_all and unparsed:
|
|
1699
1723
|
self.warning_show_known_args()
|
|
1700
|
-
self.
|
|
1701
|
-
|
|
1702
|
-
|
|
1724
|
+
self.error_unknown_arg(
|
|
1725
|
+
f"Didn't understand remaining args or targets {unparsed=} for command",
|
|
1726
|
+
f"'{self.command_name}'"
|
|
1727
|
+
)
|
|
1703
1728
|
|
|
1704
1729
|
# handle a missing self.args['top'] with last filepath or last target:
|
|
1705
1730
|
if not self.args.get('top', ''):
|
|
@@ -2244,9 +2269,10 @@ class CommandParallel(Command):
|
|
|
2244
2269
|
bad_remaining_args = [x for x in single_cmd_unparsed if x.startswith('-')]
|
|
2245
2270
|
if bad_remaining_args:
|
|
2246
2271
|
self.warning_show_known_args(command=f'{self.command_name} {command}')
|
|
2247
|
-
self.
|
|
2248
|
-
|
|
2249
|
-
|
|
2272
|
+
self.error_unknown_arg(
|
|
2273
|
+
f'for {self.command_name} {command=} the following args are unknown',
|
|
2274
|
+
f'{bad_remaining_args}'
|
|
2275
|
+
)
|
|
2250
2276
|
|
|
2251
2277
|
# Remove unparsed args starting with '+', since those are commonly sent downstream to
|
|
2252
2278
|
# single job (example, CommandSim plusargs).
|
opencos/eda_config_defaults.yml
CHANGED
opencos/files.py
CHANGED
opencos/tests/helpers.py
CHANGED
|
@@ -171,6 +171,7 @@ class Helpers:
|
|
|
171
171
|
'''Changes directory to self.DEFAULT_DIR and removes eda.work, eda.export paths'''
|
|
172
172
|
chdir_remove_work_dir('', self.DEFAULT_DIR)
|
|
173
173
|
|
|
174
|
+
|
|
174
175
|
def _resolve_logfile(self, logfile=None) -> str:
|
|
175
176
|
'''Returns the logfile's filepath'''
|
|
176
177
|
ret = logfile
|
|
@@ -232,7 +233,7 @@ class Helpers:
|
|
|
232
233
|
return rc
|
|
233
234
|
|
|
234
235
|
def is_in_log(self, *want_str, logfile=None, windows_path_support=False):
|
|
235
|
-
'''Check if
|
|
236
|
+
'''Check if want_str (joined) is in the logfile, or self.DEFAULT_LOG'''
|
|
236
237
|
logfile = self._resolve_logfile(logfile)
|
|
237
238
|
want_str0 = ' '.join(list(want_str))
|
|
238
239
|
want_str1 = want_str0.replace('/', '\\')
|
opencos/util.py
CHANGED
|
@@ -435,25 +435,67 @@ def load_env_file(env_file: str) -> None:
|
|
|
435
435
|
else:
|
|
436
436
|
warning(f'--env-file {env_file} does not exist and is not loaded.')
|
|
437
437
|
|
|
438
|
-
def
|
|
438
|
+
def patch_args_for_dir(tokens: list, patch_dir: str, caller_info: str) -> list:
|
|
439
|
+
'''Given list of args, attempt to correct for relative dir'''
|
|
440
|
+
|
|
441
|
+
# deal with relative path args or files.
|
|
442
|
+
# Note the dot-f file could have been in a different directory (-f=path/to/my.f)
|
|
443
|
+
# As a workaround to deal with relative paths, attempt to replace relative
|
|
444
|
+
# path args within this dotf contents - so they are relative the dotf dir:
|
|
445
|
+
if not os.path.isdir(patch_dir):
|
|
446
|
+
return tokens
|
|
447
|
+
|
|
448
|
+
ret = []
|
|
449
|
+
for word in tokens:
|
|
450
|
+
if word.startswith('-') and '=' in word:
|
|
451
|
+
parts = word.split('=')
|
|
452
|
+
leftarg = parts[0] + '='
|
|
453
|
+
word = '='.join(parts[1:])
|
|
454
|
+
elif word.startswith('+incdir+'):
|
|
455
|
+
# do for +incdir+ too
|
|
456
|
+
leftarg = '+incdir+'
|
|
457
|
+
word = word[len('+incdir+'):]
|
|
458
|
+
else:
|
|
459
|
+
leftarg = ''
|
|
460
|
+
|
|
461
|
+
if word and not os.path.isabs(word) and \
|
|
462
|
+
os.path.exists(os.path.join(patch_dir, word)):
|
|
463
|
+
# fix relative path of word, or --arg=word
|
|
464
|
+
word = os.path.abspath(os.path.join(patch_dir, word))
|
|
465
|
+
info(f'Using relative path {patch_dir} for arg/token: {leftarg}{word}',
|
|
466
|
+
f'{caller_info}')
|
|
467
|
+
ret.append(f'{leftarg}{word}')
|
|
468
|
+
return ret
|
|
469
|
+
|
|
470
|
+
def read_tokens_from_dot_f(filepath: str, caller_info: str = '', verbose: bool = False) -> list:
|
|
439
471
|
'''Returns list of tokens from a .f file, with ENV vars expanded'''
|
|
440
472
|
|
|
441
473
|
# Let's defer 'info' printing out what input files were opened until after
|
|
442
474
|
# args['quiet'] and debug is resolved (which may be in these .f files)
|
|
443
|
-
|
|
475
|
+
start_str = f"Opening -f / --input-file '{filepath}' for contents {caller_info}"
|
|
476
|
+
if verbose:
|
|
477
|
+
info(start_str)
|
|
478
|
+
else:
|
|
479
|
+
debug(start_str)
|
|
444
480
|
if not os.path.isfile(filepath):
|
|
445
|
-
error(f'-f (or --input-file): {filepath} does not exist',
|
|
481
|
+
error(f'-f (or --input-file): {filepath} does not exist {caller_info}',
|
|
446
482
|
error_code=status_constants.EDA_GENERAL_FILE_NOT_FOUND)
|
|
447
483
|
return []
|
|
448
484
|
if os.path.abspath(filepath) in dot_f_files_expanded:
|
|
449
485
|
error(f'-f (or --input-file): {filepath} has already been expanded',
|
|
450
|
-
'cannot traverse again (duplicate arg or nested .f files)')
|
|
486
|
+
f'cannot traverse again (duplicate arg or nested .f files) {caller_info}')
|
|
451
487
|
dot_f_files_expanded.add(os.path.abspath(filepath))
|
|
452
488
|
tokens = []
|
|
489
|
+
dotf_file_dir, _ = os.path.split(filepath)
|
|
453
490
|
with open(filepath, encoding='utf-8') as f:
|
|
454
491
|
for line in f:
|
|
455
492
|
line = os.path.expandvars(line.strip())
|
|
456
|
-
|
|
493
|
+
if not line or line.startswith('#') or line.startswith('//'):
|
|
494
|
+
continue
|
|
495
|
+
words = line.split()
|
|
496
|
+
tokens.extend(patch_args_for_dir(
|
|
497
|
+
tokens=words, patch_dir=dotf_file_dir, caller_info=f"(from dotf {filepath})"
|
|
498
|
+
))
|
|
457
499
|
return tokens
|
|
458
500
|
|
|
459
501
|
|
|
@@ -471,7 +513,7 @@ def process_debug_args(parsed: argparse.Namespace) -> None:
|
|
|
471
513
|
|
|
472
514
|
|
|
473
515
|
def process_tokens( # pylint: disable=too-many-branches
|
|
474
|
-
tokens: list
|
|
516
|
+
tokens: list, caller_info: str = ''
|
|
475
517
|
) -> (argparse.Namespace, list):
|
|
476
518
|
'''Processes tokens (unparsed args list) on util's ArgumentParser
|
|
477
519
|
|
|
@@ -517,13 +559,15 @@ def process_tokens( # pylint: disable=too-many-branches
|
|
|
517
559
|
if parsed.input_file:
|
|
518
560
|
dotf_tokens = []
|
|
519
561
|
for filepath in parsed.input_file:
|
|
520
|
-
dotf_tokens.extend(read_tokens_from_dot_f(
|
|
562
|
+
dotf_tokens.extend(read_tokens_from_dot_f(
|
|
563
|
+
filepath=filepath, caller_info=caller_info
|
|
564
|
+
))
|
|
521
565
|
|
|
522
566
|
# put the .f files before the unparsed args.
|
|
523
567
|
tokens2 = dotf_tokens + tokens2
|
|
524
568
|
|
|
525
569
|
# recurse until we've resolved nested .f files.
|
|
526
|
-
return process_tokens(tokens=tokens2)
|
|
570
|
+
return process_tokens(tokens=tokens2, caller_info=f'(from {parsed.input_file[-1]})')
|
|
527
571
|
|
|
528
572
|
|
|
529
573
|
# Continue with all normal parsing beyond --debug and -f/--input-file,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opencos-eda
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: A simple Python package for wrapping RTL simuliatons and synthesis
|
|
5
5
|
Author-email: Simon Sabato <simon@cognichip.ai>, Drew Ranck <drew@cognichip.ai>
|
|
6
6
|
Project-URL: Homepage, https://github.com/cognichip/opencos
|
|
@@ -3,9 +3,9 @@ opencos/_version.py,sha256=KaWIjS0c08g-C0fgYY1kXwSPqhOFxaq5pYEeoZhOR_I,617
|
|
|
3
3
|
opencos/_waves_pkg.sv,sha256=TL5YT9lT-fn2FD54MbVVZROmZ7vtW3ScA_rM2eRzKmU,2068
|
|
4
4
|
opencos/deps_schema.py,sha256=VUdXuq43mKfM-U4x7DSA28-MH1Xqxre6V7Ttw2DeOqI,16762
|
|
5
5
|
opencos/eda.py,sha256=91E-EsyZS-uRadApP-h2onW6rpvLBnrpJoT_9tRtsS8,23322
|
|
6
|
-
opencos/eda_base.py,sha256=
|
|
6
|
+
opencos/eda_base.py,sha256=Spt_Ssq5aVZ6L_J1koaDMB1jo81srIStwl9KMG5_irU,108740
|
|
7
7
|
opencos/eda_config.py,sha256=z3yQOPGBX7-yKp6BdQYfJ9eOJf-Jctl-mwCDj3vj2BI,12712
|
|
8
|
-
opencos/eda_config_defaults.yml,sha256=
|
|
8
|
+
opencos/eda_config_defaults.yml,sha256=LF0yAncYeaPtZIoAfEeo2aiDXT4cjYa99soGks0WRzM,16063
|
|
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
|
|
@@ -14,11 +14,11 @@ opencos/eda_extract_targets.py,sha256=POlxZfqf2dNH2nc1CEw5B_53vSHAicSTkpU9_-2_6Z
|
|
|
14
14
|
opencos/eda_tool_helper.py,sha256=_YgobDLEWW6Fzdr976LxaCDZ4DKRyuMs5CrYQHaTPrU,2558
|
|
15
15
|
opencos/export_helper.py,sha256=5BnrkhiieJBgYKAryhXD7HSGtrgvXQpZ8B5ltdrhbRY,22649
|
|
16
16
|
opencos/export_json_convert.py,sha256=tSIMbLFtc_Fo66EhFovMii1v_qJYyFZJrPNnoPdW7L0,4182
|
|
17
|
-
opencos/files.py,sha256=
|
|
17
|
+
opencos/files.py,sha256=AQOnsrvoc0r76LiFrkoMbwOGdUO1FpBiFY_jyyI_ve8,1566
|
|
18
18
|
opencos/names.py,sha256=Y2aJ5wgpbNIJ-_P5xUXnHMv_h-zMOX2Rt6iLuduqC1Q,1213
|
|
19
19
|
opencos/peakrdl_cleanup.py,sha256=vHNGtalTrIVP335PhRjPt9RhoccgpK1HJAi-E4M8Kc8,736
|
|
20
20
|
opencos/seed.py,sha256=IL9Yg-r9SLSRseMVWaEHmuw2_DNi_eyut11EafoNTsU,942
|
|
21
|
-
opencos/util.py,sha256=
|
|
21
|
+
opencos/util.py,sha256=ffaSoDDOsL6mx_fYgAyJA8fawsxZ5YHKqs67b8iW5rw,41921
|
|
22
22
|
opencos/commands/__init__.py,sha256=oOOQmn5_jHAMSOfA3swJJ7mdoyHsJA0lJwKPTudlTns,1125
|
|
23
23
|
opencos/commands/build.py,sha256=mvJYxk5J15k0Cr8R7oIdIIdsEtWV3gE-LnPweVwtSDo,1487
|
|
24
24
|
opencos/commands/deps_help.py,sha256=WDrU7H9sypzDAxe_CHqhW5B_scbQMzBEdf-v-Jcfd5Q,10682
|
|
@@ -40,14 +40,14 @@ opencos/commands/waves.py,sha256=nrp3ALwfJujZns44tgCgia_dEedQyKe0T3fuws8h39U,769
|
|
|
40
40
|
opencos/deps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
41
|
opencos/deps/defaults.py,sha256=NXh3V4oInrBVlDw64B2OCI77wzdn1NtaD64srhBnmZU,1486
|
|
42
42
|
opencos/deps/deps_commands.py,sha256=q4JfSfzRO2nM2zdNT4enCy33FokEytZYQJn1HJ6osJk,16606
|
|
43
|
-
opencos/deps/deps_file.py,sha256=
|
|
44
|
-
opencos/deps/deps_processor.py,sha256=
|
|
43
|
+
opencos/deps/deps_file.py,sha256=36KvkixS_TcIjetpvJEmYpkdaYhuY42aVi7WvV3Qtw8,16445
|
|
44
|
+
opencos/deps/deps_processor.py,sha256=DBaMUEnpoIL4xaNPs2f2AFGcWLST5pP_Qgup9r-8D7M,41403
|
|
45
45
|
opencos/hw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
46
|
opencos/hw/oc_cli.py,sha256=U1JGlshLZhtd0LgndZFBZVltAj_HemdhbjO_Zo8ZuVM,132252
|
|
47
47
|
opencos/hw/pcie.py,sha256=VUJljaZJYgScAAx5yn7F6GoA8K9eTcw24otYZbkMpYs,3035
|
|
48
48
|
opencos/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
49
49
|
opencos/tests/custom_config.yml,sha256=TRoVM9ZFKPOA_8JmlpzaMhnGO1txmaD14N_8P1oqzew,257
|
|
50
|
-
opencos/tests/helpers.py,sha256=
|
|
50
|
+
opencos/tests/helpers.py,sha256=fs7GRlCJWj_uwwilikKI6R9tbozgGH5Uxi6_qqvEEwc,11231
|
|
51
51
|
opencos/tests/test_build.py,sha256=FQAxOpLVQShAHD_L5rqJctPeSAoqoOCNFI0RXflLuY0,387
|
|
52
52
|
opencos/tests/test_deps_helpers.py,sha256=uQZxleh6aKO-mZQhagHh5xLIBbpQ8dav7-5D0eemq_g,8164
|
|
53
53
|
opencos/tests/test_deps_schema.py,sha256=T3P9KjaMyKsk8b7snNVvNSsom2hIJcg6Z9apYiXoH9Y,941
|
|
@@ -88,10 +88,10 @@ opencos/utils/str_helpers.py,sha256=726ScK5-v7QkBi-zqESKZLsOl2_ya4vVJ5ZhxJqmBFo,
|
|
|
88
88
|
opencos/utils/subprocess_helpers.py,sha256=xemAGPey6M0sWY_FElvr-Z0phCfdjaC-znP8FKihPaE,3535
|
|
89
89
|
opencos/utils/vscode_helper.py,sha256=9nHyMUIL-gzfW-qLH06sgaCnVK-YTOtu6pusitNNhL8,1363
|
|
90
90
|
opencos/utils/vsim_helper.py,sha256=1johPOGbjbMgnCDSTpgsQcSuAquiqq1Y2MBxS6WY6b4,1552
|
|
91
|
-
opencos_eda-0.3.
|
|
92
|
-
opencos_eda-0.3.
|
|
93
|
-
opencos_eda-0.3.
|
|
94
|
-
opencos_eda-0.3.
|
|
95
|
-
opencos_eda-0.3.
|
|
96
|
-
opencos_eda-0.3.
|
|
97
|
-
opencos_eda-0.3.
|
|
91
|
+
opencos_eda-0.3.1.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
|
|
92
|
+
opencos_eda-0.3.1.dist-info/licenses/LICENSE.spdx,sha256=8gn1610RMP6eFgT3Hm6q9VKXt0RvdTItL_oxMo72jII,189
|
|
93
|
+
opencos_eda-0.3.1.dist-info/METADATA,sha256=Gc70L29pHLuc43gNk0yJw3-dGE98LYbpu-o7FdLM4sw,666
|
|
94
|
+
opencos_eda-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
95
|
+
opencos_eda-0.3.1.dist-info/entry_points.txt,sha256=6n1T5NwVYDhN5l1h5zmyT197G4pE0SySDreB0QJzJR0,218
|
|
96
|
+
opencos_eda-0.3.1.dist-info/top_level.txt,sha256=J4JDP-LpRyJqPNeh9bSjx6yrLz2Mk0h6un6YLmtqql4,8
|
|
97
|
+
opencos_eda-0.3.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|