ec82764bef
RTL (GS rasterizer, EE core stub, platform bridge, LPDDR4B path), sim regression (272 TBs), docs, and tooling. Copyrighted PS2 content (BIOS, game code, GS dumps, and all dump-derived textures/traces) is excluded via .gitignore and stays local. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
158 lines
6.8 KiB
Markdown
158 lines
6.8 KiB
Markdown
# Ch258 outcome + Ch259 brief for Codex
|
||
|
||
**Status:** Ch258 landed cleanly. PCR was not the gate. Treadmill
|
||
unchanged. Next observed blocker named. Pausing for Codex's call on
|
||
Ch259 before further code changes.
|
||
|
||
## Ch258 implementation (per Codex spec)
|
||
|
||
`rtl/ee/ee_bootstrap_mmio_stub.sv` gained:
|
||
|
||
- New parameter `MMIO_10F0_PCR_VALUE = 32'h0765_4321` (IOP DMAC PCR
|
||
reset value, matches PS1/IOP reference).
|
||
- New localparam `OFFSET_10F0_WIDX = 14'h043C` (= `0x10F0 >> 2`).
|
||
- Read path: when `rd_idx == OFFSET_10F0_WIDX`, return
|
||
`MMIO_10F0_PCR_VALUE` instead of latched-zero. Mirrors the Ch202
|
||
pattern for `0x1814` exactly.
|
||
- Trace path: matching ternary so the stub-emitted `EV_READ`
|
||
event carries the actual PCR value in `ev_arg1` (not zero).
|
||
- Writes to `0x10F0` continue to latch into `regs[]` for future
|
||
reads (BIOS DOES write the PCR back, see verification below).
|
||
|
||
Framed in comments as a **realism stub**, not "the fix" — wording
|
||
mirrors Codex's directive.
|
||
|
||
## Verification — hardcode actually reaches the EE
|
||
|
||
`sim/traces/rtl/ee_bios_smoke_core.trace` (post-Ch258):
|
||
|
||
```
|
||
221902:766613 EE IFETCH 0xbfc4d2cc 0x8dce10f0 0xbf8010f0 0x07654321 0x00000002
|
||
221906:766628 EE IFETCH 0xbfc4d2dc 0x8c2010f0 0xbf8010f0 0x07654321 0x00000002
|
||
222243:767900 EE IFETCH 0xbfc4d348 0xac2e10f0 0xbf8010f0 0x07654321 0x00000001
|
||
222245:767908 EE IFETCH 0xbfc4d350 0x8c2010f0 0xbf8010f0 0x07654321 0x00000002
|
||
```
|
||
|
||
EE retires `lw $14, 0x10f0($14)` at PC=`0xbfc4d2cc` and **`$14`
|
||
now holds `0x07654321`** (column 4). BIOS then `sw $14, 0x10f0($1)`
|
||
at PC=`0xbfc4d348` — i.e., it **reads the PCR, then writes the
|
||
same value back**, as part of a read-modify-restore pattern.
|
||
Map trace confirms the writes:
|
||
|
||
```
|
||
290741:767899 MEM WRITE 0xbf8010f0 0x07654321 0x00 region=9
|
||
```
|
||
|
||
Hardcode is verifiably propagating to the EE register file and back
|
||
through the write port. Not a build glitch, not stale state.
|
||
|
||
## Behavioural outcome — treadmill unchanged
|
||
|
||
Comparison of the v7 baseline (pre-Ch258, observer with all-EE-RAM
|
||
filter) vs. Ch258-verify run (same observer, with PCR hardcode):
|
||
|
||
| metric | v7 (pre) | Ch258-verify (post) |
|
||
|----------------------------|-------------------------|---------------------|
|
||
| `Ch217 CALLER_PASSES` | 8 | 8 |
|
||
| `Ch216 RESTORE_PASSES` | 8 | 8 |
|
||
| `Ch217 verdict` | `longjmp_return_repeats_due_to_static_state` | (same) |
|
||
| `Ch218 captures` | 172 | 172 |
|
||
| `retired_events` (final) | 24,029,051 | 24,029,051 |
|
||
| stdout-log md5sum | `e389701d…` | `e389701d…` (byte-identical) |
|
||
|
||
`make run` full regression: **155 PASS / 0 FAIL** with the Ch258
|
||
hardcode in place. No regression risk.
|
||
|
||
Per Codex's acceptance: *"Either BIOS escapes the treadmill, or
|
||
Ch258 closes with 'PCR was not the gate' and names the next observed
|
||
blocker."* — **Ch258 closes with "PCR was not the gate."**
|
||
|
||
## Next observed blocker — IOP INTC at `0x1F801070..0x1F801077`
|
||
|
||
The v7 + Ch258-verify Ch218 capture (172 entries across all 8 passes,
|
||
EE-RAM scans filtered out) ranks reads by frequency:
|
||
|
||
```
|
||
35× ea=0x1f801074 ← IOP INTC at offset 4 (mask alias / write-clear region)
|
||
24× ea=0xbf8010f0 ← IOP DMAC PCR (NOW HARDCODED by Ch258)
|
||
21× ea=0x1f801070 ← IOP INTC I_STAT (pending bits)
|
||
8× ea=0xfffe0130 ← EE BIU control (already absorbed by ee_biu_mmio_stub)
|
||
7× each ea=0xa000b1e0..b20c ← our own Ch215 jmp_buf FSM reads (noise)
|
||
```
|
||
|
||
**The IOP INTC pair `0x1F801070`/`0x1F801074` is read 56 times across
|
||
the 8 treadmill passes** — more than twice the PCR rate. BIOS is
|
||
polling the IOP INTC for a pending bit or mask change between
|
||
syscall #8 cycles.
|
||
|
||
Both addresses land in `ee_bootstrap_mmio_stub`'s window (covers
|
||
`0x1F800000-0x1F80FFFF`). Currently both return latched-zero. Real
|
||
PS2 IOP INTC behavior:
|
||
|
||
- `0x1F801070` `I_STAT` — pending interrupt bitmap. W1C semantics.
|
||
Resets to 0. Real hardware sets bits when SIF, VBLANK, TIMER, etc.
|
||
fire on the IOP side.
|
||
- `0x1F801074` `I_MASK` — interrupt mask. Plain RW. Resets to 0.
|
||
|
||
This is **trickier than the PCR hardcode** because:
|
||
|
||
1. Hardcoding `I_STAT` to nonzero implies "interrupts are pending"
|
||
— BIOS will then try to dispatch through its IOP-interrupt-
|
||
handler infrastructure, which we may not have set up.
|
||
2. Hardcoding `I_MASK` to nonzero is harmless (it's just a mask
|
||
value), but BIOS reads it to check what's enabled, not as a
|
||
gate.
|
||
3. The "real" fix is to wire an interrupt source through to
|
||
`I_STAT` so the pending bit transitions on a hardware event
|
||
(SIF mailbox write, timer rollover, etc.). That's a model-
|
||
the-source chapter, not a Ch202-style hardcode.
|
||
|
||
## Three candidate Ch259 paths
|
||
|
||
**A. Sticky-set `I_STAT` hardcode.** Mirror Ch202's pattern: when
|
||
`rd_idx == OFFSET_1070_WIDX`, return some specific bit pattern
|
||
(e.g., bit corresponding to "SIF transfer complete" or "IOP boot
|
||
done"). Cost: ~5 lines in `ee_bootstrap_mmio_stub`. Risk: BIOS
|
||
might try to dispatch the indicated interrupt and hit unsupported
|
||
COP0 / handler code; might cause a new trap. Could be the
|
||
treadmill-breaker OR the next-stuck-point.
|
||
|
||
**B. Source-modeling.** Wire an actual interrupt source (e.g., from
|
||
`platform_video_stub.vblank`, or a synthetic periodic pulse) into
|
||
the IOP-side `intc_stub.irq_src[]`. Then the EE-side read at
|
||
`0x1F801070` reflects real (model-driven) state. Requires
|
||
instantiating IOP-side intc/map in the BIOS-smoke TB hierarchy.
|
||
Bigger scope, more honest.
|
||
|
||
**C. Re-frame.** The treadmill may not be a single polled-register
|
||
problem at all — it might be that BIOS is in a kernel scheduler
|
||
loop that requires a *combination* of state to flip (timer + INTC +
|
||
syscall return code). Ch259 could be a deeper observer that tracks
|
||
INTC reads' DATA values across passes (since `ev_arg1` IS carried
|
||
correctly for `ee_bootstrap_mmio_stub` events — I just need to
|
||
sample from the right trace) to confirm whether all 56 INTC reads
|
||
return the same value or vary.
|
||
|
||
## What changed in the tree
|
||
|
||
- `rtl/ee/ee_bootstrap_mmio_stub.sv` — Ch258 PCR hardcode + trace
|
||
ternary update.
|
||
- `sim/tb/integration/tb_ee_core_bios_smoke.sv` — Ch218 observer
|
||
still in place (Codex said keep for now). Currently filters out
|
||
BIOS ROM + all EE RAM (v7 config).
|
||
- `docs/wave3_bios_iop_sbus_recon.md` — Ch256/Ch257 dependency map
|
||
(not updated since v5).
|
||
- `docs/ch257_codex_brief.md` — the 7-iteration writeup from the
|
||
middle of the night.
|
||
- This file — Ch258 outcome + Ch259 hand-off.
|
||
|
||
## Decision needed from Codex
|
||
|
||
1. Ch259 path? (A / B / C / something else)
|
||
2. Should Ch218 observer be tightened or removed before Ch259, or
|
||
left as-is for verification?
|
||
3. Anything to clean up from the v1-v7 iteration drift (revert
|
||
filters, simplify the verdict, etc.)?
|
||
|
||
Pausing all code changes until your call.
|