opencos-eda 0.3.8__py3-none-any.whl → 0.3.10__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.
Files changed (42) hide show
  1. opencos/commands/deps_help.py +40 -21
  2. opencos/commands/sim.py +0 -1
  3. opencos/deps/deps_file.py +82 -79
  4. opencos/eda.py +108 -17
  5. opencos/eda_base.py +8 -4
  6. opencos/eda_config.py +8 -1
  7. opencos/eda_config_defaults.yml +14 -5
  8. opencos/eda_deps_bash_completion.bash +37 -15
  9. opencos/tools/modelsim_ase.py +19 -378
  10. opencos/tools/questa.py +42 -247
  11. opencos/tools/questa_common.py +480 -0
  12. opencos/tools/questa_fe.py +84 -0
  13. opencos/tools/questa_fse.py +7 -8
  14. opencos/tools/riviera.py +27 -10
  15. opencos/tools/verilator.py +1 -0
  16. opencos/utils/str_helpers.py +7 -0
  17. opencos/utils/vsim_helper.py +53 -21
  18. {opencos_eda-0.3.8.dist-info → opencos_eda-0.3.10.dist-info}/METADATA +2 -1
  19. {opencos_eda-0.3.8.dist-info → opencos_eda-0.3.10.dist-info}/RECORD +24 -40
  20. {opencos_eda-0.3.8.dist-info → opencos_eda-0.3.10.dist-info}/entry_points.txt +1 -0
  21. opencos/tests/__init__.py +0 -0
  22. opencos/tests/custom_config.yml +0 -13
  23. opencos/tests/deps_files/command_order/DEPS.yml +0 -44
  24. opencos/tests/deps_files/error_msgs/DEPS.yml +0 -55
  25. opencos/tests/deps_files/iverilog_test/DEPS.yml +0 -4
  26. opencos/tests/deps_files/no_deps_here/DEPS.yml +0 -0
  27. opencos/tests/deps_files/non_sv_reqs/DEPS.yml +0 -50
  28. opencos/tests/deps_files/tags_with_tools/DEPS.yml +0 -54
  29. opencos/tests/deps_files/test_err_fatal/DEPS.yml +0 -4
  30. opencos/tests/helpers.py +0 -354
  31. opencos/tests/test_build.py +0 -12
  32. opencos/tests/test_deps_helpers.py +0 -207
  33. opencos/tests/test_deps_schema.py +0 -30
  34. opencos/tests/test_eda.py +0 -921
  35. opencos/tests/test_eda_elab.py +0 -110
  36. opencos/tests/test_eda_synth.py +0 -150
  37. opencos/tests/test_oc_cli.py +0 -25
  38. opencos/tests/test_tools.py +0 -404
  39. {opencos_eda-0.3.8.dist-info → opencos_eda-0.3.10.dist-info}/WHEEL +0 -0
  40. {opencos_eda-0.3.8.dist-info → opencos_eda-0.3.10.dist-info}/licenses/LICENSE +0 -0
  41. {opencos_eda-0.3.8.dist-info → opencos_eda-0.3.10.dist-info}/licenses/LICENSE.spdx +0 -0
  42. {opencos_eda-0.3.8.dist-info → opencos_eda-0.3.10.dist-info}/top_level.txt +0 -0
@@ -1,14 +1,34 @@
1
1
  #!/usr/bin/env bash
2
2
 
3
3
  # How to use?
4
- # 1) copy this script locally and source it.
4
+ # 1) run:
5
+ # eda_show_autocomplete
6
+ # for instructions, will likely show you the location of this file,
7
+ # eda_deps_bash_completion.bash, for you to source. Does not require uv.
8
+ #
9
+ # 2) Given the result from (1), and if you use uv, add the following to your
10
+ # ~/.bashrc:
11
+ # # Make sure 'eda' is a valid executable when not in a venv:
12
+ # if ! type -P "eda" &>/dev/null; then
13
+ # uv tool install --python 3.14 opencos-eda >/dev/null 2>&1
14
+ # echo "uv tool installed opencos-eda"
15
+ # fi
16
+ # if [ -f PATH-FROM-STEP-1 ]; then
17
+ # . PATH-FROM-STEP-1
18
+ # fi
19
+ #
20
+ # 3) copy this script locally and source it.
5
21
  # For example:
6
22
  # > source ~/sh/eda_deps_bash_completion.bash
7
- # You can put this in your .bashrc.
8
- # 2) From you venv activate script:
9
- # (bottom of activate script, assuming python3.10):
23
+ # You can put this in your .bashrc. Note you will need a venv active or
24
+ # "eda" isn't in your path yet.
25
+ #
26
+ # 4) Have it sourced when you start your venv. Note this doesn't play as nicely
27
+ # with "uv" due to having a less stable .venv, but you can add this to your
28
+ # VENV_NAME/bin/activate script:
29
+ # (bottom of activate script, assuming python3.XX):
10
30
  # script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
11
- # . $script_dir/../lib/python3.10/site-packages/opencos/eda_deps_bash_completion.bash
31
+ # . $script_dir/../lib/python3.XX/site-packages/opencos/eda_deps_bash_completion.bash
12
32
 
13
33
 
14
34
  # scripts via pyproject.toml:
@@ -17,6 +37,15 @@ SCRIPT_NAME="eda"
17
37
  # how we get the completion targets:
18
38
  EXTRACTION_SCRIPT_NAME="eda_targets"
19
39
 
40
+ EDA_WORDS="sim lint elab synth flist proj multi tools-multi sweep build \
41
+ waves upload open export shell targets lec \
42
+ +define+ +incdirs+ \
43
+ --help --quiet --verbose --debug \
44
+ --tool --seed --top --keep --force --fake --lint --work-dir \
45
+ --stop-before-compile --stop-after-compile --stop-before-elaborate \
46
+ --export --export-run --export-json \
47
+ "
48
+
20
49
  _eda_script_completion() {
21
50
 
22
51
  # Set up for additional completions
@@ -28,22 +57,15 @@ _eda_script_completion() {
28
57
  if [[ $(type -P "$EXTRACTION_SCRIPT_NAME") ]]; then
29
58
  keys=$("$EXTRACTION_SCRIPT_NAME" "$cur")
30
59
  if [[ -n "$keys" ]]; then
31
- completions=($(compgen -W "$keys" -- "$cur"))
60
+ completions=($(compgen -W "$keys $EDA_WORDS" -- "$cur"))
32
61
  fi
33
62
  fi
34
63
 
35
64
  if [ -z "${completions}" ]; then
36
65
  # If we didn't find anything in a DEPS.[yml|yaml|toml|json], then use:
37
- # 1. a bunch of known eda words or args.
38
- eda_words="multi sim elab flist build synth waves proj waves targets \
39
- +define+ +incdirs+ \
40
- --help --quiet --verbose --debug \
41
- --tool --seed --top --keep --force --fake --lint --work-dir \
42
- --stop-before-compile --stop-after-compile --stop-before-elaborate \
43
- --export --export-run --export-json \
44
- "
66
+ # -- a bunch of known eda words or args.
45
67
  # 2. a glob the current word to mimic normal bash:
46
- completions=($(compgen -W "${eda_words}" -G "${cur}*" -- "$cur"))
68
+ completions=($(compgen -W "$EDA_WORDS" -G "${cur}*" -- "$cur"))
47
69
  fi
48
70
 
49
71
  COMPREPLY=("${completions[@]}")
@@ -9,31 +9,29 @@ Note that this is for 32-bit Modelsim Student Edition. Consider using --tool=que
9
9
 
10
10
  import os
11
11
 
12
- from opencos import util
13
- from opencos.commands import sim, CommandSim
14
- from opencos.tools.questa import ToolQuesta
15
- from opencos.utils.str_helpers import sanitize_defines_for_sh
12
+ from opencos.tools.questa_common import CommonSimQuesta, CommonFListQuesta
16
13
 
17
- class ToolModelsimAse(ToolQuesta):
18
- '''ToolModelsimAse used by opencos.eda for --tool=modelsim_ase'''
14
+ class CommandSimModelsimAse(CommonSimQuesta):
15
+ '''CommandSimModelsimAse is a command handler for: eda sim --tool=modelsim_ase'''
19
16
 
20
- _TOOL = 'modelsim_ase' # otherwise it's 'questa' from base class.
17
+ _TOOL = 'modelsim_ase'
21
18
  _EXE = 'vsim'
22
19
  use_vopt = False
23
20
 
24
- class CommandSimModelsimAse(CommandSim, ToolModelsimAse):
25
- '''CommandSimModelsimAse is a command handler for: eda sim --tool=modelsim_ase'''
26
-
27
21
  def __init__(self, config: dict):
28
- CommandSim.__init__(self, config=config)
29
- ToolModelsimAse.__init__(self, config=self.config)
22
+ CommonSimQuesta.__init__(self, config=config)
23
+
24
+ # repairs: override self._TOOL, and run get_versions() again.
25
+ self._TOOL = 'modelsim_ase'
26
+
30
27
  self.shell_command = os.path.join(self.sim_exe_base_path, 'vsim')
31
28
  self.starter_edition = True
32
29
  self.args.update({
33
30
  'tool': self._TOOL, # override
34
31
  'gui': False,
35
- 'vopt': self.use_vopt,
36
32
  })
33
+
34
+
37
35
  self.args_help.update({
38
36
  'vopt': (
39
37
  'Boolean to enable/disable use of vopt step prior to vsim step'
@@ -53,371 +51,6 @@ class CommandSimModelsimAse(CommandSim, ToolModelsimAse):
53
51
  )
54
52
  )
55
53
 
56
- def run_in_batch_mode(self) -> bool:
57
- '''Returns bool if we should run in batch mode (-c) from command line'''
58
- # TODO(drew): make CommandSimQuesta a parent and inherit this method instead.
59
- if self.args['test-mode']:
60
- return True
61
- if self.args['gui']:
62
- return False
63
- return True
64
-
65
- # We do override do_it() to avoid using CommandSimQuesta.do_it()
66
- def do_it(self):
67
- CommandSim.do_it(self)
68
- # self.compile() # runs if stop-before-compile is False, stop-after-compile is True
69
- # self.elaborate() # runs if stop-before-compile is False, stop-after-compile is False,
70
- # stop-after-elaborate is True
71
- # self.simulate() # runs if stop-* are all False (run the whole thing)
72
-
73
-
74
- def prepare_compile(self):
75
- self.set_tool_defines()
76
- self.write_vlog_dot_f()
77
- self.write_vsim_dot_do(dot_do_to_write='all')
78
-
79
- vsim_command_lists = self.get_compile_command_lists()
80
- util.write_shell_command_file(
81
- dirpath=self.args['work-dir'],
82
- filename='compile_only.sh',
83
- command_lists=vsim_command_lists
84
- )
85
-
86
- vsim_command_lists = self.get_elaborate_command_lists()
87
- util.write_shell_command_file(
88
- dirpath=self.args['work-dir'],
89
- filename='compile_elaborate_only.sh',
90
- command_lists=vsim_command_lists
91
- )
92
-
93
- # Write simulate.sh and all.sh to work-dir:
94
- vsim_command_lists = self.get_simulate_command_lists()
95
- self.write_sh_scripts_to_work_dir(
96
- compile_lists=[], elaborate_lists=[], simulate_lists=vsim_command_lists
97
- )
98
-
99
- def compile(self):
100
- if self.args['stop-before-compile']:
101
- # don't run anything, save everyting we've already run in _prep_compile()
102
- return
103
- if self.args['stop-after-compile']:
104
- vsim_command_lists = self.get_compile_command_lists()
105
- self.run_commands_check_logs(vsim_command_lists, log_filename='sim.log',
106
- must_strings=['Errors: 0'], use_must_strings=False)
107
-
108
- def elaborate(self):
109
- if self.args['stop-before-compile']:
110
- return
111
- if self.args['stop-after-compile']:
112
- return
113
- if self.args['stop-after-elaborate']:
114
- # only run this if we stop after elaborate (simulate run it all)
115
- vsim_command_lists = self.get_elaborate_command_lists()
116
- self.run_commands_check_logs(vsim_command_lists, log_filename='sim.log')
117
-
118
- def simulate(self):
119
- if self.args['stop-before-compile'] or self.args['stop-after-compile'] or \
120
- self.args['stop-after-elaborate']:
121
- # don't run this if we're stopping before/after compile/elab
122
- return
123
- vsim_command_lists = self.get_simulate_command_lists()
124
- self.run_commands_check_logs(vsim_command_lists, log_filename='sim.log')
125
-
126
- def get_compile_command_lists(self, **kwargs) -> list:
127
- # This will also set up a compile.
128
- vsim_command_list = [
129
- self.sim_exe,
130
- '-c' if self.run_in_batch_mode() else '',
131
- '-do', 'vsim_vlogonly.do', '-logfile', 'sim.log',
132
- ]
133
- return [vsim_command_list]
134
-
135
- def get_elaborate_command_lists(self, **kwargs) -> list:
136
- # This will also set up a compile, for vlog + vsim (0 time)
137
- vsim_command_list = [
138
- self.sim_exe,
139
- '-c' if self.run_in_batch_mode() else '',
140
- '-do', 'vsim_lintonly.do', '-logfile', 'sim.log',
141
- ]
142
- return [vsim_command_list]
143
-
144
- def get_simulate_command_lists(self, **kwargs) -> list:
145
- # This will also set up a compile, for vlog + vsim (with run -a)
146
- vsim_command_list = [
147
- self.sim_exe,
148
- '-c' if self.run_in_batch_mode() else '',
149
- '-do', 'vsim.do', '-logfile', 'sim.log',
150
- ]
151
- return [vsim_command_list]
152
-
153
- def get_post_simulate_command_lists(self, **kwargs) -> list:
154
- return []
155
-
156
- def write_vlog_dot_f(self, filename='vlog.f') -> None:
157
- '''Returns none, creates filename (str) for a vlog.f'''
158
- vlog_dot_f_lines = []
159
-
160
- # Add compile args from config.tool.modelsim_ase:
161
- vlog_dot_f_lines += self.tool_config.get(
162
- 'compile-args',
163
- '-sv -svinputport=net -lint').split()
164
- # Add waivers from config.tool.modelsim_ase:
165
- for waiver in self.tool_config.get(
166
- 'compile-waivers',
167
- [ #defaults:
168
- '2275', # 2275 - Existing package 'foo_pkg' will be overwritten.
169
- ]) + self.args['compile-waivers']:
170
- vlog_dot_f_lines += ['-suppress', str(waiver)]
171
-
172
- if self.args['gui'] or self.args['waves']:
173
- vlog_dot_f_lines += self.tool_config.get('compile-waves-args', '').split()
174
-
175
- vlog_dot_f_fname = filename
176
- vlog_dot_f_fpath = os.path.join(self.args['work-dir'], vlog_dot_f_fname)
177
-
178
- for value in self.incdirs:
179
- vlog_dot_f_lines += [ f"+incdir+{value}" ]
180
-
181
- for k,v in self.defines.items():
182
- if v is None:
183
- vlog_dot_f_lines += [ f'+define+{k}' ]
184
- else:
185
-
186
- # if the value v is a double-quoted string, such as v='"hi"', the
187
- # entire +define+NAME="hi" needs to wrapped in double quotes with the
188
- # value v double-quotes escaped: "+define+NAME=\"hi\""
189
- if isinstance(v, str) and v.startswith('"') and v.endswith('"'):
190
- str_v = v.replace('"', '\\"')
191
- vlog_dot_f_lines += [ f'"+define+{k}={str_v}"' ]
192
- else:
193
- # Generally we should only support int and str python types passed as
194
- # +define+{k}={v}, but also for SystemVerilog plusargs
195
- vlog_dot_f_lines += [ f'+define+{k}={sanitize_defines_for_sh(v)}' ]
196
-
197
-
198
- vlog_dot_f_lines += self.args['compile-args']
199
-
200
- vlog_dot_f_lines += [
201
- '-source',
202
- ] + list(self.files_sv) + list(self.files_v)
203
-
204
- if not self.files_sv and not self.files_v:
205
- if not self.args['stop-before-compile']:
206
- self.error(f'{self.target=} {self.files_sv=} and {self.files_v=} are empty,',
207
- 'cannot create a valid vlog.f')
208
-
209
- with open(vlog_dot_f_fpath, 'w', encoding='utf-8') as f:
210
- f.writelines(line + "\n" for line in vlog_dot_f_lines)
211
-
212
- def vopt_handle_parameters(self) -> (str, list):
213
- '''Returns str for vopt or voptargs, and list of vopt tcl
214
-
215
- Note this is used for self.use_vopt = True or False.
216
- '''
217
-
218
- voptargs_str = ''
219
- vopt_do_lines = []
220
-
221
- # Note that if self.use_vopt=True, we have to do some workarounds for how
222
- # some questa-like tools behave for: tcl/.do + vopt arg processing
223
- # This affects string based parameters that have spaces (vopt treats spaces unique args,
224
- # vsim does not). Since we'd like to keep the vopt/vsim split into separate steps, we can
225
- # work around this by setting tcl varaibles for each parameter.
226
- if self.parameters:
227
- if not self.use_vopt:
228
- voptargs_str += ' ' + ' '.join(self.process_parameters_get_list(arg_prefix='-G'))
229
- else:
230
- for k,v in self.parameters.items():
231
- s = sim.parameters_dict_get_command_list(params={k: v}, arg_prefix='')[0]
232
- # At this point, s should be a str in form {k}={v}
233
- if not s or '=' not in s:
234
- continue
235
- if ' ' in s:
236
- # Instead of:
237
- # vopt -GMyParam="hi bye"
238
- # we'll do:
239
- # set PARAMETERS(MyParam) "hi bye"
240
- # vopt -GMyParam=$PARAMETERS(MyParam)
241
- s = s.replace(f'{k}=', f'set PARAMETERS({k}) ')
242
- vopt_do_lines.append(s)
243
- voptargs_str += f' -G{k}=$PARAMETERS({k}) '
244
- else:
245
- voptargs_str += f' -G{s} '
246
-
247
- return voptargs_str, vopt_do_lines
248
-
249
-
250
- def write_vsim_dot_do( # pylint: disable=too-many-locals
251
- self, dot_do_to_write: list
252
- ) -> None:
253
- '''Writes files(s) based on dot_do_to_write(list of str)
254
-
255
- list arg values can be empty (all) or have items 'all', 'sim', 'lint', 'vlog'.'''
256
-
257
- vsim_dot_do_fpath = os.path.join(self.args['work-dir'], 'vsim.do')
258
- vsim_lintonly_dot_do_fpath = os.path.join(self.args['work-dir'], 'vsim_lintonly.do')
259
- vsim_vlogonly_dot_do_fpath = os.path.join(self.args['work-dir'], 'vsim_vlogonly.do')
260
-
261
- sim_plusargs_str = self._get_sim_plusargs_str()
262
- vsim_suppress_list_str = self._get_vsim_suppress_list_str()
263
- vsim_ext_args = ' '.join(self.args.get('sim-args', []))
264
-
265
- voptargs_str = self.tool_config.get('elab-args', '')
266
- voptargs_str += ' '.join(self.args.get('elab-args', []))
267
- if self.args['gui'] or self.args['waves']:
268
- voptargs_str += ' ' + self.tool_config.get('simulate-waves-args', '+acc')
269
- util.artifacts.add_extension(
270
- search_paths=self.args['work-dir'], file_extension='wlf',
271
- typ='waveform', description='Modelsim/Questa Waveform WLF (Wave Log Format) file'
272
- )
273
-
274
- # TODO(drew): support self.args['sim_libary'] (1 lists)
275
- vlog_do_lines = []
276
- vsim_do_lines = []
277
-
278
- # parameters, use helper method to get voptargs_str and vopt_do_lines
279
- more_voptargs_str, vopt_do_lines = self.vopt_handle_parameters()
280
- voptargs_str += more_voptargs_str
281
-
282
-
283
- vopt_one_liner = ""
284
- if self.use_vopt:
285
- vopt_one_liner = (
286
- f"vopt {voptargs_str} work.{self.args['top']} -o opt__{self.args['top']}"
287
- )
288
- vopt_one_liner = vopt_one_liner.replace('\n', ' ') # needs to be a one-liner
289
- # vopt doesn't need -voptargs=(value) like vsim does, simply use (value).
290
- vopt_one_liner = vopt_one_liner.replace('-voptargs=', '')
291
-
292
- vsim_one_liner = "vsim -onfinish stop" \
293
- + f" -sv_seed {self.args['seed']} {sim_plusargs_str} {vsim_suppress_list_str}" \
294
- + f" {vsim_ext_args} opt__{self.args['top']}"
295
- else:
296
- # vopt doesn't exist, use single vsim call after vlog call:
297
- vsim_one_liner = "vsim -onfinish stop" \
298
- + f" -sv_seed {self.args['seed']} {sim_plusargs_str} {vsim_suppress_list_str}" \
299
- + f" {voptargs_str} {vsim_ext_args} work.{self.args['top']}"
300
-
301
-
302
- vsim_one_liner = vsim_one_liner.replace('\n', ' ')
303
-
304
- vlog_do_lines += [
305
- "if {[file exists work]} { vdel -all work; }",
306
- "vlib work;",
307
- "quietly set qc 30;",
308
- "if {[catch {vlog -f vlog.f} result]} {",
309
- " echo \"Caught $result \";",
310
- " if {[batch_mode]} {",
311
- " quit -f -code 20;",
312
- " }",
313
- "}",
314
- ]
315
-
316
- if self.use_vopt:
317
- vopt_do_lines += [
318
- "if {[catch { " + vopt_one_liner + " } result] } {",
319
- " echo \"Caught $result\";",
320
- " if {[batch_mode]} {",
321
- " quit -f -code 19;",
322
- " }",
323
- "}",
324
- ]
325
-
326
- vsim_do_lines += [
327
- "if {[catch { " + vsim_one_liner + " } result] } {",
328
- " echo \"Caught $result\";",
329
- " if {[batch_mode]} {",
330
- " quit -f -code 18;",
331
- " }",
332
- "}",
333
- ]
334
-
335
- vsim_vlogonly_dot_do_lines = vlog_do_lines + [
336
- "if {[batch_mode]} {",
337
- " quit -f -code 0;",
338
- "}",
339
- ]
340
-
341
- final_check_teststatus_do_lines = [
342
- "set TestStatus [coverage attribute -name SEED -name TESTSTATUS];",
343
- "if {[regexp \"TESTSTATUS += 0\" $TestStatus]} {",
344
- " quietly set qc 0;",
345
- "} elseif {[regexp \"TESTSTATUS += 1\" $TestStatus]} {",
346
- " quietly set qc 0;",
347
- "} else {",
348
- " quietly set qc 2;",
349
- "}",
350
- "if {[batch_mode]} {",
351
- " quit -f -code $qc;",
352
- "}",
353
- ]
354
-
355
- # final vlog/vopt/vsim lint-only .do command (want to make sure it can completely
356
- # build for 'elab' style eda job), runs for 0ns, logs nothing for a waveform, quits
357
- vsim_lintonly_dot_do_lines = vlog_do_lines + vopt_do_lines + vsim_do_lines \
358
- + final_check_teststatus_do_lines
359
-
360
- # final vlog/opt/vsim full simulation .do command.
361
- vsim_dot_do_lines = vlog_do_lines + vopt_do_lines + vsim_do_lines + [
362
- "onbreak { resume; };",
363
- "catch {log -r *};",
364
- "run -a;",
365
- ] + final_check_teststatus_do_lines
366
-
367
- write_all = len(dot_do_to_write) == 0 or 'all' in dot_do_to_write
368
- if write_all or 'sim' in dot_do_to_write:
369
- with open(vsim_dot_do_fpath, 'w', encoding='utf-8') as f:
370
- f.writelines(line + "\n" for line in vsim_dot_do_lines)
371
-
372
- if write_all or 'lint' in dot_do_to_write:
373
- with open(vsim_lintonly_dot_do_fpath, 'w', encoding='utf-8') as f:
374
- f.writelines(line + "\n" for line in vsim_lintonly_dot_do_lines)
375
-
376
- if write_all or 'vlog' in dot_do_to_write:
377
- with open(vsim_vlogonly_dot_do_fpath, 'w', encoding='utf-8') as f:
378
- f.writelines(line + "\n" for line in vsim_vlogonly_dot_do_lines)
379
-
380
-
381
- def _get_sim_plusargs_str(self) -> str:
382
- sim_plusargs = []
383
-
384
- assert isinstance(self.args["sim-plusargs"], list), \
385
- f'{self.target=} {type(self.args["sim-plusargs"])=} but must be list'
386
-
387
- for x in self.args['sim-plusargs']:
388
- # For vsim we need to add a +key=value if the + is missing
389
- if x[0] != '+':
390
- x = f'+{x}'
391
- sim_plusargs.append(x)
392
-
393
- return ' '.join(sim_plusargs)
394
-
395
-
396
- def _get_vsim_suppress_list_str(self) -> str:
397
- vsim_suppress_list = []
398
- # Add waivers from config.tool.modelsim_ase:
399
- for waiver in self.tool_config.get(
400
- 'simulate-waivers', [
401
- #defaults:
402
- '3009', # 3009: [TSCALE] - Module 'foo' does not have a timeunit/timeprecision
403
- # specification in effect, but other modules do.
404
- ]) + self.args['sim-waivers']:
405
- vsim_suppress_list += ['-suppress', str(waiver)]
406
-
407
- return ' '.join(vsim_suppress_list)
408
-
409
-
410
- def artifacts_add(self, name: str, typ: str, description: str) -> None:
411
- '''Override from Command.artifacts_add, so we can catch known file
412
-
413
- names to make their typ/description better, such as CommandSim using
414
- sim.log
415
- '''
416
- _, leafname = os.path.split(name)
417
- if leafname == 'sim.log':
418
- description = 'Modelsim/Questa Transcript log file'
419
-
420
- super().artifacts_add(name=name, typ=typ, description=description)
421
54
 
422
55
 
423
56
  class CommandElabModelsimAse(CommandSimModelsimAse):
@@ -439,3 +72,11 @@ class CommandLintModelsimAse(CommandSimModelsimAse):
439
72
  super().__init__(config)
440
73
  self.args['stop-after-compile'] = True
441
74
  self.args['stop-after-elaborate'] = True
75
+
76
+
77
+ class CommandFListModelsimAse(CommonFListQuesta):
78
+ '''CommandFListModelsimAse is a command handler for: eda flist --tool=modelsim_ase'''
79
+
80
+ def __init__(self, config: dict):
81
+ CommonFListQuesta.__init__(self, config=config)
82
+ self._TOOL = 'questa_fse'