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>
This commit is contained in:
2026-06-29 20:10:50 -04:00
commit ec82764bef
2462 changed files with 2174303 additions and 0 deletions
+433
View File
@@ -0,0 +1,433 @@
# Stub Module Plan
This document translates the locked Phase 0 decisions and current subsystem
contracts into an implementation-oriented stub plan.
Goal:
- start real code with the smallest set of modules that produce meaningful
signal,
- keep each stub aligned with a contract,
- make Milestone A and Milestone B independently achievable,
- avoid building "temporary" code that has no upgrade path.
This is the handoff point from planning docs to first RTL.
## Planning anchors
This plan is shaped by the following locked decisions:
- posture: `staged subset on current hardware`
- BIOS policy: `real BIOS plus narrow debug stubs`
- golden references: `DobieStation` and `PCSX2` with role separation
- first milestone: split into platform/video proof and EE/BIOS trace proof
- trace format: common text envelope plus subsystem-specific payloads
## First implementation rule
Every stub in this plan must have:
- a matching contract under `docs/contracts/`,
- an explicit success condition,
- a trace output,
- a stated replacement path.
If a stub participates in BIOS behavior, it must also be tracked with:
- owner,
- scope boundary,
- removal condition.
## Immediate deliverables
The first RTL wave should target these deliverables:
1. `Milestone A`: visible GS-stub test pattern through the platform video path.
2. `Milestone B`: EE BIOS fetch and early trace agreement against DobieStation.
3. A minimal trace pipeline that both RTL stubs and golden-reference tooling can
emit.
## Initial trace format choice
Decision `0000` deliberately left room for either key/value text or stable
columns. For the first stub wave, choose `stable columns`.
Initial common envelope:
```text
cycle subsystem event arg0 arg1 arg2 arg3 flags
```
Field intent:
- `cycle`: simulation cycle or monotonic step count
- `subsystem`: short id such as `EE`, `MEM`, `GS`, `SIF`, `INTC`
- `event`: stable event code such as `IFETCH`, `READ`, `WRITE`, `IRQ`, `MODE`
- `arg0..arg3`: subsystem-defined fields documented per stub
- `flags`: compact auxiliary bits or `-` when unused
Rules:
- whitespace-delimited ASCII text
- one event per line
- comment/header lines start with `#`
- each trace file starts with a header describing the subsystem schema
This gives the project a simple diffable format now without closing the door on
future binary logging.
## Wave 1: foundation stubs
These are the first modules worth implementing.
### 1. `rtl/debug/trace_sink_stub.sv`
Purpose:
- centralize text-trace event formatting at the testbench boundary,
- avoid each stub inventing its own ad-hoc logging path.
Owns:
- accepting normalized event records from stubs,
- emitting them in the shared column format for simulation.
Success condition:
- testbench can capture deterministic trace lines from multiple subsystems.
Replacement path:
- grows into the normal simulation trace path; not expected to be thrown away.
### 2. `rtl/platform/platform_video_stub.sv`
Purpose:
- create the smallest retroDE-facing video path needed for Milestone A.
Owns:
- accepting a simple pixel or test-pattern source from the GS stub,
- adapting it into the platform-facing display signals used by the top level.
Success condition:
- stable visible output on the chosen platform path in simulation, and later on
hardware.
Replacement path:
- remains as the platform adaptation layer while the upstream source changes
from GS stub output to fuller GS/PCRTC output.
### 3. `rtl/gif_gs/gs_stub.sv`
Purpose:
- provide Milestone A without waiting for DMAC, GIF, or full GS behavior.
Minimum scope:
- accept direct privileged register writes from a local test harness or top-level
stub control path,
- implement `BGCOLOR` and the minimum mode/state needed to drive a visible
pattern,
- emit trace events on display-mode and color changes.
Success condition:
- a fixed or controllable color/test pattern appears through the platform video
path and produces repeatable traces.
Replacement path:
- keep the register shell and extend inward toward fuller GS behavior.
### 4. `rtl/memory/bios_rom_stub.sv`
Purpose:
- give the EE stub a realistic instruction source for Milestone B.
Minimum scope:
- expose a BIOS window at the agreed address range,
- back reads with either a user-supplied image path or a simulation fixture,
- emit trace lines for fetch-visible ROM reads.
Success condition:
- instruction fetches from BIOS space return deterministic data.
Replacement path:
- should survive as the BIOS storage/mapping implementation even after the rest
of the memory system becomes more complete.
### 5. `rtl/memory/ee_memory_map_stub.sv`
Purpose:
- provide only enough EE-visible address decoding for early BIOS fetch progress.
Minimum scope:
- decode BIOS ROM window,
- decode unmapped space into deterministic fault/idle responses,
- optionally reserve placeholders for RAM and EE I/O windows,
- emit `READ`, `WRITE`, and `UNMAPPED` traces.
Success condition:
- the EE stub can request BIOS fetches and get predictable answers.
Replacement path:
- grows into the broader memory-map and arbitration layer defined by
`memory.md`.
### 6. `rtl/intc/intc_stub.sv`
Purpose:
- keep interrupt ownership explicit from the start,
- support early directed tests even before real interrupt sources exist.
Minimum scope:
- register-visible status/mask shell,
- synthetic interrupt injection path for tests,
- trace on assert/mask/clear.
Success condition:
- directed tests can prove the EE-side interrupt-visible shell behaves
deterministically.
Replacement path:
- extend source inputs and timing behavior without changing ownership.
### 7. `rtl/ee/ee_fetch_stub.sv`
Purpose:
- achieve Milestone B without a full R5900 implementation.
Minimum scope:
- reset into BIOS fetch address space,
- generate sequential instruction fetch requests,
- maintain a minimal PC,
- log fetch trace lines in the common envelope.
Non-goals for this wave:
- full decode,
- exceptions beyond deterministic fault handling,
- FPU/MMI behavior,
- instruction retirement fidelity.
Success condition:
- trace shows stable BIOS fetch progression for a chosen window of cycles.
Replacement path:
- replace with or wrap a fuller EE core while preserving the memory-facing and
trace-facing interfaces where practical.
## Wave 2: bridging stubs
These are the next modules after the foundation wave.
### 8. `rtl/dmac/dmac_reg_stub.sv`
Purpose:
- establish EE DMAC register ownership and traces before real transfers exist.
Minimum scope:
- register file for selected channels,
- start/stop visibility,
- channel-state traces,
- no real data movement yet.
Success condition:
- directed tests can program DMAC-visible state and see deterministic events.
### 9. `rtl/gif_gs/gif_path_stub.sv`
Purpose:
- bridge the eventual gap between DMAC channel 2 and the GS stub.
Minimum scope:
- accept a minimal packet stream,
- log GIF tags and path source,
- optionally forward only a very narrow subset into the GS stub.
Success condition:
- a synthetic packet stream can be observed and, if enabled, drive a GS-stub
state change.
### 10. `rtl/sif/sif_mailbox_stub.sv`
Purpose:
- establish EE<->IOP coordination points before full dual-CPU bring-up.
Minimum scope:
- mailbox/flag shell,
- deterministic reads/writes,
- trace on transitions.
Success condition:
- SIF directed tests can prove basic flag and mailbox visibility.
### 11. `rtl/iop/iop_boot_stub.sv`
Purpose:
- create a place for BIOS-side IOP boot sequencing behavior without forcing a
full IOP implementation immediately.
Minimum scope:
- explicit stub-only progress markers,
- optional fake acknowledgement path if needed for a narrowly-scoped BIOS step,
- trace lines that make stub behavior unmistakable.
Guardrail:
- this stub must be tracked under the BIOS-stub policy with owner and removal
condition.
Success condition:
- if used, it unlocks one clearly named early BIOS milestone and nothing more.
### 12. `rtl/peripherals/sio2_input_stub.sv`
Purpose:
- start the controller-facing story with a deterministic placeholder.
Minimum scope:
- device-present shell,
- synthetic event injection for tests,
- no attempt at full SIO2 transaction fidelity yet.
Success condition:
- testbench can prove the platform/input handoff path exists.
## Wave 3: first upgrade targets
These are not the first stubs to write, but they are the first likely
promotions from stub to semi-real implementation.
- `ee_fetch_stub` -> fuller EE front-end or wrapped EE core
- `ee_memory_map_stub` -> RAM plus wider I/O decode
- `gs_stub` -> privileged-register shell plus simple draw/VRAM path
- `dmac_reg_stub` -> one real functional channel, likely GIF-facing first
- `sif_mailbox_stub` -> broader SIF-visible coordination
## Recommended implementation order
1. `trace_sink_stub`
2. `bios_rom_stub`
3. `ee_memory_map_stub`
4. `ee_fetch_stub`
5. `platform_video_stub`
6. `gs_stub`
7. `intc_stub`
8. `dmac_reg_stub`
9. `gif_path_stub`
10. `sif_mailbox_stub`
11. `iop_boot_stub` only if a specific milestone truly needs it
12. `sio2_input_stub`
Why this order:
- it gets Milestone B moving first with the smallest dependency stack,
- it gets Milestone A moving in parallel without waiting for DMAC/GIF,
- it avoids premature IOP complexity,
- it keeps BIOS-policy-sensitive stubs later and narrower.
## Initial testbench plan
The first stub wave should be paired with these testbenches:
### `sim/tb/ee/tb_ee_fetch_stub.sv`
Checks:
- reset PC,
- BIOS-window fetches,
- unmapped access handling,
- trace line emission.
### `sim/tb/gif_gs/tb_gs_stub.sv`
Checks:
- direct register writes to `BGCOLOR`,
- stable output state,
- trace on mode/color changes.
### `sim/tb/intc/tb_intc_stub.sv`
Checks:
- mask/set/clear behavior,
- synthetic interrupt injection,
- trace on state transitions.
## Initial trace schemas
The first wave should document these event schemas in the testbench headers or
adjacent notes:
- `EE IFETCH`: `arg0=pc arg1=data arg2=resp_kind arg3=-`
- `MEM READ`: `arg0=addr arg1=data arg2=master arg3=region`
- `MEM UNMAPPED`: `arg0=addr arg1=master arg2=access_kind arg3=-`
- `GS MODE`: `arg0=mode arg1=value arg2=- arg3=-`
- `GS BGCOLOR`: `arg0=r arg1=g arg2=b arg3=-`
- `INTC IRQ`: `arg0=source arg1=masked arg2=pending arg3=ack`
## Stub ownership map
Suggested ownership split for early implementation:
- `EE/MEM/INTC/trace` stubs: one coherent bring-up lane
- `GS/platform-video` stubs: one coherent bring-up lane
- `DMAC/GIF/SIF/IOP-peripheral` stubs: follow once the first two lanes are
stable
This is meant to support parallel work without overlapping write ownership.
## Guardrails
- No stub should pretend to be real hardware silently; every stub-only path
should trace clearly.
- No BIOS-affecting stub should land without recorded owner and removal
condition.
- No subsystem should invent a private trace format.
- No Wave 2 stub should block Milestone A or Milestone B if Wave 1 can already
produce useful signal.
## Exit criteria for stub-plan acceptance
- Claude can implement Wave 1 without reopening core architecture questions.
- Each Wave 1 module has a clear contract owner and success condition.
- Milestone A and Milestone B are both directly represented in the plan.
- The trace format is concrete enough for the first testbenches.