From 591cbd3f46a9f2a3ca85ab82ffb9b9a563beb435 Mon Sep 17 00:00:00 2001 From: James McCorrie Date: Fri, 3 Oct 2025 10:52:38 +0100 Subject: [PATCH] feat: add deployment object dump debug feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Debug feature to dump a JSON representation of the `Deploy` objects, just before they are sent to the scheduler. This feature is hidden behind an environment variable to avoid cluttering the CLI interface. The full `Deploy` object is not JSON serialisable in it's current form, so we only serialise the attributes that the `LocalLauncher` uses and some identifying attributes like the full name of the job and the deployment class name. To enable set `DVSIM_DEPLOY_DUMP=true`, run DVSim and there will be a file called `deploy--.json` generated in the scratch directory `scratch/deploy--`. This file can they be compared between runs to check for regressions in the flow leading up to job deployment. With `--fixed-seed=1 --branch=baseline`, the resulting json files should be identical. Setting the "branch" doesn't actually change the git branch, it just overrides what DVSim thinks is the branch as far as paths in the scratch directory are concerned. We need to either set this to something fixed so that the deployment objects contain the same paths, otherwise a diff will fail. Generating a `diff` or hash of the two files and comparing shows if the job deployments would be identical or not. Using this functionality I have confirmed, by backporting this commit to the first release tag, that none of the refactorings made so far in this repository have changed the deployment objects in such a way that the launched jobs are different in any way. ``` ✦ ❯ sha512sum baseline.json deploy_25.10.03_11.35.33.json af732c3011753cfc7dc40068e1ce9b6cf3624973ffbbd25f828e4d7727f27dd65b5ada19407500315ea6f279946222d185dc939fe4978b0b32b3e7e8b4f7f60c baseline.json af732c3011753cfc7dc40068e1ce9b6cf3624973ffbbd25f828e4d7727f27dd65b5ada19407500315ea6f279946222d185dc939fe4978b0b32b3e7e8b4f7f60c deploy_25.10.03_11.35.33.json ``` The first JSON file was generated from backporting the this feature to the tagged commit. The second file was generated with this branch and includes all the tidyup work made so far to DVSim. The DVSim command used is: ``` DVSIM_DEPLOY_DUMP=true dvsim \ ~/base/opentitan/hw/top_earlgrey/dv/top_earlgrey_sim_cfgs.hjson \ --proj-root ~/base/opentitan -i nightly --scratch ~/scratch \ --branch baseline --fixed-seed 1 \ --verbose=debug --max-parallel=50 \ --cov ``` **Note:** *your hashes will be different from mine as the directory paths will be different. However if you run this against the same versions your hashes should be the same as each other.* **Note:** *Depending on the flags you pass to DVSim there may be some minor indeterminism in the configuration. For example with CovMerge the coverage directories are not always given in the same order. It can take several runs to get a different hash, or it could be different on every run. In such cases it's worth using `diff` across the files to see what the actual differences are, they may not be consequential.* Signed-off-by: James McCorrie --- src/dvsim/flow/base.py | 14 ++++++++++++++ src/dvsim/job/deploy.py | 21 +++++++++++++++++++++ src/dvsim/launcher/local.py | 6 +++++- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/dvsim/flow/base.py b/src/dvsim/flow/base.py index 619526d5..a54bed3d 100644 --- a/src/dvsim/flow/base.py +++ b/src/dvsim/flow/base.py @@ -4,6 +4,7 @@ """Flow config base class.""" +import json import os import pprint import sys @@ -411,6 +412,19 @@ def deploy_objects(self) -> Mapping[Deploy, str]: log.error("Nothing to run!") sys.exit(1) + if os.environ.get("DVSIM_DEPLOY_DUMP", "true"): + filename = f"deploy_{self.branch}_{self.timestamp}.json" + (Path(self.scratch_root) / filename).write_text( + json.dumps( + # Sort on full name to ensure consistent ordering + sorted( + [d.model_dump() for d in deploy], + key=lambda d: d["full_name"], + ), + indent=2, + ), + ) + return Scheduler( items=deploy, launcher_cls=get_launcher_cls(), diff --git a/src/dvsim/job/deploy.py b/src/dvsim/job/deploy.py index cebd66be..1a744494 100644 --- a/src/dvsim/job/deploy.py +++ b/src/dvsim/job/deploy.py @@ -334,6 +334,27 @@ def create_launcher(self) -> None: # Retain the handle to self for lookup & callbacks. self.launcher = get_launcher(self) + def model_dump(self) -> Mapping: + """Dump the deployment object to mapping object. + + This method matches the interface provided by pydantic models to dump a + subset of the class attributes + + Returns: + Representation of a deployment object as a dict. + + """ + return { + "full_name": self.full_name, + "type": self.__class__.__name__, + "exports": self.exports, + "interactive": self.sim_cfg.interactive, + "log_path": self.get_log_path(), + "timeout_mins": self.get_timeout_mins(), + "cmd": self.cmd, + "gui": self.gui, + } + class CompileSim(Deploy): """Abstraction for building the simulation executable.""" diff --git a/src/dvsim/launcher/local.py b/src/dvsim/launcher/local.py index 8f9bec9f..eecc3ce6 100644 --- a/src/dvsim/launcher/local.py +++ b/src/dvsim/launcher/local.py @@ -9,9 +9,13 @@ import shlex import subprocess from pathlib import Path +from typing import TYPE_CHECKING from dvsim.launcher.base import ErrorMessage, Launcher, LauncherBusyError, LauncherError +if TYPE_CHECKING: + from dvsim.job.deploy import Deploy + class LocalLauncher(Launcher): """Implementation of Launcher to launch jobs in the user's local workstation.""" @@ -19,7 +23,7 @@ class LocalLauncher(Launcher): # Poll job's completion status every this many seconds poll_freq = 0.025 - def __init__(self, deploy) -> None: + def __init__(self, deploy: "Deploy") -> None: """Initialize common class members.""" super().__init__(deploy)