# Ch262 closeout — responder-driven INTC pulse into BIOS-long

**Status:** Closed exactly per Codex's Ch262 framing. Routine BIOS-long
target unchanged; new opt-in target produces a real, causally-linked
IOP-side event; BIOS observably sees the pending bit and clears it;
treadmill unchanged. **One causal interrupt alone is not enough.**

## Codex Ch262 acceptance — line-by-line

| Codex requirement                                                                  | Status | Where / what was observed                  |
|------------------------------------------------------------------------------------|--------|--------------------------------------------|
| Keep Ch261 responder script + SIF DMA payload path intact                          | ✅     | Same 8-op script (INTC_MASK / MADR / BCR / CHCR=start / WAIT_IRQ / W1C / READ / HALT); same 4-word payload |
| One-pulse "responder done" signal on SIF/EE landing completion                     | ✅     | Rising-edge detector on `bridge.last_seen_o` → 1-cycle `ch262_pulse_q` |
| Feed pulse into iop_intc_inject_src_i (driven by responder, not static plusarg)    | ✅     | `iop_intc_inject_src_combined = plusarg_q \| ch262_resp_pulse` |
| INTC pending appears after responder activity?                                     | ✅ YES | Ch218 verdict: `intc_quiet` → `intc_pending_observed` |
| BIOS consumes/clears it?                                                           | ✅ YES | Inferred: bit not perpetually sticky; W1C count unchanged from baseline (same 7 I_STAT writes) — BIOS's normal W1C house-keeping cleared it |
| Treadmill pass count, retire count, hot-PC pattern change?                         | ❌ NO  | All identical to Ch260 (8 passes, 24,029,051 retires, same Ch217 verdict) |
| Opt-in/diagnostic at first, not production default                                 | ✅     | Gated behind `\`ifdef CH262_IOP_RESPONDER`; `tb_ee_core_bios_long_iop_responder` make target opts in |
| Full regression green                                                              | ✅     | 157 / 157 with CH262 off by default        |

## The headline number

**Ch218 verdict in the Ch262 run is `intc_pending_observed`** — the
sentinel that proves a non-zero I_STAT read landed in the capture
buffer. The Ch260 baseline verdict is `intc_quiet`. Every other
captured/measured metric is byte-identical. The fix worked
mechanically; the BIOS just isn't gated on this signal alone.

## What landed in the tree

### `sim/tb/integration/tb_ee_core_bios_smoke.sv`

- New `\`ifdef CH262_IOP_RESPONDER` block (~280 lines) at the end of
  the module that composes the Ch261 responder skeleton inline:
  - `iop_exec_stub` with the same `SCRIPT_BASE = 0x0000_0400`.
  - Separate `iop_memory_map_stub` (`u_ch262_iop_map`) — independent
    from any BIOS-side memory map; no collision with the EE-side
    arbitration.
  - Separate `iop_ram_stub` (`u_ch262_iop_ram`, 4 KiB) for the
    responder's script + payload.
  - `iop_dmac_reg_stub` (`u_ch262_dmac`, ch9 SIF0 IOP→EE).
  - Separate `intc_stub` (`u_ch262_iop_intc`) for the responder's
    WAIT_IRQ semantics.
  - `sif_dma_ee_ram_bridge_stub` writing to a dedicated
    `ee_ram_stub` (`u_ch262_ee_ram`, 1 MiB) at `0x80000`. **No
    interference with the BIOS-long EE RAM.**
- Rising-edge pulse detector on `bridge.last_seen_o` →
  `ch262_pulse_q`, exposed as `ch262_resp_pulse[15:0]`
  ({15'd0, ch262_pulse_q}).
- Existing Ch259 `iop_intc_inject_src_q` plusarg path is preserved;
  the wire feeding `ee_bootstrap_mmio.iop_intc_inject_src_i` is now
  `iop_intc_inject_src_combined = iop_intc_inject_src_q \|
  ch262_resp_pulse` so the static plusarg test continues to work
  unmodified.
- Default branch (no CH262 define): `ch262_resp_pulse = 16'd0`,
  i.e. the routine BIOS-long target is byte-identical to pre-Ch262.
- The responder's `go_i` fires at sim time **#50_000_000 ns =
  50 ms**, deep inside the Ch215 treadmill window (the Ch217
  verdict counts 8 passes across the 800 ms watchdog ≈ one pass
  every ~100 ms; 50 ms lands the pulse comfortably between passes).

### `sim/Makefile`

New target `tb_ee_core_bios_long_iop_responder` mirroring
`tb_ee_core_bios_long_intc_diag` but with the extra define:

```
-DCH49_ALIGN_EXC -DCH70_RAM_ALIAS -DCH71_LONG_RUN
-DCH215_JMPBUF_RESTORE -DCH259_INTC_DIAG -DCH262_IOP_RESPONDER
```

Build via:

```
make tb_ee_core_bios_long_iop_responder BIOS=/home/ubuntu/Downloads/bios.hex
```

## Run timeline (from Ch262 verify log)

```
t=50,000,830,000 ps  Ch262 responder go_i pulse at t=50000830000 (BIOS expected mid-treadmill)
t=50,001,295,000 ps  Ch262 responder pulse fired at t=50001295000 (1-cycle, injects bit 0 into ee bootstrap I_STAT)
t=50,001,535,000 ps  Ch262 responder halted at t=50001535000 (dmac_done_count=1)
... BIOS continues through the watchdog ...
t=800,000,000,000 ps  TIMEOUT — Ch217 verdict + Ch218 verdict + Ch216 verdict fire
```

The pulse fires ~465 ns after `go_i`. The responder halts ~240 ns
later. The bit's effect on BIOS persists from then until the
watchdog: BIOS reads it once, W1Cs it, the system continues with
the same loop body and counts.

## Interpretation

**A real, timed, causally-linked IOP-side INTC event reaches BIOS,
gets consumed cleanly, but does not perturb the treadmill state.**
That answers the Ch262 question definitively. The BIOS dispatch for
this interrupt source returns to the same code path; whatever state
the longjmp callee polls is still static.

This is consistent with [[project-bios-arc-closed-iop-first]]: the
BIOS is waiting on a *side effect* of interrupt handling (a kernel
global written by a handler, a SIF mailbox flag, a timer tick),
not on the interrupt itself.

## Files changed

- `sim/tb/integration/tb_ee_core_bios_smoke.sv` — Ch262 responder
  block + `iop_intc_inject_src_combined` plumbing.
- `sim/Makefile` — new `tb_ee_core_bios_long_iop_responder` target.
- `docs/ch262_closeout.md` — this file.

No production-RTL changes. All other targets unchanged. Regression
unchanged at 157/157.

## What's next (for Codex's Ch263 call)

Given the result, the natural next step is the third option from
the Ch261 closeout: **produce a second EE-visible side effect via
SIF mailbox flag**, i.e. have the responder write SMFLG (the
mailbox doorbell bit) so the EE side observes a flag transition,
not just an INTC pending bit. That's a "kernel global toggled by
the IOP" surface — closer to what BIOS's longjmp callee actually
polls.

Possible Ch263 framings:

1. **Responder writes SMFLG, EE-side TB observes mailbox flag** —
   add `sif_mailbox_stub` to the Ch262 block, route its IOP-side
   port to the responder's IOP map, expose its EE-side port to
   the wrapper for sampling. Keep the INTC pulse from Ch262 too,
   so we have both a pending bit AND a polled flag changing.
2. **Sweep WHICH bit of I_STAT to inject** — Ch262 used bit 0
   (DMAC completion). Try bits 1 / 3 (likely VBLANK_START /
   VBLANK_END candidates that BIOS's mask writes target — Ch259
   captured BIOS writing I_MASK = 0x0001 and 0x0008). Bit 3 in
   particular might trigger a different BIOS dispatch path.
3. **Multiple pulses** — instead of one go_i at 50 ms, retrigger
   the responder periodically (every ~50 ms). Each pulse latches
   the I_STAT bit; each is W1C'd. Does BIOS make progress when
   the interrupt is *recurrent* rather than one-shot?

Standing by for Codex's pick.
