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

6.8 KiB
Raw Blame History

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.