Skip to content

Commit 13e6aca

Browse files
committed
feat: expose a build's options to the run step as {build_opts_file}
A run step that compiles for itself instead of loading the build's snapshot has to compile the way the build did. Every build now records its options in build_opts.f, named by the hjson as {build_opts_file}. Signed-off-by: Martin Velay <mvelay@lowrisc.org>
1 parent ecb7bb1 commit 13e6aca

3 files changed

Lines changed: 76 additions & 0 deletions

File tree

src/dvsim/job/deploy.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ def __init__(self, build_mode: "BuildMode", sim_cfg: "SimCfg") -> None:
431431
self.build_cmd: str = ""
432432
self.build_dir: str = ""
433433
self.build_opts: list[str] = []
434+
self.build_opts_file: str = ""
434435
self.post_build_cmds: list[str] = []
435436
self.build_fail_patterns: list[str] = []
436437
self.build_pass_patterns: list[str] = []
@@ -485,6 +486,7 @@ def _define_attrs(self) -> None:
485486
self.mandatory_misc_attrs.update(
486487
{
487488
"build_fail_patterns": False,
489+
"build_opts_file": False,
488490
"build_pass_patterns": False,
489491
"build_timeout_mins": False,
490492
"cov_db_dir": False,
@@ -509,6 +511,25 @@ def _set_attrs(self) -> None:
509511
if self.sim_cfg.args.build_timeout_mins is not None:
510512
self.build_timeout_mins = self.sim_cfg.args.build_timeout_mins
511513

514+
def _write_build_opts_file(self) -> None:
515+
"""Record the options this build used, in the build directory.
516+
517+
A run step may compile and elaborate for itself instead of loading the snapshot the build
518+
produced. Such a run has to compile the way the build did. Build modes and individual cfgs
519+
each contribute their own defines, include paths and libraries, and a run compiled with a
520+
different set would simulate a differently configured design.
521+
522+
The merged option list exists only here, so write it out as a file the tools accept in
523+
place of command line options. The run step names that file with {build_opts_file}, which
524+
SimCfg sets and the HJson may override.
525+
"""
526+
opts_file = Path(self.build_opts_file)
527+
opts_file.parent.mkdir(parents=True, exist_ok=True)
528+
opts_file.write_text(
529+
"".join(f"{opt.strip()}\n" for opt in self.build_opts if opt.strip()),
530+
encoding="UTF-8",
531+
)
532+
512533
def pre_launch(self) -> Callable[[], None]:
513534
"""Get pre-launch callback."""
514535

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

542+
self._write_build_opts_file()
543+
521544
return callback
522545

523546
def get_timeout_mins(self) -> float:

src/dvsim/sim/flow.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ def __init__(self, flow_cfg_file, hjson_data, args, mk_config) -> None:
134134
self.post_build_cmds = []
135135
self.post_build_opts = []
136136
self.build_dir = ""
137+
self.build_opts_file = ""
137138
self.pre_run_cmds = []
138139
self.post_run_cmds = []
139140
self.run_dir = ""
@@ -200,6 +201,13 @@ def _expand(self) -> None:
200201
if self.args.verbosity is not None:
201202
self.verbosity = self.args.verbosity
202203

204+
# Where each build records the options it compiled with, for a run step that compiles for
205+
# itself rather than loading the snapshot the build produced, see
206+
# CompileSim._write_build_opts_file(). The HJSON can name this path as {build_opts_file},
207+
# and can also set it, to move the file or to share one between cfgs.
208+
if not self.build_opts_file:
209+
self.build_opts_file = "{build_dir}/build_opts.f"
210+
203211
super()._expand()
204212

205213
if self.variant:

tests/job/test_deploy.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"""Test Job deployment models."""
66

77
from collections.abc import Mapping
8+
from pathlib import Path
89

910
import pytest
1011
from hamcrest import assert_that, equal_to
@@ -48,6 +49,7 @@ def __init__(self) -> None:
4849
self.pre_build_cmds = ["A", "B"]
4950
self.post_build_cmds = ["C", "D"]
5051
self.build_dir = "build/dir"
52+
self.build_opts_file = "{build_dir}/build_opts.f"
5153
self.build_pass_patterns = None
5254
self.build_fail_patterns = None
5355
self.build_seed = 123
@@ -202,6 +204,49 @@ def test_seed(
202204

203205
assert_that(job.seed, equal_to(seed))
204206

207+
@staticmethod
208+
def test_build_opts_file(tmp_path: Path) -> None:
209+
"""Test that a CompileSim records the options it built with, for the run step."""
210+
build_dir = tmp_path / "build" / "dir"
211+
job = _build_compile_sim(
212+
sim_overrides={"build_dir": str(build_dir), "cov_db_dir": str(tmp_path / "cov")},
213+
)
214+
215+
assert_that(job.build_opts_file, equal_to(str(build_dir / "build_opts.f")))
216+
217+
# The build directory does not exist until the build job launches.
218+
job.pre_launch()()
219+
220+
assert_that(
221+
Path(job.build_opts_file).read_text(encoding="UTF-8"),
222+
equal_to('-b path/here\n-a "Quoted"\n'),
223+
)
224+
225+
@staticmethod
226+
def test_build_opts_file_from_cfg(tmp_path: Path) -> None:
227+
"""Test that a cfg-supplied build_opts_file is used as given.
228+
229+
SimCfg only fills in a default, so an HJson that sets build_opts_file itself can put the
230+
file outside the build directory.
231+
"""
232+
opts_file = tmp_path / "elsewhere" / "opts.f"
233+
job = _build_compile_sim(
234+
sim_overrides={
235+
"build_dir": str(tmp_path / "build" / "dir"),
236+
"build_opts_file": str(opts_file),
237+
"cov_db_dir": str(tmp_path / "cov"),
238+
},
239+
)
240+
241+
assert_that(job.build_opts_file, equal_to(str(opts_file)))
242+
243+
job.pre_launch()()
244+
245+
assert_that(
246+
opts_file.read_text(encoding="UTF-8"),
247+
equal_to('-b path/here\n-a "Quoted"\n'),
248+
)
249+
205250
@staticmethod
206251
@pytest.mark.parametrize(
207252
("cli_args_overrides", "build_overrides", "timeout"),

0 commit comments

Comments
 (0)