From 9d017591f64f21f3ec1ea4c9398a5105ef289841 Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Thu, 2 Apr 2026 12:32:03 +0100 Subject: [PATCH 1/2] feat: enable options for post-build commands DVSim enables running commands after building has finished with the `post_build_cmds` option, but does not provide a mechanism for passing additional options to this post build command. Introduce this mechanism via `post_build_opts`, defined in the HJSON configs. Co-authored-by: Pascal Nasahl Signed-off-by: Alex Jones --- src/dvsim/job/deploy.py | 2 ++ src/dvsim/modes.py | 1 + src/dvsim/regression.py | 3 +++ src/dvsim/sim/flow.py | 3 +++ src/dvsim/test.py | 2 ++ tests/job/test_deploy.py | 3 +++ 6 files changed, 14 insertions(+) diff --git a/src/dvsim/job/deploy.py b/src/dvsim/job/deploy.py index 71247b85..e34cd9de 100644 --- a/src/dvsim/job/deploy.py +++ b/src/dvsim/job/deploy.py @@ -417,6 +417,7 @@ def _define_attrs(self) -> None: "build_dir": False, "build_opts": False, "post_build_cmds": False, + "post_build_opts": False, }, ) @@ -501,6 +502,7 @@ def _define_attrs(self) -> None: "build_log": False, "build_timeout_mins": False, "post_build_cmds": False, + "post_build_opts": False, "pre_build_cmds": False, # Report processing "report_cmd": False, diff --git a/src/dvsim/modes.py b/src/dvsim/modes.py index 9f944518..8e21ea76 100644 --- a/src/dvsim/modes.py +++ b/src/dvsim/modes.py @@ -265,6 +265,7 @@ def __init__(self, bdict) -> None: self.post_build_cmds = [] self.en_build_modes = [] self.build_opts = [] + self.post_build_opts = [] self.build_timeout_mins = None self.pre_run_cmds = [] self.post_run_cmds = [] diff --git a/src/dvsim/regression.py b/src/dvsim/regression.py index 3554b5e5..f438dbad 100644 --- a/src/dvsim/regression.py +++ b/src/dvsim/regression.py @@ -37,6 +37,7 @@ def __init__(self, regdict) -> None: self.pre_run_cmds = [] self.post_run_cmds = [] self.build_opts = [] + self.post_build_opts = [] self.run_opts = [] super().__init__("regression", regdict) @@ -110,6 +111,7 @@ def create_regressions(regdicts, sim_cfg, tests): # Merge the build and run cmds & opts from the sim modes regression_obj.pre_build_cmds.extend(sim_mode_obj.pre_build_cmds) regression_obj.post_build_cmds.extend(sim_mode_obj.post_build_cmds) + regression_obj.post_build_opts.extend(sim_mode_obj.post_build_opts) regression_obj.build_opts.extend(sim_mode_obj.build_opts) regression_obj.pre_run_cmds.extend(sim_mode_obj.pre_run_cmds) regression_obj.post_run_cmds.extend(sim_mode_obj.post_run_cmds) @@ -165,6 +167,7 @@ def merge_regression_opts(self) -> None: if test.build_mode.name not in processed_build_modes: test.build_mode.pre_build_cmds.extend(self.pre_build_cmds) test.build_mode.post_build_cmds.extend(self.post_build_cmds) + test.build_mode.post_build_opts.extend(self.post_build_opts) test.build_mode.build_opts.extend(self.build_opts) processed_build_modes.append(test.build_mode.name) test.pre_run_cmds.extend(self.pre_run_cmds) diff --git a/src/dvsim/sim/flow.py b/src/dvsim/sim/flow.py index 35de0c63..0ec4b629 100644 --- a/src/dvsim/sim/flow.py +++ b/src/dvsim/sim/flow.py @@ -132,6 +132,7 @@ def __init__(self, flow_cfg_file, hjson_data, args, mk_config) -> None: self.flow_makefile = "" self.pre_build_cmds = [] self.post_build_cmds = [] + self.post_build_opts = [] self.build_dir = "" self.pre_run_cmds = [] self.post_run_cmds = [] @@ -295,6 +296,7 @@ def _create_objects(self) -> None: self.pre_build_cmds.extend(build_mode_obj.pre_build_cmds) self.post_build_cmds.extend(build_mode_obj.post_build_cmds) self.build_opts.extend(build_mode_obj.build_opts) + self.post_build_opts.extend(build_mode_obj.post_build_opts) self.pre_run_cmds.extend(build_mode_obj.pre_run_cmds) self.post_run_cmds.extend(build_mode_obj.post_run_cmds) self.run_opts.extend(build_mode_obj.run_opts) @@ -417,6 +419,7 @@ def _match_items(items: list, patterns: list): self.pre_build_cmds, self.post_build_cmds, self.build_opts, + self.post_build_opts, self.pre_run_cmds, self.post_run_cmds, self.run_opts, diff --git a/src/dvsim/test.py b/src/dvsim/test.py index 452079b0..340d3b4f 100644 --- a/src/dvsim/test.py +++ b/src/dvsim/test.py @@ -121,6 +121,7 @@ def merge_global_opts( global_pre_build_cmds, global_post_build_cmds, global_build_opts, + global_post_build_opts, global_pre_run_cmds, global_post_run_cmds, global_run_opts, @@ -133,6 +134,7 @@ def merge_global_opts( test.build_mode.pre_build_cmds.extend(global_pre_build_cmds) test.build_mode.post_build_cmds.extend(global_post_build_cmds) test.build_mode.build_opts.extend(global_build_opts) + test.build_mode.post_build_opts.extend(global_post_build_opts) processed_build_modes.add(test.build_mode.name) test.pre_run_cmds.extend(global_pre_run_cmds) test.post_run_cmds.extend(global_post_run_cmds) diff --git a/tests/job/test_deploy.py b/tests/job/test_deploy.py index 7f3c8254..d6064c1b 100644 --- a/tests/job/test_deploy.py +++ b/tests/job/test_deploy.py @@ -67,6 +67,7 @@ def __init__(self) -> None: self.build_timeout_mins = 500 self.build_mode = "build_mode" self.build_opts = ["-b path/here", '-a "Quoted"'] + self.post_build_opts = ["E"] def _build_compile_sim( @@ -120,6 +121,7 @@ class TestCompileSim: "build_dir=build/dir " "build_opts='-b path/here -a \"Quoted\"' " "post_build_cmds='C && D' " + "post_build_opts=E " "pre_build_cmds='A && B' " "proj_root=/project " "sv_flist_gen_cmd=gen_cmd " @@ -134,6 +136,7 @@ class TestCompileSim: "build_dir=build/dir " "build_opts='-b path/here -a \"Quoted\"' " "post_build_cmds='C && D' " + "post_build_opts=E " "pre_build_cmds='A && B' " "proj_root=/project " "sv_flist_gen_cmd=gen_cmd " From cb32f78f0c9d2ccc569136a5adb9fbfb9215aa5a Mon Sep 17 00:00:00 2001 From: Alex Jones Date: Thu, 2 Apr 2026 14:17:52 +0100 Subject: [PATCH 2/2] feat: add initial VC Z01X simulation tool support Add support for the VC Z01X simulation tool, which is a fault simulation & injection tool layered on top of the VCS engine. A new method is introduced to the SimTool protocol to allow mutating the attributes of the Deploy objects after all attributes have been initialized & expanded. Then, when the tool is configured as Z01X, the RunTest job is changed to use two different run options: - run_opts_fi_sim: the runtime options needed for Z01X. - run_opts: Z01X itself starts the simulation using simv. Those run_opts parameters are then passed by Z01X to simv. Co-authored-by: Pascal Nasahl Signed-off-by: Alex Jones --- src/dvsim/job/deploy.py | 8 ++++++++ src/dvsim/sim/tool/base.py | 15 ++++++++++++++- src/dvsim/sim/tool/vcs.py | 13 +++++++++++++ src/dvsim/sim/tool/xcelium.py | 13 +++++++++++++ src/dvsim/sim/tool/z01x.py | 31 +++++++++++++++++++++++++++++++ src/dvsim/tool/utils.py | 2 ++ 6 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/dvsim/sim/tool/z01x.py diff --git a/src/dvsim/job/deploy.py b/src/dvsim/job/deploy.py index e34cd9de..b3c49555 100644 --- a/src/dvsim/job/deploy.py +++ b/src/dvsim/job/deploy.py @@ -92,6 +92,14 @@ def __init__(self, sim_cfg: "SimCfg") -> None: # Set class instance attributes. self._set_attrs() + # Mutate the attributes based on any tool plugins. + if self.flow == "sim": + try: + plugin = get_sim_tool_plugin(self.sim_cfg.tool) + plugin.set_additional_attrs(self) + except NotImplementedError as e: + log.debug("Could not find sim tool for %s: %s", self.sim_cfg.tool, str(e)) + # Check if all attributes that are needed are set. self._check_attrs() diff --git a/src/dvsim/sim/tool/base.py b/src/dvsim/sim/tool/base.py index 896ac20a..56c3bb66 100644 --- a/src/dvsim/sim/tool/base.py +++ b/src/dvsim/sim/tool/base.py @@ -6,10 +6,13 @@ from collections.abc import Mapping, Sequence from pathlib import Path -from typing import Protocol, runtime_checkable +from typing import TYPE_CHECKING, Protocol, runtime_checkable from dvsim.sim.data import CoverageMetrics +if TYPE_CHECKING: + from dvsim.job.deploy import Deploy + __all__ = ("SimTool",) @@ -82,3 +85,13 @@ def get_coverage_metrics(raw_metrics: Mapping[str, float | None] | None) -> Cove """ ... + + @staticmethod + def set_additional_attrs(deploy: "Deploy") -> None: + """Define any additional tool-specific attrs on the deploy object. + + Args: + deploy: the deploy object to mutate. + + """ + ... diff --git a/src/dvsim/sim/tool/vcs.py b/src/dvsim/sim/tool/vcs.py index 4948416f..06f84237 100644 --- a/src/dvsim/sim/tool/vcs.py +++ b/src/dvsim/sim/tool/vcs.py @@ -7,9 +7,13 @@ import re from collections.abc import Mapping, Sequence from pathlib import Path +from typing import TYPE_CHECKING from dvsim.sim.data import CodeCoverageMetrics, CoverageMetrics +if TYPE_CHECKING: + from dvsim.job.deploy import Deploy + __all__ = ("VCS",) @@ -132,3 +136,12 @@ def get_coverage_metrics(raw_metrics: Mapping[str, float | None] | None) -> Cove fsm=raw_metrics.get("fsm"), ), ) + + @staticmethod + def set_additional_attrs(deploy: "Deploy") -> None: + """Define any additional tool-specific attrs on the deploy object. + + Args: + deploy: the deploy object to mutate. + + """ diff --git a/src/dvsim/sim/tool/xcelium.py b/src/dvsim/sim/tool/xcelium.py index 0362f48d..9dd1bd4a 100644 --- a/src/dvsim/sim/tool/xcelium.py +++ b/src/dvsim/sim/tool/xcelium.py @@ -8,9 +8,13 @@ from collections import OrderedDict from collections.abc import Mapping, Sequence from pathlib import Path +from typing import TYPE_CHECKING from dvsim.sim.data import CodeCoverageMetrics, CoverageMetrics +if TYPE_CHECKING: + from dvsim.job.deploy import Deploy + __all__ = ("Xcelium",) @@ -157,3 +161,12 @@ def get_coverage_metrics(raw_metrics: Mapping[str, float | None] | None) -> Cove fsm=raw_metrics.get("fsm"), ), ) + + @staticmethod + def set_additional_attrs(deploy: "Deploy") -> None: + """Define any additional tool-specific attrs on the deploy object. + + Args: + deploy: the deploy object to mutate. + + """ diff --git a/src/dvsim/sim/tool/z01x.py b/src/dvsim/sim/tool/z01x.py new file mode 100644 index 00000000..9e3a7e10 --- /dev/null +++ b/src/dvsim/sim/tool/z01x.py @@ -0,0 +1,31 @@ +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +"""EDA tool plugin providing Z01X support to DVSim.""" + +from typing import TYPE_CHECKING + +from dvsim.sim.tool.vcs import VCS + +if TYPE_CHECKING: + from dvsim.job.deploy import Deploy + +__all__ = ("Z01X",) + + +class Z01X(VCS): + """Implement Z01X tool support.""" + + @staticmethod + def set_additional_attrs(deploy: "Deploy") -> None: + """Define any additional tool-specific attrs on the deploy object. + + Args: + deploy: the deploy object to mutate. + + """ + if deploy.target == "run": + sim_run_opts = " ".join(opt.strip() for opt in deploy.run_opts) + deploy.exports.append({"sim_run_opts": sim_run_opts}) + deploy.run_opts = list(deploy.sim_cfg.getattr("run_opts_fi_sim", ())) diff --git a/src/dvsim/tool/utils.py b/src/dvsim/tool/utils.py index eeb3b554..ca00d87c 100644 --- a/src/dvsim/tool/utils.py +++ b/src/dvsim/tool/utils.py @@ -8,12 +8,14 @@ from dvsim.sim.tool.base import SimTool from dvsim.sim.tool.vcs import VCS from dvsim.sim.tool.xcelium import Xcelium +from dvsim.sim.tool.z01x import Z01X __all__ = ("get_sim_tool_plugin",) _SUPPORTED_SIM_TOOLS = { "vcs": VCS, "xcelium": Xcelium, + "z01x": Z01X, }