Files
retroDE_ps2/docs/stub_module_plan.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

11 KiB

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:

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
  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.