opencos-eda 0.2.46__tar.gz → 0.2.47__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. {opencos_eda-0.2.46/opencos_eda.egg-info → opencos_eda-0.2.47}/PKG-INFO +1 -1
  2. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/deps_helpers.py +71 -28
  3. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/deps_schema.py +8 -0
  4. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/test_deps_helpers.py +56 -19
  5. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tools/vivado.py +18 -12
  6. {opencos_eda-0.2.46 → opencos_eda-0.2.47/opencos_eda.egg-info}/PKG-INFO +1 -1
  7. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/pyproject.toml +1 -1
  8. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/LICENSE +0 -0
  9. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/LICENSE.spdx +0 -0
  10. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/README.md +0 -0
  11. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/__init__.py +0 -0
  12. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/_version.py +0 -0
  13. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/_waves_pkg.sv +0 -0
  14. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/commands/__init__.py +0 -0
  15. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/commands/build.py +0 -0
  16. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/commands/elab.py +0 -0
  17. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/commands/export.py +0 -0
  18. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/commands/flist.py +0 -0
  19. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/commands/lec.py +0 -0
  20. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/commands/multi.py +0 -0
  21. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/commands/open.py +0 -0
  22. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/commands/proj.py +0 -0
  23. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/commands/shell.py +0 -0
  24. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/commands/sim.py +0 -0
  25. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/commands/sweep.py +0 -0
  26. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/commands/synth.py +0 -0
  27. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/commands/targets.py +0 -0
  28. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/commands/upload.py +0 -0
  29. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/commands/waves.py +0 -0
  30. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/eda.py +0 -0
  31. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/eda_base.py +0 -0
  32. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/eda_config.py +0 -0
  33. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/eda_config_defaults.yml +0 -0
  34. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/eda_config_max_verilator_waivers.yml +0 -0
  35. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/eda_config_reduced.yml +0 -0
  36. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/eda_deps_bash_completion.bash +0 -0
  37. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/eda_extract_targets.py +0 -0
  38. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/eda_tool_helper.py +0 -0
  39. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/export_helper.py +0 -0
  40. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/export_json_convert.py +0 -0
  41. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/files.py +0 -0
  42. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/names.py +0 -0
  43. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/oc_cli.py +0 -0
  44. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/pcie.py +0 -0
  45. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/peakrdl_cleanup.py +0 -0
  46. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/seed.py +0 -0
  47. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/__init__.py +0 -0
  48. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/custom_config.yml +0 -0
  49. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/deps_files/command_order/DEPS.yml +0 -0
  50. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/deps_files/error_msgs/DEPS.yml +0 -0
  51. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/deps_files/iverilog_test/DEPS.yml +0 -0
  52. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/deps_files/no_deps_here/DEPS.yml +0 -0
  53. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/deps_files/non_sv_reqs/DEPS.yml +0 -0
  54. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/deps_files/tags_with_tools/DEPS.yml +0 -0
  55. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/deps_files/test_err_fatal/DEPS.yml +0 -0
  56. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/helpers.py +0 -0
  57. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/test_build.py +0 -0
  58. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/test_deps_schema.py +0 -0
  59. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/test_eda.py +0 -0
  60. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/test_eda_elab.py +0 -0
  61. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/test_eda_synth.py +0 -0
  62. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/test_oc_cli.py +0 -0
  63. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tests/test_tools.py +0 -0
  64. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tools/__init__.py +0 -0
  65. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tools/invio.py +0 -0
  66. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tools/invio_helpers.py +0 -0
  67. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tools/invio_yosys.py +0 -0
  68. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tools/iverilog.py +0 -0
  69. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tools/modelsim_ase.py +0 -0
  70. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tools/questa.py +0 -0
  71. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tools/riviera.py +0 -0
  72. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tools/slang.py +0 -0
  73. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tools/slang_yosys.py +0 -0
  74. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tools/surelog.py +0 -0
  75. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tools/tabbycad_yosys.py +0 -0
  76. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tools/verilator.py +0 -0
  77. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/tools/yosys.py +0 -0
  78. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos/util.py +0 -0
  79. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos_eda.egg-info/SOURCES.txt +0 -0
  80. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos_eda.egg-info/dependency_links.txt +0 -0
  81. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos_eda.egg-info/entry_points.txt +0 -0
  82. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos_eda.egg-info/requires.txt +0 -0
  83. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/opencos_eda.egg-info/top_level.txt +0 -0
  84. {opencos_eda-0.2.46 → opencos_eda-0.2.47}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opencos-eda
3
- Version: 0.2.46
3
+ Version: 0.2.47
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
@@ -68,7 +68,9 @@ class Defaults:
68
68
  'shell',
69
69
  'work-dir-add-srcs', 'work-dir-add-sources',
70
70
  'peakrdl',
71
- 'run-from-work-dir',
71
+ 'run-from-work-dir', # default True
72
+ 'filepath-subst-target-dir', # default True
73
+ 'dirpath-subst-target-dir', # default False
72
74
  'var-subst-args',
73
75
  'var-subst-os-env',
74
76
  'tee',
@@ -384,7 +386,13 @@ def deps_list_target_sanitize(entry, default_key:str='deps', target_node:str='',
384
386
  assert False, f"Can't convert to list {entry=} {default_key=} {target_node=} {deps_file=}"
385
387
 
386
388
 
387
- def path_substitutions_relative_to_work_dir(exec_list : list, info_str : str, target_path : str):
389
+ def path_substitutions_relative_to_work_dir(
390
+ exec_list: list, info_str: str, target_path: str,
391
+ enable_filepath_subst: bool, enable_dirpath_subst: bool
392
+ ) -> list:
393
+
394
+ if not enable_filepath_subst and not enable_dirpath_subst:
395
+ return exec_list
388
396
 
389
397
  # Look for path substitutions, b/c we later "work" in self.args['work-dir'], but
390
398
  # files should be relative to our target_path.
@@ -398,10 +406,18 @@ def path_substitutions_relative_to_work_dir(exec_list : list, info_str : str, ta
398
406
  # need this, and we can't assume dir levels in the work-dir.
399
407
  try:
400
408
  try_path = os.path.abspath(os.path.join(os.path.abspath(target_path), m.group(1)))
401
- if os.path.isfile(try_path) or os.path.isdir(try_path):
409
+ if enable_filepath_subst and os.path.isfile(try_path):
410
+ # make the substitution
411
+ exec_list[i] = word.replace(m.group(1), try_path)
412
+ debug(f'file path substitution {info_str=} {target_path=}: replaced - {word=}'
413
+ f'is now ={exec_list[i]}. This can be disabled in DEPS with:',
414
+ '"filepath-subst-targetdir: false"')
415
+ elif enable_dirpath_subst and os.path.isdir(try_path):
402
416
  # make the substitution
403
417
  exec_list[i] = word.replace(m.group(1), try_path)
404
- debug(f'path substitution {info_str=} {target_path=}: replaced - {word=} is now ={exec_list[i]}')
418
+ debug(f'dir path substitution {info_str=} {target_path=}: replaced - {word=}'
419
+ f'is now ={exec_list[i]}. This can be disabled in DEPS with:',
420
+ '"dirpath-subst-targetdir: false"')
405
421
  except:
406
422
  pass
407
423
 
@@ -1034,7 +1050,10 @@ class DepsProcessor:
1034
1050
 
1035
1051
 
1036
1052
 
1037
- def parse_deps_shell_str(line : str, target_path : str, target_node : str, enable : bool = True):
1053
+ def parse_deps_shell_str(line: str, target_path: str, target_node: str,
1054
+ enable_filepath_subst_target_dir: bool = True,
1055
+ enable_dirpath_subst_target_dir: bool = False,
1056
+ enable: bool = True) -> dict:
1038
1057
  '''Returns None or a dict of a possible shell command from line (str)
1039
1058
 
1040
1059
  Examples of 'line' str:
@@ -1050,25 +1069,30 @@ def parse_deps_shell_str(line : str, target_path : str, target_node : str, enabl
1050
1069
  target_node (str) -- from dependency parsing, the target containing this 'line' str.
1051
1070
  '''
1052
1071
  if not enable:
1053
- return None
1072
+ return {}
1054
1073
 
1055
1074
  m = re.match(r'^\s*shell\@(.*)\s*$', line)
1056
1075
  if not m:
1057
- return None
1076
+ return {}
1058
1077
 
1059
1078
  exec_str = m.group(1)
1060
1079
  exec_list = exec_str.split()
1061
1080
 
1062
1081
  # Look for path substitutions, b/c we later "work" in self.args['work-dir'], but
1063
1082
  # files should be relative to our target_path.
1064
- exec_list = path_substitutions_relative_to_work_dir(exec_list=exec_list, info_str='shell@', target_path=target_path)
1083
+ # Note this can be disable in DEPS via path-subst-target-dir=False
1084
+ exec_list = path_substitutions_relative_to_work_dir(
1085
+ exec_list=exec_list, info_str='shell@', target_path=target_path,
1086
+ enable_filepath_subst=enable_filepath_subst_target_dir,
1087
+ enable_dirpath_subst=enable_dirpath_subst_target_dir
1088
+ )
1065
1089
 
1066
- d = {'target_path': os.path.abspath(target_path),
1067
- 'target_node': target_node,
1068
- 'run_from_work_dir': True,
1069
- 'exec_list': exec_list,
1070
- }
1071
- return d
1090
+ return {
1091
+ 'target_path': os.path.abspath(target_path),
1092
+ 'target_node': target_node,
1093
+ 'run_from_work_dir': True, # may be overriden later.
1094
+ 'exec_list': exec_list,
1095
+ }
1072
1096
 
1073
1097
 
1074
1098
  def parse_deps_work_dir_add_srcs(line : str, target_path : str, target_node : str, enable : bool = True):
@@ -1100,8 +1124,12 @@ def parse_deps_work_dir_add_srcs(line : str, target_path : str, target_node : st
1100
1124
  return d
1101
1125
 
1102
1126
 
1103
- def parse_deps_peakrdl(line : str, target_path : str, target_node : str, enable : bool = True,
1104
- tool : str = ''):
1127
+ def parse_deps_peakrdl(
1128
+ line: str, target_path: str, target_node: str, enable: bool = True,
1129
+ enable_filepath_subst_target_dir: bool = True,
1130
+ enable_dirpath_subst_target_dir: bool = False,
1131
+ tool: str = ''
1132
+ ) -> dict:
1105
1133
  '''Returns None or a dict describing a PeakRDL CSR register generator dependency
1106
1134
 
1107
1135
  Examples of 'line' str:
@@ -1172,10 +1200,13 @@ def parse_deps_peakrdl(line : str, target_path : str, target_node : str, enable
1172
1200
  # Make these look like a dep_shell_command:
1173
1201
  for one_cmd_as_list in shell_commands:
1174
1202
  ret_dict['shell_commands_list'].append(
1175
- parse_deps_shell_str(line = ' shell@ ' + ' '.join(one_cmd_as_list),
1176
- target_path = target_path,
1177
- target_node = target_node
1178
- )
1203
+ parse_deps_shell_str(
1204
+ line=(' shell@ ' + ' '.join(one_cmd_as_list)),
1205
+ target_path=target_path,
1206
+ target_node=target_node,
1207
+ enable_filepath_subst_target_dir=enable_filepath_subst_target_dir,
1208
+ enable_dirpath_subst_target_dir=enable_dirpath_subst_target_dir
1209
+ )
1179
1210
  )
1180
1211
 
1181
1212
  # Make the work_dir_add_srcs dict:
@@ -1237,14 +1268,22 @@ def deps_commands_handler(config: dict, eda_args: dict,
1237
1268
  var_subst_dict = eda_args
1238
1269
 
1239
1270
  tee_fpath = command.get('tee', None)
1240
- run_from_work_dir = command.get('run-from-work-dir', True) # for shell, default True
1271
+
1272
+ # These are both optional bools, default True, would have to explicitly be set to False
1273
+ # to take effect:
1274
+ run_from_work_dir = command.get('run-from-work-dir', True)
1275
+ filepath_subst_target_dir = command.get('filepath-subst-target-dir', True)
1276
+ dirpath_subst_target_dir = command.get('dirpath-subst-target-dir', False)
1241
1277
 
1242
1278
  for key,item in command.items():
1243
1279
 
1244
- # skip the var-subst-* keys, since these types are bools
1245
- if key.startswith('var-subst') or \
1246
- key.startswith('tee') or \
1247
- key.startswith('run-from-work-dir'):
1280
+ # skip the tee and var-subst-* keys, since these types are bools and not commands.
1281
+ if key in ['tee',
1282
+ 'var-subst-os-env',
1283
+ 'var-subst-args',
1284
+ 'run-from-work-dir',
1285
+ 'filepath-subst-target-dir',
1286
+ 'dirpath-subst-target-dir']:
1248
1287
  continue
1249
1288
 
1250
1289
  # Optional variable substituion in commands
@@ -1255,9 +1294,11 @@ def deps_commands_handler(config: dict, eda_args: dict,
1255
1294
  if key == 'shell':
1256
1295
  # For now, piggyback on parse_deps_shell_str:
1257
1296
  ret_dict = parse_deps_shell_str(
1258
- line = 'shell@ ' + item,
1259
- target_path = target_path,
1260
- target_node = target_node,
1297
+ line=('shell@ ' + item),
1298
+ target_path=target_path,
1299
+ target_node=target_node,
1300
+ enable_filepath_subst_target_dir=filepath_subst_target_dir,
1301
+ enable_dirpath_subst_target_dir=dirpath_subst_target_dir,
1261
1302
  enable=config['dep_command_enables']['shell'],
1262
1303
  )
1263
1304
  # To support 'tee: <some-file>' need to append it to last
@@ -1286,6 +1327,8 @@ def deps_commands_handler(config: dict, eda_args: dict,
1286
1327
  line = 'peakrdl@ ' + item,
1287
1328
  target_path = target_path,
1288
1329
  target_node = target_node,
1330
+ enable_filepath_subst_target_dir=filepath_subst_target_dir,
1331
+ enable_dirpath_subst_target_dir=dirpath_subst_target_dir,
1289
1332
  enable=config['dep_command_enables']['peakrdl'],
1290
1333
  tool=eda_args.get('tool', '')
1291
1334
  )
@@ -71,6 +71,12 @@ my_target_name:
71
71
  var-subst-os-env: <---- bool, perform var substitution using os.environ
72
72
  run-from-work-dir: <---- bool, default True, if False runs from target dir
73
73
  instead of work-dir.
74
+ filepath-subst-target-dir: <---- bool, default True, if False does not perform
75
+ file path substitution relative to target dir
76
+ (if substituted file exists).
77
+ dirpath-subst-target-dir: <---- bool, default False, if True performs
78
+ directory path substitution relative to target dir
79
+ (if substituted directory exists).
74
80
  tee: <---- string, filename to write logs to
75
81
  - work-dir-add-sources: <---- work-dir-add-sources, optional list (or string)
76
82
  - some_file_gen_from_sh.sv <---- string filename that we created with sh command
@@ -153,6 +159,8 @@ DEPS_COMMANDS_LIST = [
153
159
  Optional('var-subst-args'): bool,
154
160
  Optional('var-subst-os-env'): bool,
155
161
  Optional('run-from-work-dir'): bool,
162
+ Optional('filepath-subst-target-dir'): bool,
163
+ Optional('dirpath-subst-target-dir'): bool,
156
164
  Optional('tee'): Or(str, type(None)),
157
165
  },
158
166
  {
@@ -14,7 +14,7 @@ from opencos import eda_tool_helper, deps_helpers
14
14
 
15
15
  THISPATH = os.path.dirname(__file__)
16
16
 
17
- # Figure out what tools the system has available, without calling eda.main(..)
17
+ # Figure out what tools the system has avail, without calling eda.main(..)
18
18
  config, tools_loaded = eda_tool_helper.get_config_and_tools_loaded()
19
19
 
20
20
 
@@ -58,63 +58,100 @@ def test_get_all_targets_eda_multi():
58
58
  def test_parse_deps_shell_str__no_parse():
59
59
  line = 'some_file.sv'
60
60
  d = deps_helpers.parse_deps_shell_str(line, '', '')
61
- assert d is None, f'{d=}'
61
+ assert not d, f'{d=}'
62
62
 
63
63
  line = 'some_target:'
64
64
  d = deps_helpers.parse_deps_shell_str(line, '', '')
65
- assert d is None, f'{d=}'
65
+ assert not d, f'{d=}'
66
66
 
67
67
  line = ' csr@some_file.sv'
68
68
  d = deps_helpers.parse_deps_shell_str(line, '', '')
69
- assert d is None, f'{d=}'
69
+ assert not d, f'{d=}'
70
70
 
71
71
  def test_parse_deps_shell_str__cp():
72
72
  line = ' shell@ cp ./oclib_fifo_test.sv oclib_fifo_test_COPY.sv ;'
73
73
  d = deps_helpers.parse_deps_shell_str(line, '', '')
74
- assert d is not None, f'{d=}'
74
+ assert d, f'{d=}'
75
75
  assert d['exec_list'] == ['cp', './oclib_fifo_test.sv', 'oclib_fifo_test_COPY.sv', ';'], f'{d=}'
76
76
 
77
77
  def test_parse_deps_shell_str__echo():
78
78
  line = ' shell@echo "hello world"'
79
79
  d = deps_helpers.parse_deps_shell_str(line, '', '')
80
- assert d is not None, f'{d=}'
80
+ assert d, f'{d=}'
81
81
  assert d['exec_list'] == ['echo', '"hello', 'world"'], f'{d=}'
82
82
 
83
- def test_parse_deps_shell_str__path_replacement():
83
+ def test_parse_deps_shell_str__enable_filepath_replacement():
84
84
  # Dealing w/ relative paths, change the current working directory to the module directory
85
+ # Default is enabled.
85
86
  module_dir = os.path.dirname(os.path.abspath(__file__))
86
87
  os.chdir(module_dir)
87
88
  line = 'shell@cp ../deps_helpers.py foo.py'
88
89
  d = deps_helpers.parse_deps_shell_str(line, target_path='./', target_node='foo_target')
89
- assert d is not None, f'{d=}'
90
+ assert d, f'{d=}'
90
91
  assert d['exec_list'] == ['cp', os.path.abspath('../deps_helpers.py'), 'foo.py'], f'{d=}'
91
92
  assert d['target_node'] == 'foo_target'
92
93
  assert d['target_path'] == os.path.abspath('./')
93
94
 
95
+ def test_parse_deps_shell_str__disable_filepath_replacement():
96
+ # Dealing w/ relative paths, change the current working directory to the module directory
97
+ module_dir = os.path.dirname(os.path.abspath(__file__))
98
+ os.chdir(module_dir)
99
+ line = 'shell@cp ../deps_helpers.py foo.py'
100
+ d = deps_helpers.parse_deps_shell_str(line, target_path='./', target_node='foo_target',
101
+ enable_filepath_subst_target_dir=False)
102
+ assert d, f'{d=}'
103
+ assert d['exec_list'] == ['cp', '../deps_helpers.py', 'foo.py'], f'{d=}'
104
+ assert d['target_node'] == 'foo_target'
105
+ assert d['target_path'] == os.path.abspath('./')
106
+
107
+ def test_parse_deps_shell_str__enable_dirpath_replacement():
108
+ # Dealing w/ relative paths, change the current working directory to the module directory
109
+ module_dir = os.path.dirname(os.path.abspath(__file__))
110
+ os.chdir(module_dir)
111
+ line = 'shell@ls -ltr ./'
112
+ d = deps_helpers.parse_deps_shell_str(line, target_path='./', target_node='foo_target',
113
+ enable_dirpath_subst_target_dir=True)
114
+ assert d, f'{d=}'
115
+ assert d['exec_list'] == ['ls', '-ltr', os.path.abspath('./')], f'{d=}'
116
+ assert d['target_node'] == 'foo_target'
117
+ assert d['target_path'] == os.path.abspath('./')
118
+
119
+ def test_parse_deps_shell_str__disable_dirpath_replacement():
120
+ # Dealing w/ relative paths, change the current working directory to the module directory
121
+ # Default is disabled.
122
+ module_dir = os.path.dirname(os.path.abspath(__file__))
123
+ os.chdir(module_dir)
124
+ line = 'shell@ls -ltr ./'
125
+ d = deps_helpers.parse_deps_shell_str(line, target_path='./', target_node='foo_target')
126
+ assert d, f'{d=}'
127
+ assert d['exec_list'] == ['ls', '-ltr', './'], f'{d=}'
128
+ assert d['target_node'] == 'foo_target'
129
+ assert d['target_path'] == os.path.abspath('./')
130
+
94
131
 
95
132
  def test_parse_deps_work_dir_add_srcs__no_parse():
96
133
  line = 'some_file.sv'
97
134
  d = deps_helpers.parse_deps_work_dir_add_srcs(line, '', '')
98
- assert d is None, f'{d=}'
135
+ assert not d, f'{d=}'
99
136
 
100
137
  line = 'some_target:'
101
138
  d = deps_helpers.parse_deps_work_dir_add_srcs(line, '', '')
102
- assert d is None, f'{d=}'
139
+ assert not d, f'{d=}'
103
140
 
104
141
  line = ' csr@some_file.sv'
105
142
  d = deps_helpers.parse_deps_work_dir_add_srcs(line, '', '')
106
- assert d is None, f'{d=}'
143
+ assert not d, f'{d=}'
107
144
 
108
145
  def test_parse_deps_work_dir_add_srcs__single_file():
109
146
  line = ' work_dir_add_srcs@ single_file.txt'
110
147
  d = deps_helpers.parse_deps_work_dir_add_srcs(line, '', '')
111
- assert d is not None, f'{d=}'
148
+ assert d, f'{d=}'
112
149
  assert d['file_list'] == ['single_file.txt']
113
150
 
114
151
  def test_parse_deps_work_dir_add_srcs__several_file():
115
152
  line = ' work_dir_add_srcs@ single_file.txt another.sv gen-verilog/mine.v ./gen-vhdl/wordy.vhdl'
116
153
  d = deps_helpers.parse_deps_work_dir_add_srcs(line, '', '')
117
- assert d is not None, f'{d=}'
154
+ assert d, f'{d=}'
118
155
  assert d['file_list'] == [
119
156
  'single_file.txt', 'another.sv', 'gen-verilog/mine.v', './gen-vhdl/wordy.vhdl'
120
157
  ]
@@ -123,33 +160,33 @@ def test_parse_deps_work_dir_add_srcs__several_file():
123
160
  def test_parse_deps_peakrdl__no_parse():
124
161
  line = 'some_file.sv'
125
162
  d = deps_helpers.parse_deps_peakrdl(line, '', '')
126
- assert d is None, f'{d=}'
163
+ assert not d, f'{d=}'
127
164
 
128
165
  line = 'some_target:'
129
166
  d = deps_helpers.parse_deps_peakrdl(line, '', '')
130
- assert d is None, f'{d=}'
167
+ assert not d, f'{d=}'
131
168
 
132
169
  line = ' csr@some_file.sv'
133
170
  d = deps_helpers.parse_deps_peakrdl(line, '', '')
134
- assert d is None, f'{d=}'
171
+ assert not d, f'{d=}'
135
172
 
136
173
  def test_parse_deps_peakrdl__with_top():
137
174
  line = ' peakrdl@ --cpuif axi4-lite-flat --top my_fancy_csrs ./my_csrs.rdl'
138
175
  d = deps_helpers.parse_deps_peakrdl(line, '', '')
139
- assert d is not None, f'{d=}'
176
+ assert d, f'{d=}'
140
177
  assert len(d['shell_commands_list']) > 0
141
178
  assert d['work_dir_add_srcs']['file_list'] == ['peakrdl/my_fancy_csrs_pkg.sv', 'peakrdl/my_fancy_csrs.sv']
142
179
 
143
180
  def test_parse_deps_peakrdl__with_top2():
144
181
  line = ' peakrdl@ --cpuif axi4-lite-flat --top=my_fancy_csrs ./my_csrs.rdl'
145
182
  d = deps_helpers.parse_deps_peakrdl(line, '', '')
146
- assert d is not None, f'{d=}'
183
+ assert d, f'{d=}'
147
184
  assert len(d['shell_commands_list']) > 0
148
185
  assert d['work_dir_add_srcs']['file_list'] == ['peakrdl/my_fancy_csrs_pkg.sv', 'peakrdl/my_fancy_csrs.sv']
149
186
 
150
187
  def test_parse_deps_peakrdl__infer_top():
151
188
  line = ' peakrdl@ --cpuif axi4-lite-flat ./my_csrs.rdl'
152
189
  d = deps_helpers.parse_deps_peakrdl(line, '', '')
153
- assert d is not None, f'{d=}'
190
+ assert d, f'{d=}'
154
191
  assert len(d['shell_commands_list']) > 0
155
192
  assert d['work_dir_add_srcs']['file_list'] == ['peakrdl/my_csrs_pkg.sv', 'peakrdl/my_csrs.sv']
@@ -136,7 +136,7 @@ class CommandSimVivado(CommandSim, ToolVivado):
136
136
  def __init__(self, config: dict):
137
137
  CommandSim.__init__(self, config)
138
138
  ToolVivado.__init__(self, config=self.config)
139
- # add args specific to this simulator
139
+ # add args specific to this tool
140
140
  self.args.update({
141
141
  'gui': False,
142
142
  'tcl-file': 'sim.tcl',
@@ -349,7 +349,7 @@ class CommandElabVivado(CommandSimVivado):
349
349
  '''CommandElabVivado is a command handler for: eda elab --tool=vivado, uses xvlog, xelab'''
350
350
  def __init__(self, config: dict):
351
351
  CommandSimVivado.__init__(self, config)
352
- # add args specific to this simulator
352
+ # add args specific to this tool
353
353
  self.args['stop-after-elaborate'] = True
354
354
 
355
355
 
@@ -358,7 +358,7 @@ class CommandSynthVivado(CommandSynth, ToolVivado):
358
358
  def __init__(self, config: dict):
359
359
  CommandSynth.__init__(self, config)
360
360
  ToolVivado.__init__(self, config=self.config)
361
- # add args specific to this simulator
361
+ # add args specific to this tool
362
362
  self.args['gui'] = False
363
363
  self.args['tcl-file'] = "synth.tcl"
364
364
  self.args['xdc'] = ""
@@ -401,9 +401,7 @@ class CommandSynthVivado(CommandSynth, ToolVivado):
401
401
  defines = ""
402
402
  for key, value in self.defines.items():
403
403
  defines += (f"-verilog_define {key}" + (" " if value is None else f"={value} "))
404
- incdirs = ""
405
- if self.incdirs:
406
- incdirs = " -include_dirs " + ";".join(self.incdirs)
404
+ incdirs = ' '.join([f'-include_dirs {x}' for x in self.incdirs])
407
405
  flatten = ""
408
406
  if self.args['flatten-all']:
409
407
  flatten = "-flatten_hierarchy full"
@@ -547,7 +545,7 @@ class CommandProjVivado(CommandProj, ToolVivado):
547
545
  def __init__(self, config: dict):
548
546
  CommandProj.__init__(self, config)
549
547
  ToolVivado.__init__(self, config=self.config)
550
- # add args specific to this simulator
548
+ # add args specific to this tool
551
549
  self.args['gui'] = True
552
550
  self.args['oc-vivado-tcl'] = True
553
551
  self.args['tcl-file'] = "proj.tcl"
@@ -630,10 +628,11 @@ class CommandBuildVivado(CommandBuild, ToolVivado):
630
628
  def __init__(self, config: dict):
631
629
  CommandBuild.__init__(self, config)
632
630
  ToolVivado.__init__(self, config=self.config)
633
- # add args specific to this simulator
631
+ # add args specific to this tool
634
632
  self.args['gui'] = False
635
633
  self.args['fpga'] = ""
636
634
  self.args['proj'] = False
635
+ self.args['resynth'] = False
637
636
  self.args['reset'] = False
638
637
  self.args['all-sv'] = False
639
638
 
@@ -705,6 +704,8 @@ class CommandBuildVivado(CommandBuild, ToolVivado):
705
704
  ]
706
705
  if self.args['proj']:
707
706
  command_list += ['--proj']
707
+ if self.args['resynth']:
708
+ command_list += ['--resynth']
708
709
  if self.args['reset']:
709
710
  command_list += ['--reset']
710
711
 
@@ -732,7 +733,7 @@ class CommandUploadVivado(CommandUpload, ToolVivado):
732
733
  def __init__(self, config: dict):
733
734
  CommandUpload.__init__(self, config)
734
735
  ToolVivado.__init__(self, config=self.config)
735
- # add args specific to this simulator
736
+ # add args specific to this tool
736
737
  self.args.update({
737
738
  'gui': False,
738
739
  'bitfile': "",
@@ -743,8 +744,10 @@ class CommandUploadVivado(CommandUpload, ToolVivado):
743
744
  'device': -1,
744
745
  'host': "localhost",
745
746
  'port': 3121,
746
- 'tcl-file': "upload.tcl",
747
747
  'all-sv': False,
748
+ 'tcl-file': "eda_upload.tcl",
749
+ 'log-file': "eda_upload.log",
750
+ 'test-mode': False,
748
751
  })
749
752
  # TODO(drew): Add self.args_help.update({...})
750
753
 
@@ -825,7 +828,7 @@ class CommandUploadVivado(CommandUpload, ToolVivado):
825
828
 
826
829
  # ── Generate TCL script ───────────────────────────────────────────────────
827
830
  script_file = Path(self.args['tcl-file'])
828
- log_file = Path("eda_upload.log")
831
+ log_file = Path(self.args['log-file'])
829
832
 
830
833
  try:
831
834
  with script_file.open("w", encoding="utf-8") as fout:
@@ -924,6 +927,9 @@ class CommandUploadVivado(CommandUpload, ToolVivado):
924
927
  command_list.append('-notrace')
925
928
  self.exec(Path(util.getcwd()), command_list)
926
929
 
930
+ if not self.args['keep']:
931
+ os.unlink(self.args['tcl-file'])
932
+
927
933
  util.info("Upload done")
928
934
 
929
935
 
@@ -935,7 +941,7 @@ class CommandOpenVivado(CommandOpen, ToolVivado):
935
941
  def __init__(self, config: dict):
936
942
  CommandOpen.__init__(self, config)
937
943
  ToolVivado.__init__(self, config=self.config)
938
- # add args specific to this simulator
944
+ # add args specific to this tool
939
945
  self.args['gui'] = True
940
946
  self.args['file'] = False
941
947
  self.args['all-sv'] = False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opencos-eda
3
- Version: 0.2.46
3
+ Version: 0.2.47
4
4
  Summary: A simple Python package for wrapping RTL simuliatons and synthesis
5
5
  Author-email: Simon Sabato <simon@cognichip.ai>, Drew Ranck <drew@cognichip.ai>
6
6
  Project-URL: Homepage, https://github.com/cognichip/opencos
@@ -2,7 +2,7 @@
2
2
 
3
3
  [project]
4
4
  name = "opencos-eda"
5
- version = "0.2.46"
5
+ version = "0.2.47"
6
6
  dependencies = [
7
7
  # opencos/eda.py dependencies
8
8
  "mergedeep >= 1.3.4",
File without changes
File without changes
File without changes
File without changes