Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/dvsim/job/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ def __init__(self, build_mode: "BuildMode", sim_cfg: "SimCfg") -> None:
self.build_cmd: str = ""
self.build_dir: str = ""
self.build_opts: list[str] = []
self.build_opts_file: str = ""
self.post_build_cmds: list[str] = []
self.build_fail_patterns: list[str] = []
self.build_pass_patterns: list[str] = []
Expand Down Expand Up @@ -485,6 +486,7 @@ def _define_attrs(self) -> None:
self.mandatory_misc_attrs.update(
{
"build_fail_patterns": False,
"build_opts_file": False,
"build_pass_patterns": False,
"build_timeout_mins": False,
"cov_db_dir": False,
Expand All @@ -509,6 +511,21 @@ def _set_attrs(self) -> None:
if self.sim_cfg.args.build_timeout_mins is not None:
self.build_timeout_mins = self.sim_cfg.args.build_timeout_mins

def _write_build_opts_file(self) -> None:
"""Write the options this build used to {build_opts_file}.

Doing so allows a run step to recompile and elaborate for itself, without having to
re-invoke dvsim from scratch. It would be complicated for an external tool to infer these
options: they depend on lots of configuration files. Writing them out here solves that
problem.
"""
maybe_options = [opt.strip() for opt in self.build_opts]
options = [opt for opt in maybe_options if opt]

opts_file = Path(self.build_opts_file)
opts_file.parent.mkdir(parents=True, exist_ok=True)
opts_file.write_text("\n".join(options) + "\n", encoding="UTF-8")

def pre_launch(self) -> Callable[[], None]:
"""Get pre-launch callback."""

Expand All @@ -518,6 +535,8 @@ def callback() -> None:
# need to do this because the build directory is not 'renewed'.
rm_path(Path(self.cov_db_dir))

self._write_build_opts_file()

return callback

def get_timeout_mins(self) -> float:
Expand Down
9 changes: 9 additions & 0 deletions src/dvsim/sim/flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ def __init__(self, flow_cfg_file, hjson_data, args, mk_config) -> None:
self.post_build_cmds = []
self.post_build_opts = []
self.build_dir = ""
# Where each build records the options it compiled with, for a run step that compiles for
# itself rather than loading the snapshot the build produced, see
# CompileSim._write_build_opts_file(). The HJSON can name this path as {build_opts_file},
# and can also set it, to move the file or to share one between cfgs. The default is filled
# in by _expand(), once the HJSON has had its say.
self.build_opts_file = ""
self.pre_run_cmds = []
self.post_run_cmds = []
self.run_dir = ""
Expand Down Expand Up @@ -200,6 +206,9 @@ def _expand(self) -> None:
if self.args.verbosity is not None:
self.verbosity = self.args.verbosity

if not self.build_opts_file:
self.build_opts_file = "{build_dir}/build_opts.f"

super()._expand()

if self.variant:
Expand Down
47 changes: 47 additions & 0 deletions tests/job/test_deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"""Test Job deployment models."""

from collections.abc import Mapping
from pathlib import Path

import pytest
from hamcrest import assert_that, equal_to
Expand Down Expand Up @@ -48,6 +49,7 @@ def __init__(self) -> None:
self.pre_build_cmds = ["A", "B"]
self.post_build_cmds = ["C", "D"]
self.build_dir = "build/dir"
self.build_opts_file = "{build_dir}/build_opts.f"
self.build_pass_patterns = None
self.build_fail_patterns = None
self.build_seed = 123
Expand Down Expand Up @@ -202,6 +204,51 @@ def test_seed(

assert_that(job.seed, equal_to(seed))

@staticmethod
def test_build_opts_file(tmp_path: Path) -> None:
"""Test that a CompileSim records the options it built with, for the run step."""
build_dir = tmp_path / "build" / "dir"
# pre_launch() also deletes the coverage database, so keep that path inside tmp_path
job = _build_compile_sim(
sim_overrides={"build_dir": str(build_dir), "cov_db_dir": str(tmp_path / "cov")},
Comment thread
martin-velay marked this conversation as resolved.
)

assert_that(job.build_opts_file, equal_to(str(build_dir / "build_opts.f")))

# The build directory does not exist until the build job launches.
job.pre_launch()()

assert_that(
Path(job.build_opts_file).read_text(encoding="UTF-8"),
equal_to('-b path/here\n-a "Quoted"\n'),
)

@staticmethod
def test_build_opts_file_from_cfg(tmp_path: Path) -> None:
"""Test that a cfg-supplied build_opts_file is used as given.

SimCfg only fills in a default, so an HJson that sets build_opts_file itself can put the
file outside the build directory.
"""
opts_file = tmp_path / "elsewhere" / "opts.f"
# pre_launch() also deletes the coverage database, so keep that path inside tmp_path
job = _build_compile_sim(
sim_overrides={
"build_dir": str(tmp_path / "build" / "dir"),
"build_opts_file": str(opts_file),
"cov_db_dir": str(tmp_path / "cov"),
},
)

assert_that(job.build_opts_file, equal_to(str(opts_file)))

job.pre_launch()()

assert_that(
opts_file.read_text(encoding="UTF-8"),
equal_to('-b path/here\n-a "Quoted"\n'),
)

@staticmethod
@pytest.mark.parametrize(
("cli_args_overrides", "build_overrides", "timeout"),
Expand Down
Loading