opencos-eda 0.2.44__py3-none-any.whl → 0.2.46__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/tests/test_eda.py CHANGED
@@ -692,14 +692,22 @@ class TestDepsReqs:
692
692
  assert rc != 0
693
693
 
694
694
 
695
- @pytest.mark.skipif(not can_run_eda_sim(), reason='no tool found to handle command: sim')
696
- def test_deps_command_order():
695
+ @pytest.mark.parametrize("command", ['sim', 'shell'])
696
+ def test_deps_command_order(command):
697
697
  '''Test for various "commands" within a DEPS target. This test checks that command
698
698
  order is preserved in the top-to-bottom deps order, meaning that eda.py has to collect
699
699
  all commands deps order, and then execute them in that order.'''
700
700
 
701
701
  chdir_remove_work_dir('deps_files/command_order')
702
- cmd_list = 'sim --stop-before-compile target_test'.split()
702
+ if command == 'sim' and not can_run_eda_sim():
703
+ pytest.skip(f'sim skipped, {can_run_eda_sim()=}')
704
+ return # skip/pass
705
+
706
+ if command == 'shell':
707
+ cmd_list = 'shell target_test'.split()
708
+ else:
709
+ cmd_list = 'sim --stop-before-compile target_test'.split()
710
+
703
711
  with open('eda.log', 'w', encoding='utf-8') as f:
704
712
  with redirect_stdout(f):
705
713
  with redirect_stderr(f):
@@ -730,14 +738,16 @@ def test_deps_command_order():
730
738
  # Added check, we redirected to create eda.log earlier to confirm the targets worked,
731
739
  # but as a general eda.py check, all shell commands should create their own
732
740
  # {target}__shell_0.log file:
733
- work_dir = os.path.join(THISPATH, 'deps_files/command_order', 'eda.work', 'target_test.sim')
741
+ work_dir = os.path.join(
742
+ THISPATH, 'deps_files', 'command_order', 'eda.work', f'target_test.{command}'
743
+ )
734
744
  with open(os.path.join(work_dir, 'target_echo_hi__shell_0.log'), encoding='utf-8') as f:
735
745
  text = ''.join(f.readlines()).strip()
736
- assert text == 'hi'
746
+ assert text in ['hi', '"hi"', '\\"hi\\"']
737
747
  # Added check, one of the targets uses a custom 'tee' file name, instead of the default log.
738
748
  with open(os.path.join(work_dir, 'custom_tee_echo_bye.log'), encoding='utf-8') as f:
739
749
  text = ''.join(f.readlines()).strip()
740
- assert text == 'bye'
750
+ assert text in ['bye', '"bye"', '\\"bye\\"']
741
751
 
742
752
 
743
753
  @pytest.mark.skipif('verilator' not in tools_loaded, reason="requires verilator")
@@ -896,9 +906,9 @@ class TestDepsTags(Helpers):
896
906
  # b/c that should only apply in 'verilator' for this target.)
897
907
  exec_lines = self.get_log_lines_with('exec: ', logfile=logfile)
898
908
  assert len(exec_lines) == 3
899
- assert 'xvlog ' in exec_lines[0]
900
- assert 'xelab ' in exec_lines[1]
901
- assert 'xsim ' in exec_lines[2]
909
+ assert 'xvlog' in exec_lines[0]
910
+ assert 'xelab' in exec_lines[1]
911
+ assert 'xsim' in exec_lines[2]
902
912
  assert not self.is_in_log('--lint-only', logfile=logfile)
903
913
 
904
914
 
@@ -51,7 +51,7 @@ class CommandSynthInvioYosys(CommonSynthYosys, ToolInvioYosys):
51
51
  'invio-blackbox': 'List of modules that invio will blackbox prior to yosys',
52
52
  })
53
53
 
54
- def write_and_run_yosys_f_files(self, **kwargs) -> None:
54
+ def write_and_run_yosys_f_files(self) -> None:
55
55
 
56
56
  # Use helper module for Invio/Verific to save out Verilog-2001 from our
57
57
  # Verilog + SystemVerilog + VHDL file lists.
@@ -104,7 +104,7 @@ class CommandSynthInvioYosys(CommonSynthYosys, ToolInvioYosys):
104
104
  )
105
105
 
106
106
  # Optinally create and run a sta.f:
107
- sta_command_list = self.create_sta_f() # [] or util.ShellCommandList
107
+ sta_command_lists = self.create_sta_f() # [] or [util.ShellCommandList]
108
108
 
109
109
  # We create a run_yosys.sh wrapping these scripts, but we do not run this one.
110
110
  util.write_shell_command_file(
@@ -122,8 +122,7 @@ class CommandSynthInvioYosys(CommonSynthYosys, ToolInvioYosys):
122
122
  # Gives us bash commands with tee and pipstatus:
123
123
  invio_command_list,
124
124
  synth_command_list,
125
- sta_command_list,
126
- ],
125
+ ] + sta_command_lists,
127
126
  )
128
127
 
129
128
  # Do not run this if args['stop-before-compile'] is True
@@ -135,9 +134,10 @@ class CommandSynthInvioYosys(CommonSynthYosys, ToolInvioYosys):
135
134
  self.exec( work_dir=work_dir, command_list=synth_command_list,
136
135
  tee_fpath=synth_command_list.tee_fpath )
137
136
 
138
- if self.args['sta']:
139
- self.exec(work_dir=self.full_work_dir, command_list=sta_command_list,
140
- tee_fpath=sta_command_list.tee_fpath)
137
+ for x in sta_command_lists:
138
+ if self.args['sta'] and x:
139
+ self.exec(work_dir=self.full_work_dir, command_list=x,
140
+ tee_fpath=x.tee_fpath)
141
141
 
142
142
  if self.status == 0:
143
143
  util.info(f'yosys: wrote verilog to {self.yosys_v_path}')
@@ -8,7 +8,7 @@ Contains classes for ToolSlangYosys, CommandSynthSlangYosys
8
8
  import os
9
9
 
10
10
  from opencos import util
11
- from opencos.tools.yosys import ToolYosys, CommonSynthYosys
11
+ from opencos.tools.yosys import ToolYosys, CommonSynthYosys, CommandLecYosys
12
12
 
13
13
  class ToolSlangYosys(ToolYosys):
14
14
  '''Uses slang.so in yosys plugins directory, called via yosys > plugin -i slang'''
@@ -37,7 +37,7 @@ class CommandSynthSlangYosys(CommonSynthYosys, ToolSlangYosys):
37
37
  self.slang_out_dir = ''
38
38
  self.slang_v_path = ''
39
39
 
40
- def write_and_run_yosys_f_files(self, **kwargs) -> None:
40
+ def write_and_run_yosys_f_files(self) -> None:
41
41
  '''
42
42
  1. Creates and runs: yosys.slang.f
43
43
  -- should create post_slang_ls.txt
@@ -54,7 +54,7 @@ class CommandSynthSlangYosys(CommonSynthYosys, ToolSlangYosys):
54
54
  self.blackbox_list += self.args.get('synth-blackbox', [])
55
55
  util.debug(f'slang_yosys: {self.blackbox_list=}')
56
56
 
57
- # create {work_dir} / yosys
57
+ # create {work_dir} / slang
58
58
  self.slang_out_dir = os.path.join(self.full_work_dir, 'slang')
59
59
  util.safe_mkdir(self.slang_out_dir)
60
60
 
@@ -62,13 +62,13 @@ class CommandSynthSlangYosys(CommonSynthYosys, ToolSlangYosys):
62
62
 
63
63
  # Run our created yosys.slang.f script
64
64
  # Note - this will always run, even if --stop-before-compile is set.
65
- slang_command_list = self._create_yosys_slang_f() # util.ShellCommandList
65
+ slang_command_list = self._create_and_run_yosys_slang_f() # util.ShellCommandList
66
66
 
67
67
  # Create and run yosys.synth.f
68
68
  synth_command_list = self.create_yosys_synth_f() # util.ShellCommandList
69
69
 
70
70
  # Optinally create and run a sta.f:
71
- sta_command_list = self.create_sta_f() # [] or util.ShellCommandList
71
+ sta_command_lists = self.create_sta_f() # [] or [util.ShellCommandList]
72
72
 
73
73
  # We create a run_yosys.sh wrapping these scripts, but we do not run this one.
74
74
  util.write_shell_command_file(
@@ -78,8 +78,7 @@ class CommandSynthSlangYosys(CommonSynthYosys, ToolSlangYosys):
78
78
  # Gives us bash commands with tee and pipstatus:
79
79
  slang_command_list,
80
80
  synth_command_list,
81
- sta_command_list,
82
- ],
81
+ ] + sta_command_lists,
83
82
  )
84
83
 
85
84
  # Do not run this if args['stop-before-compile'] is True
@@ -92,9 +91,10 @@ class CommandSynthSlangYosys(CommonSynthYosys, ToolSlangYosys):
92
91
  self.exec(work_dir=self.full_work_dir, command_list=synth_command_list,
93
92
  tee_fpath=synth_command_list.tee_fpath)
94
93
 
95
- if self.args['sta']:
96
- self.exec(work_dir=self.full_work_dir, command_list=sta_command_list,
97
- tee_fpath=sta_command_list.tee_fpath)
94
+ for x in sta_command_lists:
95
+ if self.args['sta'] and x:
96
+ self.exec(work_dir=self.full_work_dir, command_list=x,
97
+ tee_fpath=x.tee_fpath)
98
98
 
99
99
  if self.status == 0:
100
100
  util.info(f'yosys: wrote verilog to {self.yosys_v_path}')
@@ -108,36 +108,13 @@ class CommandSynthSlangYosys(CommonSynthYosys, ToolSlangYosys):
108
108
  '--best-effort-hierarchy',
109
109
  ]
110
110
 
111
- for name,value in self.defines.items():
112
- if not name:
113
- continue
114
- if name in ['SIMULATION']:
115
- continue
116
-
117
- if value is None:
118
- read_slang_cmd.append(f'--define-macro {name}')
119
- else:
120
- read_slang_cmd.append(f'--define-macro {name}={value}')
121
-
122
- # We must define SYNTHESIS for oclib_defines.vh to work correctly.
123
- if 'SYNTHESIS' not in self.defines:
124
- read_slang_cmd.append('--define-macro SYNTHESIS')
125
-
126
- for path in self.incdirs:
127
- read_slang_cmd.append(f'-I {path}')
128
-
129
- for path in self.files_v:
130
- read_slang_cmd.append(path)
131
-
132
- for path in self.files_sv:
133
- read_slang_cmd.append(path)
134
-
111
+ read_slang_cmd += self.get_yosys_read_verilog_defines_incdirs_files()
135
112
  read_slang_cmd.append(f'--top {self.args["top"]}')
136
113
  return ' '.join(read_slang_cmd)
137
114
 
138
115
 
139
- def _create_yosys_slang_f(self) -> util.ShellCommandList:
140
- '''Returns the util.ShellCommandList for: yosys --scriptfile yosys.slang.f'''
116
+ def _create_and_run_yosys_slang_f(self) -> util.ShellCommandList:
117
+ '''Runs, and Returns the util.ShellCommandList for: yosys --scriptfile yosys.slang.f'''
141
118
 
142
119
  script_slang_lines = [
143
120
  'plugin -i slang'
@@ -181,7 +158,7 @@ class CommandSynthSlangYosys(CommonSynthYosys, ToolSlangYosys):
181
158
  )
182
159
  return slang_command_list
183
160
 
184
- def _get_yosys_blackbox_list(self) -> list:
161
+ def get_yosys_blackbox_list(self) -> list:
185
162
  '''Based on the results in post_slang_ls.txt, create blackbox commands for
186
163
 
187
164
  yosys.synth.f script. Uses self.blackbox_list.
@@ -206,12 +183,14 @@ class CommandSynthSlangYosys(CommonSynthYosys, ToolSlangYosys):
206
183
  return yosys_blackbox_list
207
184
 
208
185
  def create_yosys_synth_f(self) -> util.ShellCommandList:
186
+ '''Overriden from CommonSynthYosys'''
187
+
209
188
  # Create yosys.synth.f
210
189
  yosys_synth_f_path = os.path.join(self.full_work_dir, 'yosys.synth.f')
211
190
 
212
191
  # Based on the results in post_slang_ls.txt, create blackbox commands for
213
192
  # yosys.synth.f script.
214
- yosys_blackbox_list = self._get_yosys_blackbox_list()
193
+ yosys_blackbox_list = self.get_yosys_blackbox_list()
215
194
 
216
195
  if self.args['liberty-file'] and not os.path.exists(self.args['liberty-file']):
217
196
  self.error(f'--liberty-file={self.args["liberty-file"]} file does not exist')
@@ -251,3 +230,15 @@ class CommandElabSlangYosys(CommandSynthSlangYosys): # pylint: disable=too-many-
251
230
  'stop-before-compile': True,
252
231
  'lint': True
253
232
  })
233
+
234
+ class CommandLecSlangYosys(CommandLecYosys, ToolSlangYosys): # pylint: disable=too-many-ancestors
235
+ '''CommandHandler for: eda lec --tool=slang_yosys
236
+
237
+ All steps from CommandLecYosys are re-used, except that using ToolSlangYosys
238
+ instead of ToolYosys. This is necessary so the default --synth arg will
239
+ synthesize the two designs using slang_yosys for the tool instead of yosys.
240
+ '''
241
+
242
+ def __init__(self, config: dict):
243
+ CommandLecYosys.__init__(self, config)
244
+ ToolSlangYosys.__init__(self, config=self.config)
@@ -36,7 +36,7 @@ class CommandSynthTabbyCadYosys(CommonSynthYosys, ToolTabbyCadYosys):
36
36
  ToolTabbyCadYosys.__init__(self, config=self.config)
37
37
 
38
38
 
39
- def write_and_run_yosys_f_files(self, **kwargs) -> None:
39
+ def write_and_run_yosys_f_files(self) -> None:
40
40
  '''
41
41
  1. Creates and runs: yosys.verific.f
42
42
  -- should create post_verific_ls.txt
opencos/tools/vivado.py CHANGED
@@ -649,10 +649,10 @@ class CommandBuildVivado(CommandBuild, ToolVivado):
649
649
  eda_path = eda_base.get_eda_exec('flist')
650
650
  command_list = [
651
651
  eda_path, 'flist',
652
- '--tool', self.args['tool'],
652
+ '--tool=' + self.args['tool'],
653
653
  self.args['top-path'],
654
654
  '--force',
655
- '--out', flist_file,
655
+ '--out=' + flist_file,
656
656
  #'--no-emit-incdir',
657
657
  #'--no-single-quote-define', # Needed to run in Command.exec( ... shell=False)
658
658
  '--no-quote-define',
@@ -662,11 +662,11 @@ class CommandBuildVivado(CommandBuild, ToolVivado):
662
662
  '--no-equal-define',
663
663
  '--bracket-quote-path',
664
664
  # on --prefix- items, use shlex.quote(str) so spaces work with subprocess shell=False:
665
- '--prefix-incdir', shlex.quote("oc_set_project_incdir "),
666
- '--prefix-define', shlex.quote("oc_set_project_define "),
667
- '--prefix-sv', shlex.quote("add_files -norecurse "),
668
- '--prefix-v', shlex.quote("add_files -norecurse "),
669
- '--prefix-vhd', shlex.quote("add_files -norecurse "),
665
+ '--prefix-incdir=' + shlex.quote("oc_set_project_incdir "),
666
+ '--prefix-define=' + shlex.quote("oc_set_project_define "),
667
+ '--prefix-sv=' + shlex.quote("add_files -norecurse "),
668
+ '--prefix-v=' + shlex.quote("add_files -norecurse "),
669
+ '--prefix-vhd=' + shlex.quote("add_files -norecurse "),
670
670
  ]
671
671
  for key,value in self.defines.items():
672
672
  if value is None:
@@ -674,6 +674,7 @@ class CommandBuildVivado(CommandBuild, ToolVivado):
674
674
  else:
675
675
  command_list += [ shlex.quote(f"+define+{key}={value}") ]
676
676
  cwd = util.getcwd()
677
+ util.debug(f"CommandBuildVivado: {cwd=}")
677
678
 
678
679
 
679
680
  # Write out a .sh command, but only for debug, it is not run.