# 41 — Phased practical improvements to risc-v-gsp-rm-debugger: stability and time-to-value report > **Date:** 2026-10-03. **Scope:** the simulator/debugger workstream inside > `debug/risc-v-gsp-rm-vm/` only. **Verdict:** the minimum bar for marking the > *tool and standalone GSP simulator* as **stable (conditional)** is passed: > 417 tests green (298 at the first review; the XMPU/libos wave added the > rest), deterministic real-firmware runs, an independently > reproduced A/B verdict "above the QEMU line", and reproducible value > measurements. Conditions are listed in §7 — chiefly that the device model > currently reaches boot rung B3 (message-loop port wait; the CSB poll awaits > host traffic) and cycle numbers are > modelled, not silicon-calibrated. > > Companion: `../../../../handoff-simulator.md` (directive ledger, top work). > Public text describes components and behaviour only. ## 1. What we were doing before (the QEMU baseline) * The only execution engine was `qemu-system-riscv64` via the gdbstub. On the real `gsp-570.144.fwimage.bin` it loaded flat, executed a handful of instructions, faulted at firmware vaddr `0x4009014` reading `0x2000000000000A00`, then looped on `mtvec=0`. * Questions about GSP boot progress could only be answered by static reading of decompiled code; every dynamic question stalled at the first fault. * Tool runs produced sessions, but with no device semantics, no cycle context, and no way to prove "the emulator knows more than the probe". * New-firmware triage was a manual sequence of probe + version diff + reading. ## 2. What we are doing now (the upgrade, phased) | Phase | Improvement | Status | |---|---|---| | P1 | **GSP device model** (`sim/devices/`, `sim/profiles/`) with PMC/FALCON/PRISCV/timer/CSB/FWSEC/PMU/DMA/IRQ windows, versioned profile, boot shims, **XMPU model** (`sim/mpu.py`) and **libos service model** (`sim/libos.py`) | B3: 474,043 instr, `ecall` port wait, 0 unknown MMIO, two-run identical | | P2 | **`sim.gsp_boot` boot-ladder runner** with rung classification and serialisable device state | B0–B3 (B4/B5 targets) | | P3 | **One-command release triage** (`./risc-v-gsp-rm-debugger.sh triage`) orchestrating identity/QEMU probe/native boot/A-B eval/version diff/readiness | 570.144 in ~2.7 s; baseline pair ~11.4 s | | P4 | **QEMU-line A/B evaluation harness** (`harness/sim_qemu_line.py`, frozen checks) | verdict `above`, all threshold checks computed from live runs | | P5 | **Real RE demonstration** (`harness/re_demo.py`) answering a concrete bootstrap question with simulator tools | PASS 5/5, 0.13 s vs 601 s baseline floor | | P6 | **MCP native-backend tools** (launch, cycles, device state, profile, regions, budgets) | 55 MCP tests green; read-only default preserved | | P7 | **Documentation and workflow review** (`docs/39`), docs 30–41, README/Makefile integration, link checks | 143 tool files link-checked, 0 broken | ## 3. Proof of value (before → after) | Scenario | Before | Now | Evidence | |---|---|---|---| | What happens in GSP boot before the first wall? | QEMU: fault at `0x4009014`, stop | Device model serves the path; deterministic B3 port wait (`ecall @ 0x4018038`); unknown accesses 0 | `python3 -m sim.gsp_boot`; sessions `dumps/gsp-boot-b3-run1/2` | | Triage a new firmware image | manual probe + reading, ~1800 s estimated | one command, **2.68 s**, JSON+MD report with hashes | `./risc-v-gsp-rm-debugger.sh triage --firmware … --version 570.144` | | Is the emulator better than QEMU? | no mechanism | validators run both, compute rung/feature deltas; verdict `above` | `python3 harness/sim_qemu_line.py` | | Answer a bootstrap RE question | static reading only | 5/5 recorded answers in 0.13 s | `python3 harness/re_demo.py` | | Scripted/agent operation against the simulator | QEMU-only MCP | native backend tools tested | `tests/test_mcp.py` | Baselines are explicitly labelled estimates where they are not measured human studies (frozen thresholds: 600 s RE-time floor, 1800 s triage baseline); all wall times are labelled host-load dependent. Every number above has a one-line command in the report/doc that produced it. ## 4. Stability evidence * `python3 -m unittest discover -s tests -t .` → **417 tests, OK** (298 at the first review; the XMPU/libos wave added 13 boot/MPU checks plus WPR2 and trace-number updates); MCP 55, triage 14, device model 35 included. * Determinism: B1/B3 device-state SHA identical across runs; triage sessions hashed; A/B harness repeats native runs and compares. * Back-compat: `Session`, `RspClient`, `SimClient` and CLI keep prior behaviour; additions are keyword/default forms; QEMU path untouched (toggle `--backend qemu|native`). * Boundary compliance: no writes outside the tool dir; no hardware, module, guest, mdev, reboot or RM 610 action; MCP read/observe default unchanged. * Fidelity honesty: cycles are labelled *modeled*; L2 is not claimed silicon-accurate; L3 device semantics are declared assumptions in-session; "above QEMU" is computed against the frozen rung contract, not asserted. ## 5. Adversarial review record * **Round 1** (review + fix): 3 P1s found and fixed — device model not wired into the A/B harness/triage, dead PTIMER window offsets, MCP device-state returning a non-JSON object. P2 backlog listed. * **Round 2** (independent, harsher): falsification runs confirmed all headline numbers; 2 P1s found and fixed (docs/35 B1 overclaim; personal host path in `gpgpu-sim/setup.sh`), 8 P2s fixed (timer opt-in, FWSEC state derivation, DMA refusal counting, PMC chip-ID duplication, overlapping window fallback, stale doc counts, `session_launch` documentation, docs/40 measurement labels). One latent item recorded: WPR2 window offsets versus profile base — left unserved because the old B2 run never reached the read; the XMPU/libos wave reached it and the offset defect was fixed (relative and absolute forms both accepted, docs/36 §3). * Verdict after fixes: conditional stability as stated in §7; no unverified "beats silicon" or "boots RM" statement anywhere. ## 6. Top work for the next session (time-to-value first) 1. **Push the device model to B4/B5** (host-traffic-triggered CSB/TRANSCOM poll semantics, one scripted message served end-to-end) — this is the gate to serving a real RM message and the largest remaining time-to-value lever. *Update 2026-10-03, session 4c: the XMPU model, bootstrap-args shim and libos service model landed; the ladder is now B3 (was B2), with the former DMEM-runspace unknown resolved.* 2. **Surgical rehost of the live GR engine-context promote/commit wall** (docs/39 top-3): convert the manual, multi-cycle physical campaign into device-free hook/watch/compare sessions. 3. **Physical-cycle capture → session → compare** helper (read-only), to cut the dominant recorded cost of manual evidence assembly. 4. Everything else remains in the private handoff: GPGPU-Sim board model, VF bridge (`GREENEYE_GSP_EM_BRIDGE`, default OFF), VBIOS, fabric, Ampere/Blackwell, and the "not useful yet" list. ## 7. Conditions on the stability claim 1. Device model ceiling is B3 (libos init complete; message-loop port wait); B4/B5 (host-traffic-triggered CSB poll, scripted message) pending. 2. Cycle counts are modelled defaults, not calibrated bands. 3. Manual-baseline speedups use labelled estimates, not timed human studies. 4. Cross-version triage was exercised as a self-diff rehearsal (no second local firmware version); RM 610 remains human-gated. 5. The stability claim covers the tool and its standalone GSP simulator, not any GPGPU-Sim integration or silicon equivalence. ## 8. Reproduce everything ```bash cd open-iov/debug/risc-v-gsp-rm-vm python3 -m unittest discover -s tests -t . # 417 tests python3 -m sim.gsp_boot # B3 (port wait) python3 -m sim.gsp_boot --no-shim # B1 budget stop python3 harness/sim_qemu_line.py # verdict "above" python3 harness/re_demo.py # PASS 5/5 ./risc-v-gsp-rm-debugger.sh triage \ --firmware ../../../firmware/57X-GSP/570.144/gsp-570.144.fwimage.bin \ --version 570.144 --out /tmp/triage-570.144 ```