Files
retroDE_ps2/docs/ch258_outcome_and_ch259_brief.md
T
thejayman77 ec82764bef Initial commit: retroDE_ps2 — first-of-its-kind PS2 GS FPGA core (DE25-Nano / Agilex 5)
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>
2026-06-29 20:10:50 -04:00

158 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.