opencos-eda 0.2.45__py3-none-any.whl → 0.2.47__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_helpers.py CHANGED
@@ -68,6 +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', # default True
72
+ 'filepath-subst-target-dir', # default True
73
+ 'dirpath-subst-target-dir', # default False
71
74
  'var-subst-args',
72
75
  'var-subst-os-env',
73
76
  'tee',
@@ -383,24 +386,38 @@ def deps_list_target_sanitize(entry, default_key:str='deps', target_node:str='',
383
386
  assert False, f"Can't convert to list {entry=} {default_key=} {target_node=} {deps_file=}"
384
387
 
385
388
 
386
- 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
387
396
 
388
397
  # Look for path substitutions, b/c we later "work" in self.args['work-dir'], but
389
398
  # files should be relative to our target_path.
390
- for iter,word in enumerate(exec_list):
399
+ for i,word in enumerate(exec_list):
391
400
  m = re.search(r'(\.+\/+[^"\;\:\|\<\>\*]*)$', word)
392
401
  if m:
393
402
  # ./, ../, file=./../whatever It might be a filepath.
394
403
  # [^"\;\:\|\<\>\*] is looking for non-path like characters, so we dont' have a trailing
395
404
  # " : ; < > |
396
- # try and see if this file exists. Note that files in the self.args['work-dir'] don't
405
+ # try and see if this file or dir exists. Note that files in the self.args['work-dir'] don't
397
406
  # need this, and we can't assume dir levels in the work-dir.
398
407
  try:
399
408
  try_path = os.path.abspath(os.path.join(os.path.abspath(target_path), m.group(1)))
400
- if os.path.isfile(try_path):
409
+ if enable_filepath_subst and os.path.isfile(try_path):
401
410
  # make the substitution
402
- exec_list[iter] = word.replace(m.group(1), try_path)
403
- debug(f'path substitution {info_str=} {target_path=}: replaced - {word=} is now ={exec_list[iter]}')
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):
416
+ # make the substitution
417
+ exec_list[i] = word.replace(m.group(1), try_path)
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"')
404
421
  except:
405
422
  pass
406
423
 
@@ -1033,7 +1050,10 @@ class DepsProcessor:
1033
1050
 
1034
1051
 
1035
1052
 
1036
- 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:
1037
1057
  '''Returns None or a dict of a possible shell command from line (str)
1038
1058
 
1039
1059
  Examples of 'line' str:
@@ -1049,24 +1069,30 @@ def parse_deps_shell_str(line : str, target_path : str, target_node : str, enabl
1049
1069
  target_node (str) -- from dependency parsing, the target containing this 'line' str.
1050
1070
  '''
1051
1071
  if not enable:
1052
- return None
1072
+ return {}
1053
1073
 
1054
1074
  m = re.match(r'^\s*shell\@(.*)\s*$', line)
1055
1075
  if not m:
1056
- return None
1076
+ return {}
1057
1077
 
1058
1078
  exec_str = m.group(1)
1059
1079
  exec_list = exec_str.split()
1060
1080
 
1061
1081
  # Look for path substitutions, b/c we later "work" in self.args['work-dir'], but
1062
1082
  # files should be relative to our target_path.
1063
- 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
+ )
1064
1089
 
1065
- d = {'target_path': os.path.abspath(target_path),
1066
- 'target_node': target_node,
1067
- 'exec_list': exec_list,
1068
- }
1069
- 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
+ }
1070
1096
 
1071
1097
 
1072
1098
  def parse_deps_work_dir_add_srcs(line : str, target_path : str, target_node : str, enable : bool = True):
@@ -1098,8 +1124,12 @@ def parse_deps_work_dir_add_srcs(line : str, target_path : str, target_node : st
1098
1124
  return d
1099
1125
 
1100
1126
 
1101
- def parse_deps_peakrdl(line : str, target_path : str, target_node : str, enable : bool = True,
1102
- 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:
1103
1133
  '''Returns None or a dict describing a PeakRDL CSR register generator dependency
1104
1134
 
1105
1135
  Examples of 'line' str:
@@ -1137,12 +1167,12 @@ def parse_deps_peakrdl(line : str, target_path : str, target_node : str, enable
1137
1167
 
1138
1168
  sv_files = list()
1139
1169
  top = ''
1140
- for iter,str_value in enumerate(args_list):
1170
+ for i,str_value in enumerate(args_list):
1141
1171
  if '--top=' in str_value:
1142
1172
  _, top = str_value.split('=')
1143
1173
  elif '--top' in str_value:
1144
- if iter + 1 < len(args_list):
1145
- top = args_list[iter + 1]
1174
+ if i + 1 < len(args_list):
1175
+ top = args_list[i + 1]
1146
1176
 
1147
1177
  for str_item in args_list:
1148
1178
  if str_item[-4:] == '.rdl':
@@ -1170,10 +1200,13 @@ def parse_deps_peakrdl(line : str, target_path : str, target_node : str, enable
1170
1200
  # Make these look like a dep_shell_command:
1171
1201
  for one_cmd_as_list in shell_commands:
1172
1202
  ret_dict['shell_commands_list'].append(
1173
- parse_deps_shell_str(line = ' shell@ ' + ' '.join(one_cmd_as_list),
1174
- target_path = target_path,
1175
- target_node = target_node
1176
- )
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
+ )
1177
1210
  )
1178
1211
 
1179
1212
  # Make the work_dir_add_srcs dict:
@@ -1236,13 +1269,21 @@ def deps_commands_handler(config: dict, eda_args: dict,
1236
1269
 
1237
1270
  tee_fpath = command.get('tee', None)
1238
1271
 
1239
- for key,item in command.items():
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)
1240
1277
 
1241
- # skip the var-subst-* keys, since these types are bools
1242
- if key.startswith('var-subst'):
1243
- continue
1278
+ for key,item in command.items():
1244
1279
 
1245
- if key.startswith('tee'):
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']:
1246
1287
  continue
1247
1288
 
1248
1289
  # Optional variable substituion in commands
@@ -1253,15 +1294,18 @@ def deps_commands_handler(config: dict, eda_args: dict,
1253
1294
  if key == 'shell':
1254
1295
  # For now, piggyback on parse_deps_shell_str:
1255
1296
  ret_dict = parse_deps_shell_str(
1256
- line = 'shell@ ' + item,
1257
- target_path = target_path,
1258
- 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,
1259
1302
  enable=config['dep_command_enables']['shell'],
1260
1303
  )
1261
1304
  # To support 'tee: <some-file>' need to append it to last
1262
1305
  # list item in ret_dict['exec_list'], and make it a util.ShellCommandList.
1263
1306
  if tee_fpath:
1264
1307
  ret_dict['exec_list'] = ShellCommandList(ret_dict['exec_list'], tee_fpath=tee_fpath)
1308
+ ret_dict['run_from_work_dir'] = run_from_work_dir
1265
1309
  assert ret_dict, f'shell command failed in {dep=} {target_node=} in {deps_file=}'
1266
1310
  shell_commands_list.append(ret_dict) # process this later, append to our to-be-returned tuple
1267
1311
 
@@ -1283,6 +1327,8 @@ def deps_commands_handler(config: dict, eda_args: dict,
1283
1327
  line = 'peakrdl@ ' + item,
1284
1328
  target_path = target_path,
1285
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,
1286
1332
  enable=config['dep_command_enables']['peakrdl'],
1287
1333
  tool=eda_args.get('tool', '')
1288
1334
  )
opencos/deps_schema.py CHANGED
@@ -69,6 +69,14 @@ my_target_name:
69
69
  - shell: <---- string for shell command to be run
70
70
  var-subst-args: <---- bool, perform var substitution using args
71
71
  var-subst-os-env: <---- bool, perform var substitution using os.environ
72
+ run-from-work-dir: <---- bool, default True, if False runs from target dir
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).
72
80
  tee: <---- string, filename to write logs to
73
81
  - work-dir-add-sources: <---- work-dir-add-sources, optional list (or string)
74
82
  - some_file_gen_from_sh.sv <---- string filename that we created with sh command
@@ -150,6 +158,9 @@ DEPS_COMMANDS_LIST = [
150
158
  Optional('shell'): str,
151
159
  Optional('var-subst-args'): bool,
152
160
  Optional('var-subst-os-env'): bool,
161
+ Optional('run-from-work-dir'): bool,
162
+ Optional('filepath-subst-target-dir'): bool,
163
+ Optional('dirpath-subst-target-dir'): bool,
153
164
  Optional('tee'): Or(str, type(None)),
154
165
  },
155
166
  {
opencos/eda_base.py CHANGED
@@ -716,8 +716,9 @@ class CommandDesign(Command):
716
716
 
717
717
  log_fnames_count = {} # count per target_node.
718
718
 
719
- for iter, d in enumerate(self.dep_shell_commands):
719
+ for i, d in enumerate(self.dep_shell_commands):
720
720
  clist = util.ShellCommandList(d['exec_list'])
721
+ run_from_work_dir = d['run_from_work_dir'] # default True
721
722
  log = clist.tee_fpath
722
723
  target_node = d["target_node"]
723
724
  if clist.tee_fpath is None:
@@ -729,24 +730,38 @@ class CommandDesign(Command):
729
730
  all_cmds_lists += [
730
731
  [], # blank line
731
732
  # comment, where it came from, log to {node}__shell_{lognum}.log (or tee name from DEPS.yml)
732
- [f'# command {iter}: target: {d["target_path"]} : {target_node} --> {log}'],
733
- # actual command (list or util.ShellCommandList)
734
- clist,
733
+ [f'# command {i}: target: {d["target_path"]} : {target_node} --> {log}'],
735
734
  ]
735
+ if not run_from_work_dir:
736
+ all_cmds_lists.append([f'cd {d["target_path"]}'])
737
+
738
+ # actual command (list or util.ShellCommandList)
739
+ all_cmds_lists.append(clist)
740
+
741
+ if not run_from_work_dir:
742
+ all_cmds_lists.append([f'cd {os.path.abspath(self.args["work-dir"])}'])
743
+
736
744
  d['exec_list'] = clist # update to tee_fpath is set.
737
745
 
738
746
  util.write_shell_command_file(dirpath=self.args['work-dir'], filename='pre_compile_dep_shell_commands.sh',
739
747
  command_lists=all_cmds_lists)
740
748
 
741
- for iter,d in enumerate(self.dep_shell_commands):
742
- util.info(f'run_dep_shell_commands {iter=}: {d=}')
749
+ for i,d in enumerate(self.dep_shell_commands):
750
+ util.info(f'run_dep_shell_commands {i=}: {d=}')
743
751
  clist = util.ShellCommandList(d['exec_list'])
752
+ tee_fpath=clist.tee_fpath
753
+ if d['run_from_work_dir']:
754
+ run_from_dir = self.args['work-dir']
755
+ else:
756
+ # Run from the target's directory (not the `eda` caller $PWD)
757
+ run_from_dir = d["target_path"]
758
+ tee_fpath = os.path.abspath(os.path.join(self.args['work-dir'], tee_fpath))
744
759
  # NOTE(drew): shell=True subprocess call, can disable with self.config
745
760
  if sys.platform.startswith('win'):
746
761
  # for Windows, we run shell=True otherwise most built-in cmd.exe calls won't work.
747
- self.exec(self.args['work-dir'], clist, tee_fpath=clist.tee_fpath, shell=True)
762
+ self.exec(run_from_dir, clist, tee_fpath=tee_fpath, shell=True)
748
763
  else:
749
- self.exec(self.args['work-dir'], clist, tee_fpath=clist.tee_fpath,
764
+ self.exec(run_from_dir, clist, tee_fpath=tee_fpath,
750
765
  shell=self.config.get('deps_subprocess_shell', False))
751
766
 
752
767
  def update_file_lists_for_work_dir(self):
@@ -766,10 +781,10 @@ class CommandDesign(Command):
766
781
  my_file_lists_list = [self.files_v, self.files_sv, self.files_vhd, self.files_cpp,
767
782
  self.files_sdc]
768
783
  for my_file_list in my_file_lists_list:
769
- for iter,value in enumerate(my_file_list):
784
+ for i,value in enumerate(my_file_list):
770
785
  if value and type(value) is str and value.startswith(self._work_dir_add_srcs_path_string):
771
786
  new_value = os.path.join(work_dir_abspath, value[_work_dir_add_srcs_path_string_len :])
772
- my_file_list[iter] = new_value
787
+ my_file_list[i] = new_value
773
788
  util.debug(f"file lists: replaced {value} with {new_value}")
774
789
 
775
790
  def update_non_source_files_in_work_dir(self):
@@ -1575,10 +1590,10 @@ class CommandParallel(Command):
1575
1590
  else:
1576
1591
  util.info(f"Parallel: <No jobs found>")
1577
1592
  # Make sure all jobs have a set status:
1578
- for iter,rc in enumerate(self.jobs_status):
1593
+ for i,rc in enumerate(self.jobs_status):
1579
1594
  if rc is None or type(rc) != int:
1580
- self.error(f'job {iter=} {rc=} did not return a proper return code')
1581
- jobs_status[iter] = 1
1595
+ self.error(f'job {i=} {rc=} did not return a proper return code')
1596
+ jobs_status[i] = 1
1582
1597
 
1583
1598
  # if self.status > 0, then keep it non-zero, else set it if we still have running jobs.
1584
1599
  if self.status == 0:
@@ -62,6 +62,7 @@ file_extensions:
62
62
  - .vhdl
63
63
  cpp:
64
64
  - .cpp
65
+ - .cc
65
66
  synth_constraints:
66
67
  - .sdc
67
68
  - .xdc
@@ -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']
opencos/tools/vivado.py CHANGED
@@ -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.45
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
@@ -1,12 +1,12 @@
1
1
  opencos/__init__.py,sha256=ZQ7aOCbP0jkIMYGdVrb-mkZX3rnvaK8epBkmp506tXU,85
2
2
  opencos/_version.py,sha256=qN7iBoOv-v4tEZz-Pu9sVUJwefshJOsgdaddn8HcHio,510
3
3
  opencos/_waves_pkg.sv,sha256=1lbhQOVGc3t_R8czYjP40hssP0I3FlZOpHTkI7yKFbI,1251
4
- opencos/deps_helpers.py,sha256=jIMYDp9BVwEl9gYUcVie19EHqO5-DRY-d-vSqaDKi4Y,56971
5
- opencos/deps_schema.py,sha256=MhytzXwp071F14RwxqHt78ak8Qruoe4FeK5XSzkO2f0,14658
4
+ opencos/deps_helpers.py,sha256=iFUMnrh8hiNflRgZWp0hid7x6BKk1P2PegUn_gJS8Z0,59452
5
+ opencos/deps_schema.py,sha256=ECysiiagTGXAtAVp2GnW3N_Iw2ZakYEuSEg-WUWtUKo,15469
6
6
  opencos/eda.py,sha256=Ky_Uc47TU1N6lRs06eatdpAvtgoSh0iXO0BxhSfEuk0,19420
7
- opencos/eda_base.py,sha256=RY32yrUyUpGUaDN4y5SIv54osV57K4r9zs4lIGsYJCY,83784
7
+ opencos/eda_base.py,sha256=utUTieQMv0RC2Mz5n8b7rtneKjSFI3YcgCiJON0T7Ws,84410
8
8
  opencos/eda_config.py,sha256=8wwX4PTZ5rmxWogrVxxqAY6adQFPxTsFkkTYbo6H4vU,8853
9
- opencos/eda_config_defaults.yml,sha256=7apbA6F0HS-9qC6pOiM128qDf29It0U_ZKxntYSuGUg,11525
9
+ opencos/eda_config_defaults.yml,sha256=AteZbwRJ6wviinks47-e5TX0DoU0culJfBw6L3xYOOA,11535
10
10
  opencos/eda_config_max_verilator_waivers.yml,sha256=lTAU4IOEbUWVlPzuer1YYhIyxpPINeA4EJqcRIT-Ymk,840
11
11
  opencos/eda_config_reduced.yml,sha256=cQ9jY4J7EvAbeHTiP6bvpDSVJAYiitjLZPSxxLKIEbk,1440
12
12
  opencos/eda_deps_bash_completion.bash,sha256=jMkQKY82HBgOnQeMdA1hMrXguRFtB52SMBxUemKovL4,1958
@@ -41,7 +41,7 @@ opencos/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
41
  opencos/tests/custom_config.yml,sha256=TRoVM9ZFKPOA_8JmlpzaMhnGO1txmaD14N_8P1oqzew,257
42
42
  opencos/tests/helpers.py,sha256=r4UYMckYzHY2i2RbSWvysOjerPhty_7i7RB-Z767M-c,8294
43
43
  opencos/tests/test_build.py,sha256=FQAxOpLVQShAHD_L5rqJctPeSAoqoOCNFI0RXflLuY0,387
44
- opencos/tests/test_deps_helpers.py,sha256=_nJSgLN6WVlMKqu6sCr29gjQyN3Jj-dVk8Ac64ygpJs,5928
44
+ opencos/tests/test_deps_helpers.py,sha256=_C5qH1YuScCCvG3E-Lr8aS_n6C6YKgEl-wIycJEFLRY,7697
45
45
  opencos/tests/test_deps_schema.py,sha256=T3P9KjaMyKsk8b7snNVvNSsom2hIJcg6Z9apYiXoH9Y,941
46
46
  opencos/tests/test_eda.py,sha256=tplHcx4FiEn8Jmw1mJMlD6tGjpUJ6cxdBGiVRKo7Ykw,38809
47
47
  opencos/tests/test_eda_elab.py,sha256=75bJpOaoO8rn1FXFxiE4KSu5FdjZP1IbW6SyTCjM_ao,2553
@@ -68,12 +68,12 @@ opencos/tools/slang_yosys.py,sha256=3fyLRRdTXhSppNtUhhUl00oG-cT9TyyPTH6JvasS9ZE,
68
68
  opencos/tools/surelog.py,sha256=XhxJCGt8hyligL0LNT1fCWkHF5pkt4WSp3eqVJlQ4uA,4998
69
69
  opencos/tools/tabbycad_yosys.py,sha256=2LePPgYXBVdsy7YcffPIWN-I0B7queLQ_f_pme2SCGw,7803
70
70
  opencos/tools/verilator.py,sha256=dWnoO8FUvjdMyFmuTjHvC_XYI_zwjApJApYy7iYubf0,18398
71
- opencos/tools/vivado.py,sha256=_GVqKNIZt9CZeiXS5yZCWTFrhD3BKjcQfzhhxR1qLQM,40017
71
+ opencos/tools/vivado.py,sha256=D0we45_2M5dr7Dp6FBjSaXxYmRpgJWm4rq3dc23Uv1A,40219
72
72
  opencos/tools/yosys.py,sha256=FV43RcejyFir4B24WRShnzUoppJMK0sDDNkSlIX8Vew,25579
73
- opencos_eda-0.2.45.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
74
- opencos_eda-0.2.45.dist-info/licenses/LICENSE.spdx,sha256=8gn1610RMP6eFgT3Hm6q9VKXt0RvdTItL_oxMo72jII,189
75
- opencos_eda-0.2.45.dist-info/METADATA,sha256=MNMQxXKjmHYdAEIike4YdzaCEQeaqld1hPo4GLQk8PY,604
76
- opencos_eda-0.2.45.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
77
- opencos_eda-0.2.45.dist-info/entry_points.txt,sha256=V8OE1lySAFcFQpDNJuVxVZteeSmDH-joLMhGvrxrvmg,164
78
- opencos_eda-0.2.45.dist-info/top_level.txt,sha256=J4JDP-LpRyJqPNeh9bSjx6yrLz2Mk0h6un6YLmtqql4,8
79
- opencos_eda-0.2.45.dist-info/RECORD,,
73
+ opencos_eda-0.2.47.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
74
+ opencos_eda-0.2.47.dist-info/licenses/LICENSE.spdx,sha256=8gn1610RMP6eFgT3Hm6q9VKXt0RvdTItL_oxMo72jII,189
75
+ opencos_eda-0.2.47.dist-info/METADATA,sha256=VNi89oYQGS94RsyWbns7hETc1o9STz57mwYYGvXXEi4,604
76
+ opencos_eda-0.2.47.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
77
+ opencos_eda-0.2.47.dist-info/entry_points.txt,sha256=V8OE1lySAFcFQpDNJuVxVZteeSmDH-joLMhGvrxrvmg,164
78
+ opencos_eda-0.2.47.dist-info/top_level.txt,sha256=J4JDP-LpRyJqPNeh9bSjx6yrLz2Mk0h6un6YLmtqql4,8
79
+ opencos_eda-0.2.47.dist-info/RECORD,,