Skip to content

Commit 5c524d3

Browse files
committed
Support running optimization from GUI
1 parent e2393cd commit 5c524d3

File tree

4 files changed

+122
-52
lines changed

4 files changed

+122
-52
lines changed

examples/vhdl/three_step_flow/run.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,5 @@
3636
test.add_config(name=f"{value}", generics=dict(value=value))
3737

3838
vu.set_sim_option("modelsim.three_step_flow", True)
39-
vu.set_sim_option("modelsim.vsim_flags", ["-novopt", "-suppress", "12110"])
4039

4140
vu.main()

vunit/sim_if/modelsim.py

Lines changed: 61 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,47 @@ def _get_mapped_libraries(self):
236236
del libraries["others"]
237237
return libraries
238238

239-
def _create_optimize_script(self, design_to_optimize, optimized_design, config):
239+
def _optimize_design(self, config):
240+
"""
241+
Return if design shall be optimized.
242+
"""
243+
244+
return config.sim_options.get("modelsim.three_step_flow", False)
245+
246+
@staticmethod
247+
def _design_to_optimize(config):
248+
"""
249+
Return the design to optimize.
250+
"""
251+
if config.architecture_name is None:
252+
architecture_suffix = ""
253+
else:
254+
architecture_suffix = f"({config.architecture_name!s})"
255+
256+
return (
257+
config.library_name + "." + config.entity_name + architecture_suffix
258+
if config.vhdl_configuration_name is None
259+
else config.library_name + "." + config.vhdl_configuration_name
260+
)
261+
262+
@staticmethod
263+
def _to_optimized_design(design_to_optimize):
264+
"""
265+
Return name for optimized design.
266+
267+
vopt has limitations on how the optimized design can be named. Simply removing
268+
non-alphanumeric characters is a simple solution to that.
269+
"""
270+
271+
return "opt_" + "".join(ch for ch in design_to_optimize if ch.isalnum())
272+
273+
def _create_optimize_function(self, config):
240274
"""
241275
Create vopt script.
242276
"""
277+
design_to_optimize = self._design_to_optimize(config)
278+
optimized_design = self._to_optimized_design(design_to_optimize)
279+
243280
vopt_flags = [
244281
f"{design_to_optimize}",
245282
f"-work {{{config.library_name}}}",
@@ -261,17 +298,18 @@ def _create_optimize_script(self, design_to_optimize, optimized_design, config):
261298
tcl = """
262299
proc vunit_optimize {{vopt_extra_args ""}} {"""
263300
tcl += """
264-
set vopt_failed [catch {{
265-
eval vopt ${{vopt_extra_args}} {{{vopt_flags}}}
266-
}}]
267-
268-
if {{${{vopt_failed}}}} {{
269-
echo Command 'vopt ${{vopt_extra_args}} {vopt_flags}' failed
270-
echo Bad flag from vopt_extra_args?
271-
return true
272-
}}
301+
echo Optimizing using command 'vopt ${{vopt_extra_args}} {vopt_flags}'
302+
set vopt_failed [catch {{
303+
eval vopt ${{vopt_extra_args}} {{{vopt_flags}}}
304+
}}]
273305
274-
return False
306+
if {{${{vopt_failed}}}} {{
307+
echo Command 'vopt ${{vopt_extra_args}} {vopt_flags}' failed
308+
echo Bad flag from vopt_extra_args?
309+
return true
310+
}}
311+
312+
return False
275313
}}
276314
""".format(
277315
vopt_flags=" ".join(vopt_flags)
@@ -355,19 +393,7 @@ def _release_library_lock(self, library, config):
355393
self._library_locks[config.library_name].release()
356394

357395
def _optimize(self, config, script_path):
358-
if config.architecture_name is None:
359-
architecture_suffix = ""
360-
else:
361-
architecture_suffix = f"({config.architecture_name!s})"
362-
363-
design_to_optimize = (
364-
config.library_name + "." + config.entity_name + architecture_suffix
365-
if config.vhdl_configuration_name is None
366-
else config.library_name + "." + config.vhdl_configuration_name
367-
)
368-
369-
if not config.sim_options.get("modelsim.three_step_flow", False):
370-
return design_to_optimize
396+
design_to_optimize = self._design_to_optimize(config)
371397

372398
libraries = {lib.name: lib for lib in self._libraries}
373399
library = libraries[config.library_name]
@@ -392,14 +418,10 @@ def _optimize(self, config, script_path):
392418

393419
LOGGER.debug("Optimizing %s", design_to_optimize)
394420

395-
# vopt has limitations on how the optimized design can be named. Simply removing
396-
# non-alphanumeric characters is a simple solution to that
397-
optimized_design = "opt_" + "".join(ch for ch in design_to_optimize if ch.isalnum())
421+
optimized_design = self._to_optimized_design(design_to_optimize)
398422

399423
optimize_file_name = script_path / "optimize.do"
400-
write_file(
401-
str(optimize_file_name), self._create_optimize_script(design_to_optimize, optimized_design, config)
402-
)
424+
write_file(str(optimize_file_name), self._create_optimize_function(config))
403425

404426
if self._persistent_shell is not None:
405427
status = self._run_persistent_optimize(optimize_file_name)
@@ -441,13 +463,18 @@ def _optimize(self, config, script_path):
441463
else:
442464
LOGGER.debug("Reusing optimized %s.", design_to_optimize)
443465

444-
return optimized_design
466+
return True
445467

446-
def _create_load_function(self, test_suite_name, config, output_path, simulation_target):
468+
def _create_load_function(self, test_suite_name, config, output_path, optimize_design):
447469
"""
448470
Create the vunit_load TCL function that runs the vsim command and loads the design
449471
"""
450472

473+
if optimize_design:
474+
simulation_target = self._to_optimized_design(self._design_to_optimize(config))
475+
else:
476+
simulation_target = self._design_to_optimize(config)
477+
451478
set_generic_str = " ".join(
452479
(
453480
f"-g/{config.entity_name!s}/{name!s}={encode_generic_value(value)!s}"
@@ -485,16 +512,15 @@ def _create_load_function(self, test_suite_name, config, output_path, simulation
485512
# There is a known bug in modelsim that prevents the -modelsimini flag from accepting
486513
# a space in the path even with escaping, see issue #36
487514
if " " not in self._sim_cfg_file_name:
488-
modelsimini_option = f"-modelsimini {fix_path(self._sim_cfg_file_name)!s}"
489-
vsim_flags.insert(0, modelsimini_option)
515+
vsim_flags.insert(0, f"-modelsimini {fix_path(self._sim_cfg_file_name)!s}")
490516

491517
for library in self._libraries:
492518
vsim_flags += ["-L", library.name]
493519

494520
vhdl_assert_stop_level_mapping = {"warning": 1, "error": 2, "failure": 3}
495521

496522
tcl = """
497-
proc vunit_load {{vsim_extra_args ""} {vopt_extra_args ""}} {"""
523+
proc vunit_load {{vsim_extra_args ""}} {"""
498524

499525
tcl += """
500526
set vsim_failed [catch {{

vunit/sim_if/rivierapro.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ def _get_mapped_libraries(self, library_cfg_file):
282282
return libraries
283283

284284
def _create_load_function(
285-
self, test_suite_name, config, output_path, simulation_target
285+
self, test_suite_name, config, output_path, optimize_design
286286
): # pylint: disable=unused-argument
287287
"""
288288
Create the vunit_load TCL function that runs the vsim command and loads the design

vunit/sim_if/vsim_simulator_mixin.py

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def create_process(ident):
5151
self._persistent_shell = None
5252

5353
@staticmethod
54-
def _create_restart_function():
54+
def _create_restart_function(optimize_design):
5555
""" "
5656
Create the vunit_restart function to recompile and restart the simulation
5757
@@ -92,7 +92,7 @@ def _create_restart_function():
9292
]
9393
recompile_command_eval_tcl = " ".join([f"{{{part}}}" for part in recompile_command_eval])
9494

95-
return f"""
95+
tcl = f"""
9696
proc vunit_compile {{}} {{
9797
set cmd_show {{{recompile_command_visual!s}}}
9898
puts "Re-compiling using command ${{cmd_show}}"
@@ -112,16 +112,30 @@ def _create_restart_function():
112112
return false
113113
}}
114114
}}
115-
116-
proc vunit_restart {{}} {{
117-
if {{![vunit_compile]}} {{
115+
"""
116+
if optimize_design:
117+
tcl += """
118+
proc vunit_restart {} {
119+
if {![vunit_compile]} {
120+
if {![vunit_optimize]} {
121+
_vunit_sim_restart
122+
vunit_run
123+
}
124+
}
125+
}
126+
"""
127+
else:
128+
tcl += """
129+
proc vunit_restart {} {
130+
if {![vunit_compile]} {
118131
_vunit_sim_restart
119132
vunit_run
120-
}}
121-
}}
133+
}
134+
}
122135
"""
136+
return tcl
123137

124-
def _create_common_script(self, test_suite_name, config, script_path, output_path, simulation_target):
138+
def _create_common_script(self, test_suite_name, config, script_path, output_path, *, optimize_design):
125139
"""
126140
Create tcl script with functions common to interactive and batch modes
127141
"""
@@ -138,10 +152,27 @@ def _create_common_script(self, test_suite_name, config, script_path, output_pat
138152
puts {vunit_run}
139153
puts { - Run test, must do vunit_load first}
140154
puts {vunit_compile}
155+
puts { - Recompiles the source files}"""
156+
157+
if optimize_design:
158+
tcl += """
159+
puts {vunit_optimize [vopt_extra_args]}
160+
puts { - Optimizes the design. Must be done after vunit_compile}
161+
puts { - Optional first argument are passed as extra flags to vopt}"""
162+
163+
if optimize_design:
164+
tcl += """
165+
puts {vunit_restart}
141166
puts { - Recompiles the source files}
167+
puts { - Reoptimizes the design if the compile was successful}
168+
puts { - and re-runs the simulation if the compile and optimize were successful}"""
169+
else:
170+
tcl += """
142171
puts {vunit_restart}
143172
puts { - Recompiles the source files}
144-
puts { - and re-runs the simulation if the compile was successful}
173+
puts { - and re-runs the simulation if the compile was successful}"""
174+
175+
tcl += """
145176
}
146177
147178
proc vunit_run {} {
@@ -164,10 +195,14 @@ def _create_common_script(self, test_suite_name, config, script_path, output_pat
164195
"""
165196
tcl += self._create_init_files_after_load(config)
166197
tcl += self._create_init_files_before_run(config)
167-
tcl += self._create_load_function(test_suite_name, config, script_path, simulation_target)
198+
tcl += self._create_load_function(test_suite_name, config, script_path, optimize_design)
168199
tcl += get_is_test_suite_done_tcl(get_result_file_name(output_path))
169200
tcl += self._create_run_function()
170-
tcl += self._create_restart_function()
201+
tcl += self._create_restart_function(optimize_design)
202+
203+
if optimize_design:
204+
tcl += self._create_optimize_function(config)
205+
171206
return tcl
172207

173208
@staticmethod
@@ -313,6 +348,13 @@ def _optimize(self, config, script_path): # pylint: disable=unused-argument
313348
"""
314349
return "Optimize not supported"
315350

351+
def _optimize_design(self, config): # pylint: disable=unused-argument
352+
"""
353+
Return if design shall be optimized.
354+
"""
355+
356+
return False
357+
316358
def simulate(self, output_path, test_suite_name, config, elaborate_only):
317359
"""
318360
Run a test bench
@@ -323,13 +365,16 @@ def simulate(self, output_path, test_suite_name, config, elaborate_only):
323365
gui_file_name = script_path / "gui.do"
324366
batch_file_name = script_path / "batch.do"
325367

326-
simulation_target = self._optimize(config, script_path)
327-
if simulation_target is False:
328-
return False
368+
optimize_design = self._optimize_design(config)
369+
if optimize_design:
370+
if not self._optimize(config, script_path):
371+
return False
329372

330373
write_file(
331374
str(common_file_name),
332-
self._create_common_script(test_suite_name, config, script_path, output_path, simulation_target),
375+
self._create_common_script(
376+
test_suite_name, config, script_path, output_path, optimize_design=optimize_design
377+
),
333378
)
334379
write_file(str(gui_file_name), self._create_gui_script(str(common_file_name), config))
335380
write_file(

0 commit comments

Comments
 (0)