From cc79b478843f0230fe6aa8ecd822de7ba71c891e Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Sat, 3 Oct 2026 14:05:38 -0400 Subject: 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 --- debug/risc-v-gsp-rm-vm/docs/32-GSP-CYCLE-MODEL.md | 187 ++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 debug/risc-v-gsp-rm-vm/docs/32-GSP-CYCLE-MODEL.md (limited to 'debug/risc-v-gsp-rm-vm/docs/32-GSP-CYCLE-MODEL.md') diff --git a/debug/risc-v-gsp-rm-vm/docs/32-GSP-CYCLE-MODEL.md b/debug/risc-v-gsp-rm-vm/docs/32-GSP-CYCLE-MODEL.md new file mode 100644 index 0000000..018e07c --- /dev/null +++ b/debug/risc-v-gsp-rm-vm/docs/32-GSP-CYCLE-MODEL.md @@ -0,0 +1,187 @@ +# 32 — GSP cycle model (increment 0, in development) + +> **Status: in development (Phase 1.5, work package WP1.5.1 increment 0).** +> This page describes a table-driven **modeled** cycle count added to the +> native reference core (`sim/`) and a bounded, deterministic "cycle-0" +> profile of the real 570.144 GSP firmware. It makes **no silicon timing, +> performance, latency or accuracy claim**: the numbers are modeled defaults +> under an explicit table, not measurements. The simulator's fidelity +> statement is unchanged — L0 (instruction semantics) and L1 (memory +> behaviour) are modelled; **L2 (time/concurrency) is not** (`06-ACCURACY.md`). +> Development-only: nothing here authorises GPU hardware, kernel modules, +> mdev or guest access. + +## 1. Purpose + +The native simulator reports virtual time as an instruction count (`insns`). +That is enough for functional debugging but not for comparing instruction +mixes, for calibration-table work, or for a first, honest cycle-shaped +artifact from a real firmware run. Increment 0 adds: + +* `sim/cycles.py` — an isolated, per-instruction-class latency table with a + deterministic cost function; +* a `cycles` counter on `sim.machine.Machine`, advanced by that table + alongside the existing instruction count; +* `sim/gsp_profile.py` — a bounded, read-only run of the real + `firmware/57X-GSP/570.144/gsp-570.144.fwimage.bin` that records a normal + `greeneye-session/1` directory with the modeled cycle totals; +* `tests/test_sim_cycles.py`. + +Everything is stdlib-only Python 3.10+, offline, and read-only with respect to +the firmware image. + +## 2. The model + +`sim/cycles.CycleModel` is a plain Python table. All defaults are **modeled** +from public, generic in-order RISC-V pipeline assumptions — one cycle for +plain ALU work, conservative multi-cycle M-extension costs, a fixed extra +latency for a completed memory access — and are deliberately *not* derived +from the GSP core, from silicon or from vendor data. + +| Class | Default | Notes | +|---|---|---| +| ALU / shift / `lui` / `auipc` / op-imm | 1 | add, sub, logical, compare | +| branch | 1 | taken/not-taken penalty deliberately not modelled | +| `jal` / `jalr` | 1 | | +| `mul` / `mulh` / `mulhsu` / `mulhu` | 3 | conservative | +| `div` / `divu` / `rem` / `remu` | 20 | conservative, data-independent | +| load / store | 1 | plus a completed-access latency (below) | +| AMO (`lr`/`sc`/`amo*`) | 2 | plus one completed-access latency | +| CSR | 2 | | +| trap (`ecall`/`ebreak`/`mret`) | 3 | | +| `fence` / `fence.i` | 1 | no ordering model (single hart) | +| illegal | 1 | execution stops immediately | + +Memory latency is a **parameter**, not a cache model: + +| Parameter | Default | Meaning | +|---|---|---| +| `memory_latency` | 3 | extra cycles when a RAM access completes | +| `mmio_latency` | 12 | extra cycles when an unmodelled-MMIO access completes | + +The cost of one instruction is `instruction_cost(kind, sub)`; a completed +load/store/AMO adds `memory_cost(is_mmio)` on top. Cost depends only on the +decoded instruction class (`sim/decode.py` kind/sub) and the access region: +no host clock, no entropy, no caches, no hazards. `CycleModel.describe()` +emits the full table for session metadata. + +## 3. Machine integration + +`sim.machine.Machine` keeps its previous behaviour exactly; cycles are +additive: + +```python +from sim.machine import Machine + +m = Machine() # DEFAULT_MODEL active +m.run(10_000) +m.insns # virtual time (unchanged semantics) +m.cycles # modeled cycles, advanced by the table +m.cycle_model.name # "rv64imac-modeled/1" + +off = Machine(cycle_model=False) # cycles stays 0; disabling path for A/B +slow = Machine(cycle_model=CycleModel(memory_latency=9)) +``` + +`greeneye.sim_backend.launch_native(..., cycle_model=...)` threads the choice +through the Session API (`None` = default table, `False` = off, or an +instance). The counter increments for the instruction the machine stops on +under a watchpoint/breakpoint, mirroring how `insns` counts it; the memory +latency is only added when the access actually completes. Determinism is by +construction: two identical runs produce identical instruction and cycle +totals (tested). + +Measured overhead on this host (CPython 3.12, 200k instructions of the real +image, best of three): ~0.073 s with accounting disabled vs ~0.082 s enabled +(~12%); disabled runs are byte-for-byte the pre-increment behaviour. + +## 4. The cycle-0 GSP profile + +```bash +# bounded, deterministic, read-only; writes a session under dumps/ +python3 -m sim.gsp_profile --instructions 200000 + +# explicit session directory and machine-readable result +python3 -m sim.gsp_profile --record dumps/gsp-cycle0 --json + +# start from a harvested first-touch map and keep what the run learned +python3 -m sim.gsp_profile --device-map dumps//device-map.json --learn --learn-out /tmp/map.json + +# image absent (e.g. LFS not fetched): exits 2 with a skip reason, no session +python3 -m sim.gsp_profile --image /nonexistent.bin +``` + +The profile mirrors the established device-map/probe path: the ELF's PT_LOAD +plan is relocated by `bias=0x80000000` (`greeneye/elf.py`), RAM is sized to +cover the image as `greeneye/device_map.py` computes it, and all unmodelled +accesses are served leniently (zero or the mapped value) through a +`greeneye-device-map/1`. The instruction budget is exact, not wall-clock: +`Machine.run(budget)` is called directly, so the run is deterministic. + +Session metadata (`session.json`) and a `gsp_cycle_profile` event carry: +`firmware_sha256`, `bias`, `instructions_executed`, `cycles`, +`cycle_model`, `cycle_model_table`, `cycle_fidelity`, `stop_reason`/`stop_pc` +(both relocated and firmware-space), `mmio_unknown` and the first unknown +MMIO access. + +**Observed output** (this tree, 2026-10-03; sha256 +`2d1bb5c6…c3ceea`, budget 200 000): + +``` +instructions: 200000 +cycles (modeled): 200012 +stop: budget pc=0x84009070 (fw 0x4009070) +unknown MMIO accesses: 1 +first unknown MMIO: pc=0x84009014 addr=0x2000000000000a00 size=4 rw=r +``` + +This is a bounded lenient first-touch profile, **not a boot**: it reproduces +the documented QEMU probe first-touch address and continues under the modeled +lenient policy for the budget. The stop PC is a budget sample inside the +firmware's early path, not a milestone. + +## 5. What is not claimed + +* No silicon timing, latency, throughput, frequency or pipeline claim; the + table is a modeled default and says so in code, metadata and reports + (`sim/cycles.py::NOTE`, `CYCLE_FIDELITY`). +* No cache/memory-hierarchy model: `memory_latency`/`mmio_latency` are fixed + parameters, not simulated caches or DRAM. +* No device model: L3 remains absent (`06-ACCURACY.md`); the profile runs + under lenient MMIO, so its control flow after the first unknown access is + conditioned on that policy, not on device behaviour. +* No accuracy metric may be computed from this increment alone. Calibration + (`RISC-V-GSP-RM-DEBUGGER-ROADMAP.md`, `16-CUSTOM-SIMULATOR.md`) still + requires sourced latency tables and, for any product-facing claim, + supervised physical confirmation. + +## 6. Tests + +`tests/test_sim_cycles.py` (21 tests, all offline): + +* table sanity (every decoded kind has a positive cost; ALU/branch/jump unit + cost; M-extension ordering; memory latency is a parameter; labeling); +* counter arithmetic on hand-assembled programs (RAM vs MMIO latency); +* disabling the model leaves `cycles` at 0 and changes no execution state; +* determinism double-runs at machine and profile level; +* the bundled demo executes identically with and without the model; +* real-image bounded profile: first touch matches the documented probe + address, session metadata carries the cycle totals, two runs are identical; +* absent image skips cleanly. + +## 7. Next steps + +1. Device model (WP1.5.2): falcon/SEC2 windows, CSB/TRANSCOM, WPR2/FWSEC, + PTIMER, IRQ routing — the run then stops modelling MMIO leniently. +2. Boot shims with recorded assumptions (WP1.5.3) so the profile can report a + real milestone instead of a budget sample. +3. Sourced instruction/access latency tables and a documented calibration + metric (`06-ACCURACY.md`, `16-CUSTOM-SIMULATOR.md`) before any + timing-shaped statement; per-MCU cycle domains come with + WP1.5.4/WP1.5.5. +4. Additive `cycle` event class in the session schema (roadmap V2, "formats + and versioning") once the event vocabulary is reviewed. + +The increment is deliberately a table and a counter: every later step can +replace defaults without touching the execution loop (the model is passed in) +or the session format (metadata is additive). -- cgit v1.2.3