summaryrefslogtreecommitdiffstats
path: root/debug/risc-v-gsp-rm-vm/gpgpu-sim/scripts
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-03 14:05:38 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-03 14:05:38 -0400
commit32b551d43781dc7b8ac4587ca2ba1554b0cbd5e5 (patch)
treed1cab6bcc35e461610cd5dfcf3f51ba679a576fc /debug/risc-v-gsp-rm-vm/gpgpu-sim/scripts
parentfa71f1b53b524e5f6c6c1fbff1088d610b9f3236 (diff)
downloadopen-iov-32b551d43781dc7b8ac4587ca2ba1554b0cbd5e5.tar.gz
open-iov-32b551d43781dc7b8ac4587ca2ba1554b0cbd5e5.zip
vgsp: host CUDA bridge + sema release recovery; greeneye simulator wave
- kernel: gsp_cuda_bridge (QMD launch capture, debugfs job/out/done, param+output resolution cached from inline writes), sema drain fixes (never hold/starve a channel), GR ring autopin + counter autoreg, per-page push reads, counter-derive gate; module builds clean - tools/cuda-bridge: CUDA driver-API daemon executing mail/vadd kernels on the physical GPU, CUBB2/CBD2 v2 protocol, layout check + self-tests - tools/guest-diag + tools/cuda-ab: scanner/pin fixes, victory push-only mode - debug/risc-v-gsp-rm-vm: Phase S simulator wave (GSP device model, boot ladder, triage/re-demo harnesses, docs 30-41), GPGPU-sim scaffolding - STATE-CURRENT/docs updates
Diffstat (limited to 'debug/risc-v-gsp-rm-vm/gpgpu-sim/scripts')
-rwxr-xr-xdebug/risc-v-gsp-rm-vm/gpgpu-sim/scripts/config_sanity.py278
-rwxr-xr-xdebug/risc-v-gsp-rm-vm/gpgpu-sim/scripts/run_sim.sh109
2 files changed, 387 insertions, 0 deletions
diff --git a/debug/risc-v-gsp-rm-vm/gpgpu-sim/scripts/config_sanity.py b/debug/risc-v-gsp-rm-vm/gpgpu-sim/scripts/config_sanity.py
new file mode 100755
index 0000000..052695e
--- /dev/null
+++ b/debug/risc-v-gsp-rm-vm/gpgpu-sim/scripts/config_sanity.py
@@ -0,0 +1,278 @@
+#!/usr/bin/env python3
+"""config_sanity.py -- stdlib-only sanity check for the TU104 scaffold config.
+
+Parses gpgpu-sim/configs/turing-tu104-2080super/gpgpusim.config and asserts
+that the key device knobs and the machine-checkable `# SPEC:` markers are
+present and internally consistent:
+
+ * SM count : n_clusters x n_cores_per_cluster == 48
+ * compute capability : major.minor == 7.5, PTX force max capability == 75
+ * memory type : GDDR6 (burst length 16, QDR freq ratio 4)
+ * memory capacity : SPEC vram_gib == 8 (documentation-only; GPGPU-Sim
+ 4.x has no VRAM capacity knob)
+ * L2 size : sets x bsize x assoc x n_mem x n_sub == 4 MiB
+ * bandwidth : buswidth x freq_ratio x DRAM clock x n_mem == 496 GB/s
+ * clocks : base 1650 MHz, DRAM 3875 MHz (15.5 Gbps / 4)
+
+This is a scaffold consistency test, not a calibration: passing says the file
+internally encodes the published TU104 numbers, NOT that the simulator models
+TU104 accurately. Exit code 0 = all checks pass; 1 = at least one mismatch;
+2 = usage/parse error.
+
+Usage:
+ python3 gpgpu-sim/scripts/config_sanity.py [--config PATH] [--quiet]
+"""
+
+from __future__ import annotations
+
+import argparse
+import re
+import sys
+from pathlib import Path
+
+EXPECTED_SPECS = {
+ "sm_count": "48",
+ "memory_type": "GDDR6",
+ "vram_gib": "8",
+ "bus_width_bits": "256",
+ "bandwidth_gbps": "496",
+ "l2_mib": "4",
+ "rops": "64",
+ "tmus": "192",
+ "base_mhz": "1650",
+ "boost_mhz": "1815",
+ "compute_capability": "7.5",
+}
+
+DEFAULT_CONFIG = (
+ Path(__file__).resolve().parents[1]
+ / "configs"
+ / "turing-tu104-2080super"
+ / "gpgpusim.config"
+)
+ICNT_NAME = "config_turing_islip.icnt"
+
+
+def parse_config(path: Path) -> tuple[dict[str, str], dict[str, str]]:
+ """Return (options, spec_markers) parsed from a gpgpusim.config file."""
+ opts: dict[str, str] = {}
+ specs: dict[str, str] = {}
+ for raw in path.read_text(encoding="utf-8").splitlines():
+ spec = re.match(r"^\s*#\s*SPEC:\s*([A-Za-z0-9_]+)\s*=\s*(\S+)\s*$", raw)
+ if spec:
+ specs[spec.group(1)] = spec.group(2)
+ line = raw.split("#", 1)[0].strip()
+ if not line or not line.startswith("-"):
+ continue
+ parts = line.split(None, 1)
+ opts[parts[0]] = parts[1].strip() if len(parts) > 1 else ""
+ return opts, specs
+
+
+class Checker:
+ def __init__(self, quiet: bool = False) -> None:
+ self.quiet = quiet
+ self.passed = 0
+ self.failures: list[str] = []
+
+ def check(self, name: str, condition: bool, detail: str) -> None:
+ if condition:
+ self.passed += 1
+ if not self.quiet:
+ print(f"PASS: {name}: {detail}")
+ else:
+ self.failures.append(f"{name}: {detail}")
+ print(f"FAIL: {name}: {detail}")
+
+ def note(self, text: str) -> None:
+ if not self.quiet:
+ print(f"NOTE: {text}")
+
+
+def parse_int(opts: dict[str, str], key: str) -> int | None:
+ try:
+ return int(opts[key], 0)
+ except (KeyError, ValueError):
+ return None
+
+
+def parse_l2(opts: dict[str, str]) -> tuple[int, int, int] | None:
+ """Parse '<nsets>:<bsize>:<assoc>' from -gpgpu_cache:dl2 S:... ."""
+ m = re.match(r"^S:(\d+):(\d+):(\d+)", opts.get("-gpgpu_cache:dl2", ""))
+ if not m:
+ return None
+ return int(m.group(1)), int(m.group(2)), int(m.group(3))
+
+
+def run_checks(config_path: Path, quiet: bool = False) -> int:
+ if not config_path.is_file():
+ print(f"config_sanity: ERROR: config not found: {config_path}", file=sys.stderr)
+ return 2
+
+ opts, specs = parse_config(config_path)
+ c = Checker(quiet=quiet)
+
+ # 1. spec markers ------------------------------------------------------
+ for key, expected in EXPECTED_SPECS.items():
+ actual = specs.get(key)
+ c.check(
+ f"SPEC {key}",
+ actual == expected,
+ f"expected {expected}, got {actual!r}",
+ )
+
+ # 2. SMs / compute capability -----------------------------------------
+ clusters = parse_int(opts, "-gpgpu_n_clusters")
+ cores = parse_int(opts, "-gpgpu_n_cores_per_cluster")
+ sm_count = None if clusters is None or cores is None else clusters * cores
+ c.check(
+ "SM count",
+ sm_count == int(EXPECTED_SPECS["sm_count"]),
+ f"n_clusters({clusters}) x n_cores_per_cluster({cores}) = {sm_count},"
+ f" expected {EXPECTED_SPECS['sm_count']}",
+ )
+ cc = f"{opts.get('-gpgpu_compute_capability_major', '?')}." \
+ f"{opts.get('-gpgpu_compute_capability_minor', '?')}"
+ c.check(
+ "compute capability",
+ cc == EXPECTED_SPECS["compute_capability"],
+ f"{cc}, expected {EXPECTED_SPECS['compute_capability']}",
+ )
+ c.check(
+ "PTX force max capability",
+ parse_int(opts, "-gpgpu_ptx_force_max_capability") == 75,
+ f"{opts.get('-gpgpu_ptx_force_max_capability', '(missing)')}, expected 75 (sm_75)",
+ )
+
+ # 3. clocks / GDDR6 / memory geometry ---------------------------------
+ clocks = opts.get("-gpgpu_clock_domains", "").split(":")
+ dram_mhz = None
+ if len(clocks) == 4:
+ try:
+ dram_mhz = float(clocks[3])
+ except ValueError:
+ dram_mhz = None
+ c.check(
+ "DRAM clock",
+ dram_mhz == 3875.0,
+ f"{clocks[3] if len(clocks) == 4 else clocks}, expected 3875.0 MHz (15.5 Gbps / 4)",
+ )
+ c.check(
+ "base core clock",
+ len(clocks) == 4 and clocks[0] == "1650.0",
+ f"{clocks[0] if clocks else '(missing)'}, expected 1650.0 MHz",
+ )
+ c.check(
+ "memory type GDDR6",
+ specs.get("memory_type") == "GDDR6"
+ and parse_int(opts, "-gpgpu_dram_burst_length") == 16
+ and parse_int(opts, "-dram_data_command_freq_ratio") == 4,
+ "burst_length="
+ f"{opts.get('-gpgpu_dram_burst_length', '(missing)')}, "
+ "freq_ratio="
+ f"{opts.get('-dram_data_command_freq_ratio', '(missing)')}"
+ " (GDDR6 expected: 16 / 4)",
+ )
+ c.check(
+ "memory chips per controller",
+ parse_int(opts, "-gpgpu_n_mem_per_ctrlr") == 1,
+ f"{opts.get('-gpgpu_n_mem_per_ctrlr', '(missing)')}, expected 1 (upstream Turing convention)",
+ )
+ c.check(
+ "VRAM capacity marker (documentation-only)",
+ specs.get("vram_gib") == "8",
+ "SPEC vram_gib="
+ f"{specs.get('vram_gib')!r}; GPGPU-Sim 4.x has no VRAM capacity knob,"
+ " so 8 GiB is recorded as a spec marker only",
+ )
+
+ # 4. L2 size consistency ----------------------------------------------
+ n_mem = parse_int(opts, "-gpgpu_n_mem")
+ n_sub = parse_int(opts, "-gpgpu_n_sub_partition_per_mchannel")
+ l2 = parse_l2(opts)
+ l2_mib = None
+ if l2 and n_mem and n_sub:
+ sets, bsize, assoc = l2
+ l2_mib = sets * bsize * assoc * n_mem * n_sub / (1024 * 1024)
+ spec_l2 = float(EXPECTED_SPECS["l2_mib"])
+ c.check(
+ "L2 size",
+ l2_mib == spec_l2,
+ f"dl2({l2}) x n_mem({n_mem}) x n_sub({n_sub}) = {l2_mib} MiB,"
+ f" expected {spec_l2} MiB",
+ )
+
+ # 5. bandwidth consistency --------------------------------------------
+ buswidth = parse_int(opts, "-gpgpu_dram_buswidth")
+ ratio = parse_int(opts, "-dram_data_command_freq_ratio")
+ bw_gbps = None
+ if None not in (buswidth, ratio, dram_mhz, n_mem):
+ bw_gbps = buswidth * ratio * dram_mhz * 1e6 * n_mem / 1e9
+ spec_bw = float(EXPECTED_SPECS["bandwidth_gbps"])
+ c.check(
+ "modeled bandwidth",
+ bw_gbps == spec_bw,
+ f"buswidth({buswidth} B) x ratio({ratio}) x DRAM({dram_mhz} MHz)"
+ f" x n_mem({n_mem}) = {bw_gbps} GB/s, expected {spec_bw} GB/s",
+ )
+ bw_bits_ok = False
+ if n_mem and buswidth:
+ bw_bits_ok = (
+ specs.get("bus_width_bits") == "256"
+ and int(EXPECTED_SPECS["bus_width_bits"]) // (8 * n_mem) == buswidth
+ )
+ c.check(
+ "bus width marker",
+ bw_bits_ok,
+ f"SPEC bus_width_bits={specs.get('bus_width_bits')!r}, modeled"
+ f" buswidth={buswidth} B x n_mem={n_mem} (expected {EXPECTED_SPECS['bus_width_bits']} bits"
+ f" = {buswidth} B x {n_mem} modules)",
+ )
+
+ # 6. informational markers not modeled by GPGPU-Sim 4.x ---------------
+ for key, label in (("rops", "ROPs"), ("tmus", "TMUs"), ("boost_mhz", "boost clock")):
+ c.check(
+ f"SPEC {key} present",
+ specs.get(key) == EXPECTED_SPECS[key],
+ f"{label}: {specs.get(key)!r} (expected {EXPECTED_SPECS[key]});"
+ " recorded for documentation, not a simulator knob",
+ )
+
+ # 7. sibling interconnect file (not used with -network_mode 2) -------
+ icnt = config_path.parent / ICNT_NAME
+ c.check(
+ "interconnect config present",
+ icnt.is_file(),
+ f"{icnt}",
+ )
+
+ total = c.passed + len(c.failures)
+ print(
+ f"config_sanity: {c.passed}/{total} checks passed"
+ + (f", {len(c.failures)} failed" if c.failures else "")
+ )
+ if c.failures:
+ for failure in c.failures:
+ print(f"config_sanity: FAILED -> {failure}", file=sys.stderr)
+ return 1
+ print("config_sanity: OK (scaffold consistency only; no accuracy claim)")
+ return 0
+
+
+def main(argv: list[str] | None = None) -> int:
+ parser = argparse.ArgumentParser(
+ description="Sanity-check the GreenEye-GPGPU-Sim TU104 scaffold config."
+ )
+ parser.add_argument(
+ "--config",
+ type=Path,
+ default=DEFAULT_CONFIG,
+ help=f"path to gpgpusim.config (default: {DEFAULT_CONFIG})",
+ )
+ parser.add_argument("--quiet", action="store_true", help="only print failures and summary")
+ args = parser.parse_args(argv)
+ return run_checks(args.config, quiet=args.quiet)
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/debug/risc-v-gsp-rm-vm/gpgpu-sim/scripts/run_sim.sh b/debug/risc-v-gsp-rm-vm/gpgpu-sim/scripts/run_sim.sh
new file mode 100755
index 0000000..85dd11e
--- /dev/null
+++ b/debug/risc-v-gsp-rm-vm/gpgpu-sim/scripts/run_sim.sh
@@ -0,0 +1,109 @@
+#!/usr/bin/env bash
+# run_sim.sh -- run a CUDA binary on the GreenEye-GPGPU-Sim TU104 scaffold.
+#
+# Substitutes the CUDA runtime with GPGPU-Sim's libcudart.so via
+# LD_LIBRARY_PATH (the mechanism documented in the upstream README, "Step 3:
+# Run"), points the simulator at the tracked TU104 scaffold config, and
+# executes the binary from a dedicated run directory so simulator output does
+# not pollute the source tree.
+#
+# Development-only tooling: it simulates; it never touches GPU hardware,
+# kernel modules, mdev, or a guest.
+#
+# Usage:
+# ./run_sim.sh [--workdir DIR] [--build-type release|debug] <cuda-binary> [args...]
+#
+# Prerequisites: ./setup.sh has completed a build, and the binary was linked
+# with `--cudart shared` so it resolves libcudart.so dynamically.
+#
+# Outputs (in the work directory, default gpgpu-sim/build/run/):
+# gpgpusim.config -> symlink to the tracked TU104 config
+# config_turing_islip.icnt -> symlink to the tracked interconnect config
+# gpgpusim_out.txt, gpgpu_inst_stats.txt, ... (upstream simulator outputs)
+set -euo pipefail
+
+HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
+UPSTREAM="$HERE/upstream"
+DEFAULT_CONFIG_DIR="$HERE/configs/turing-tu104-2080super"
+CONFIG_NAME="gpgpusim.config"
+ICNT_NAME="config_turing_islip.icnt"
+BUILD_TYPE="${GPGPUSIM_BUILD_TYPE:-release}"
+WORKDIR="${GPGPUSIM_RUN_DIR:-$HERE/build/run}"
+CONFIG_DIR="$DEFAULT_CONFIG_DIR"
+
+die() { echo "run_sim.sh: ERROR: $*" >&2; exit 1; }
+
+usage() {
+ cat <<'EOF'
+Usage: run_sim.sh [--workdir DIR] [--build-type release|debug] \
+ [--config-dir DIR] <cuda-binary> [args...]
+
+ --workdir DIR directory the binary runs in (default gpgpu-sim/build/run)
+ --build-type TYPE release (default) or debug
+ --config-dir DIR config directory to use (default configs/turing-tu104-2080super)
+ -h, --help this help
+
+The binary must be dynamically linked against libcudart (link with
+"--cudart shared"); LD_LIBRARY_PATH is replaced with the GPGPU-Sim runtime
+so no recompilation for the simulator is needed.
+EOF
+}
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ --workdir) WORKDIR="${2:-}"; shift ;;
+ --build-type) BUILD_TYPE="${2:-}"; shift ;;
+ --config-dir) CONFIG_DIR="${2:-}"; shift ;;
+ -h|--help) usage; exit 0 ;;
+ --) shift; break ;;
+ -*) usage >&2; exit 2 ;;
+ *) break ;;
+ esac
+ shift
+done
+
+[ $# -ge 1 ] || { usage >&2; exit 2; }
+[ -n "$WORKDIR" ] || die "--workdir requires a value"
+[ -n "$CONFIG_DIR" ] || die "--config-dir requires a value"
+case "$BUILD_TYPE" in release|debug) ;; *) die "unknown build type '$BUILD_TYPE'" ;; esac
+
+BIN="$1"; shift
+
+case "$BIN" in
+ */*)
+ [ -e "$BIN" ] || die "binary not found: $BIN"
+ BIN="$(cd "$(dirname "$BIN")" && pwd)/$(basename "$BIN")"
+ ;;
+ *)
+ resolved="$(command -v "$BIN" || true)"
+ [ -n "$resolved" ] || die "binary '$BIN' not found in PATH"
+ BIN="$resolved"
+ ;;
+esac
+
+[ -d "$CONFIG_DIR" ] || die "config dir not found: $CONFIG_DIR"
+[ -f "$CONFIG_DIR/$CONFIG_NAME" ] || die "missing $CONFIG_DIR/$CONFIG_NAME"
+
+LIBDIR="$(find "$UPSTREAM/lib" -maxdepth 3 -type d -name "$BUILD_TYPE" 2>/dev/null | sort | head -n 1 || true)"
+[ -n "$LIBDIR" ] || die "no GPGPU-Sim runtime library dir under $UPSTREAM/lib; run ./setup.sh first"
+if ! ls "$LIBDIR"/libcudart.so* >/dev/null 2>&1; then
+ echo "run_sim.sh: WARNING: no libcudart.so in $LIBDIR; the binary may load the system CUDA runtime" >&2
+fi
+
+mkdir -p "$WORKDIR"
+ln -sfn "$CONFIG_DIR/$CONFIG_NAME" "$WORKDIR/$CONFIG_NAME"
+if [ -f "$CONFIG_DIR/$ICNT_NAME" ]; then
+ ln -sfn "$CONFIG_DIR/$ICNT_NAME" "$WORKDIR/$ICNT_NAME"
+fi
+
+export GPGPUSIM_ROOT="$UPSTREAM"
+export LD_LIBRARY_PATH="$LIBDIR${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
+export CUDA_INSTALL_PATH="${CUDA_INSTALL_PATH:-/usr/local/cuda}"
+
+echo "run_sim.sh: binary : $BIN"
+echo "run_sim.sh: config : $CONFIG_DIR/$CONFIG_NAME"
+echo "run_sim.sh: workdir : $WORKDIR"
+echo "run_sim.sh: runtime libs: $LIBDIR"
+
+cd "$WORKDIR"
+exec "$BIN" "$@"