Skip to content

Commit

Permalink
Initial effort to support three-step flow. Related to #899.
Browse files Browse the repository at this point in the history
Known limitation is that parallel threads aren't supported.
  • Loading branch information
LarsAsplund committed Jun 27, 2024
1 parent 1bad679 commit ad8b23f
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 5 deletions.
24 changes: 24 additions & 0 deletions examples/vhdl/three_step_flow/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
#
# Copyright (c) 2014-2024, Lars Asplund lars.anders.asplund@gmail.com

from pathlib import Path
from vunit import VUnit

vu = VUnit.from_argv()
vu.add_vhdl_builtins()

lib = vu.add_library("lib")
lib.add_source_files(Path(__file__).parent / "*.vhd")

tb = lib.test_bench("tb_example")
test = tb.test("test 2")

for value in range(3):
test.add_config(name=f"{value}", generics=dict(value=value))

vu.set_sim_option("modelsim.three_step_flow", True)

vu.main()
32 changes: 32 additions & 0 deletions examples/vhdl/three_step_flow/tb_example.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
-- You can obtain one at http://mozilla.org/MPL/2.0/.
--
-- Copyright (c) 2014-2024, Lars Asplund lars.anders.asplund@gmail.com

library vunit_lib;
context vunit_lib.vunit_context;

entity tb_example is
generic (
runner_cfg : string;
value : natural := 42);
end entity;

architecture tb of tb_example is
begin
main : process
begin
test_runner_setup(runner, runner_cfg);

while test_suite loop
if run("test 1") then
elsif run("test 2") then
end if;

info("Running " & running_test_case & " with generic value = " & to_string(value));
end loop;

test_runner_cleanup(runner);
end process;
end architecture;
70 changes: 65 additions & 5 deletions vunit/sim_if/modelsim.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from ..exceptions import CompileError
from ..ostools import Process, file_exists
from ..vhdl_standard import VHDL
from . import SimulatorInterface, ListOfStringOption, StringOption
from . import SimulatorInterface, ListOfStringOption, StringOption, BooleanOption
from .vsim_simulator_mixin import VsimSimulatorMixin, fix_path

LOGGER = logging.getLogger(__name__)
Expand All @@ -41,9 +41,12 @@ class ModelSimInterface(VsimSimulatorMixin, SimulatorInterface): # pylint: disa
sim_options = [
ListOfStringOption("modelsim.vsim_flags"),
ListOfStringOption("modelsim.vsim_flags.gui"),
ListOfStringOption("modelsim.vopt_flags"),
ListOfStringOption("modelsim.vopt_flags.gui"),
ListOfStringOption("modelsim.init_files.after_load"),
ListOfStringOption("modelsim.init_files.before_run"),
StringOption("modelsim.init_file.gui"),
BooleanOption("modelsim.three_step_flow"),
]

@classmethod
Expand Down Expand Up @@ -258,14 +261,33 @@ def _create_load_function(self, test_suite_name, config, output_path):
coverage_save_cmd = ""
coverage_args = ""

simulation_target = (
three_step_flow = config.sim_options.get("modelsim.three_step_flow", False)

design_to_optimize = (
config.library_name + "." + config.entity_name + architecture_suffix
if config.vhdl_configuration_name is None
else config.library_name + "." + config.vhdl_configuration_name
)

if three_step_flow:
# vopt has limitations on how the optimized design can be named. Simply removing
# non-alphanumeric characters is a simple solution to that
simulation_target = "opt_" + "".join(ch for ch in design_to_optimize if ch.isalnum())

vopt_flags = [
f"{design_to_optimize}",
f"-work {{{config.library_name}}}",
"-quiet",
f"-floatgenerics+{config.entity_name}.",
f"-o {{{simulation_target}}}",
self._vopt_extra_args(config),
]
else:
simulation_target = design_to_optimize

vsim_flags = [
f"-wlf {{{fix_path(str(Path(output_path) / 'vsim.wlf'))!s}}}",
f"-work {{{config.library_name}}}",
"-quiet",
"-t ps",
# for correct handling of verilog fatal/finish
Expand All @@ -280,15 +302,41 @@ def _create_load_function(self, test_suite_name, config, output_path):
# There is a known bug in modelsim that prevents the -modelsimini flag from accepting
# a space in the path even with escaping, see issue #36
if " " not in self._sim_cfg_file_name:
vsim_flags.insert(0, f"-modelsimini {fix_path(self._sim_cfg_file_name)!s}")
modelsimini_option = f"-modelsimini {fix_path(self._sim_cfg_file_name)!s}"
vsim_flags.insert(0, modelsimini_option)

if three_step_flow:
vopt_flags.insert(0, modelsimini_option)

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

vsim_flags += library_option

if three_step_flow:
vopt_flags += library_option

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

tcl = """
proc vunit_load {{{{vsim_extra_args ""}}}} {{
proc vunit_load {{vsim_extra_args ""} {vopt_extra_args ""}} {"""

if three_step_flow:
tcl += """
set vopt_failed [catch {{
eval vopt ${{vopt_extra_args}} {{{vopt_flags}}}
}}]
if {{${{vopt_failed}}}} {{
echo Command 'vopt ${{vopt_extra_args}} {vopt_flags}' failed
echo Bad flag from vopt_extra_args?
return true
}}""".format(
vopt_flags=" ".join(vopt_flags)
)

tcl += """
set vsim_failed [catch {{
eval vsim ${{vsim_extra_args}} {{{vsim_flags}}}
}}]
Expand Down Expand Up @@ -360,6 +408,18 @@ def _create_run_function():
}
"""

def _vopt_extra_args(self, config):
"""
Determine vopt_extra_args
"""
vopt_extra_args = []
vopt_extra_args = config.sim_options.get("modelsim.vopt_flags", vopt_extra_args)

if self._gui:
vopt_extra_args = config.sim_options.get("modelsim.vopt_flags.gui", vopt_extra_args)

return " ".join(vopt_extra_args)

def _vsim_extra_args(self, config):
"""
Determine vsim_extra_args
Expand Down

0 comments on commit ad8b23f

Please sign in to comment.