# Ch305 closeout — DSUBU; THIRD inflection (+1.46M retires); EE-core reality checkpoint queued

**Status:** Closed. **Verdict from re-running qbert.elf:**
`elf_timeout_with_hot_pc (1489428 retires, hot_pc=0x00106154)` —
qbert advanced 29,417 → **1,489,428 retires (+1,460,011)**, a
**third inflection**, then hit a new steady-state wait loop in a
different code region.

## What landed — `rtl/ee/ee_core_stub.sv` (4 edits)

R5900 DSUBU (SPECIAL funct 0x2F), the 64-bit-subtract sibling of
Ch272's DADDU. Modelled as SUBU on the low 32 bits, no overflow
trap:

1. `localparam FUNC_DSUBU = 6'h2F`.
2. `is_dsubu = is_special && (func == FUNC_DSUBU)`.
3. Added `is_dsubu` to `is_rtype_alu` (which auto-excludes it from
   `is_nop_class` via the SPECIAL clause — no separate nop_class
   edit needed).
4. Extended the SUBU writeback arm: `is_sub || is_subu || is_dsubu`
   → `rs_val - rt_val`.

## Focused TB — `tb_ee_core_dsubu.sv`

Three cases, all PASS:
1. Normal: `dsubu $t0, $a0, $a1` (8 - 3 = 5).
2. **Exact qbert encoding asserted** `0x0062102F` = `dsubu $v0,
   $v1, $v0` (10 - 4 = 6).
3. Underflow: `dsubu $t3, $0, $a3` (0 - 1 = 0xFFFFFFFF, no trap).

Result: `$t0=5 $v0=6 $t3=0xFFFFFFFF errors=0 PASS`.

## qbert progression — third inflection

| Chapter | retire_count | verdict |
|---------|--------------|---------|
| Post-Ch304 (0x6B) | 29,417 | opcode trap (DSUBU) |
| **Post-Ch305 (DSUBU)** | **1,489,428** | **timeout_with_hot_pc** |

+1.46M retires. The third time a single opcode/syscall addition
has unlocked a >1M-retire stretch (after Ch293's syscall 0x7A and
Ch297's syscall 0x77). DSUBU was the last blocker in a hot
numeric-init path; clearing it let qbert run deep into a new
region (hot_pc 0x00106154 — note 0x00106xxx, *lower* than all
prior blockers, so a different/earlier-linked function).

The new wait loop at 0x00106154 is a Ch307+ autopsy candidate —
**deferred** in favor of the Ch306 reality checkpoint per the
strategic decision below.

## Strategic pivot — Ch306 = EE core reality checkpoint

Codex and the project owner have (correctly) called the question:
**the qbert track is building a behavioral compatibility oracle,
not a synthesizable R5900.** Before sinking more chapters into
either track, Ch306 is a recon/design checkpoint that splits the
roadmap into two explicit tracks:

- **Track A — EE Behavioral Oracle** (`ee_core_stub`): continue
  qbert only to *discover* required instructions/syscalls/MMIO.
  Output = a living compliance checklist.
- **Track B — Synthesizable EE Core**: a separate, deliberate RTL
  plan. Must NOT grow accidentally from the stub.

Ch306's job (a workflow): inventory every `ee_core_stub` feature
and classify each as:
1. **architectural instruction** → graduates to real RTL,
2. **HLE syscall behavior** → BIOS/kernel, lives in ROM or an HLE
   companion, NOT the CPU,
3. **TB-only / qbert-specific hack** (gate pokes, $a0-aware
   returns, Ch215 shim) → pure scaffolding for missing async
   hardware, NEVER graduates,
4. **unsynthesizable / sim-only** (trace ports, hierarchical
   peeks) → must be stripped or gated for synthesis.

Plus: a go/no-go on whether a simple multicycle/interpreter-style
R5900 subset fits the Agilex 5 and passes the existing ~178 TBs.
The qbert-focused TBs become the compliance suite for Track B.

**The validation answer** (the concern that triggered this
pivot): we *can* validate a real R5900 RTL — the 178 TBs +
qbert boot path already ARE the harness. We've been writing a
spec-by-execution for 35 chapters; Ch306 makes it explicit and
decides the graduation path before, not after, building Track B.

## Files changed

- `rtl/ee/ee_core_stub.sv` — 4 DSUBU edits.
- `sim/tb/integration/tb_ee_core_dsubu.sv` — new focused TB.
- `sim/Makefile` — target + both regression lists.

## Regression

**178/178 PASS** — clean full regression covering both Ch304
(syscall 0x6B) and Ch305 (DSUBU), with tb_ee_core_dsubu in the
suite. (Was 177 in Ch304; +1 for the new DSUBU TB.)
