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
+142
View File
@@ -0,0 +1,142 @@
// retroDE_ps2 — ee_biu_mmio_stub
//
// Narrow latched-register-file stub for the EE Bus Interface Unit /
// cache-control window at virtual `0xFFFE_0000 - 0xFFFE_0FFF`
// (physical `0x1FFE_0000 - 0x1FFE_0FFF` after kseg1-stripping).
// Architecturally this is the R5900's privileged BIU/control
// register space — the same place the BIOS writes CACHE-control
// and BIU-config values during boot.
//
// Chapter 9: chapter 8 closed the 0x1F80_xxxx hole. The first-
// unmapped observer in tb_ee_core_bios_smoke then showed the next
// unmapped event was a WRITE at 0xFFFE_0130 (pc=0xBFC0_21BC,
// cycle 808). Multiple more writes to that same offset fire later
// with values 0xCC4, 0xCC0, 0x1E988, 0xC04, 0x3202_000F —
// classic cache/BIU config dance. Without a stub, these writes
// land as UNMAPPED events; the first one reads back to this stub
// would return 0xDEADBEEF and re-poison the pointer chain chapter
// 8 just cleaned up.
//
// Codex's call for chapter 9: give this its own dedicated stub
// with its own region tag, NOT a broad "everything else" fallback.
// Keep architecturally distinct surfaces distinct. If the BIOS
// later touches 0x1FA0_0000 (next unmapped in the observer), that
// will be its own chapter, not folded in here.
//
// Semantics (same shape as ee_bootstrap_mmio_stub):
// - 4 KiB window = 1024 × 32-bit latched registers, zero-init.
// - Writes latch per-byte: for each `wr_be[i]`, byte[i] of the
// addressed register updates; untouched lanes preserve their
// prior value. Makes SB/SH through the window safe.
// - Reads return currently-latched value, one-cycle latency.
// - No side effects. BIOS read-modify-write sequences stay
// self-consistent.
//
// Size cost: 1024 × 32 bits = 4 KiB sim memory. Negligible.
//
// Trace: per-access event on SUBSYS_MEM with region tag
// `REGION_EE_BIU = 10` (distinct from REGION_EE_MISC_MMIO=9 so
// post-run analysis can separate the two windows).
`timescale 1ns/1ps
module ee_biu_mmio_stub
import trace_pkg::*;
(
input logic clk,
input logic rst_n,
// Write port — 12-bit offset within the 4 KiB window
input logic reg_wr_en,
input logic [11:0] reg_wr_addr,
input logic [31:0] reg_wr_data,
input logic [3:0] reg_wr_be,
// Read port — 1-cycle latency
input logic reg_rd_en,
input logic [11:0] reg_rd_addr,
output logic [31:0] reg_rd_data,
output logic reg_rd_valid,
// Trace
output logic ev_valid,
output subsys_e ev_subsys,
output event_e ev_event,
output logic [63:0] ev_arg0,
output logic [63:0] ev_arg1,
output logic [63:0] ev_arg2,
output logic [63:0] ev_arg3,
output logic [31:0] ev_flags
);
localparam int WORDS = 1024; // 4 KiB / 4
localparam logic [63:0] REGION_EE_BIU = 64'd10;
logic [31:0] regs [0:WORDS-1];
initial begin
for (int i = 0; i < WORDS; i++) regs[i] = 32'd0;
end
logic [9:0] wr_idx;
logic [9:0] rd_idx;
assign wr_idx = reg_wr_addr[11:2];
assign rd_idx = reg_rd_addr[11:2];
// Per-byte write latch
always_ff @(posedge clk) begin
if (rst_n && reg_wr_en) begin
if (reg_wr_be[0]) regs[wr_idx][ 7: 0] <= reg_wr_data[ 7: 0];
if (reg_wr_be[1]) regs[wr_idx][15: 8] <= reg_wr_data[15: 8];
if (reg_wr_be[2]) regs[wr_idx][23:16] <= reg_wr_data[23:16];
if (reg_wr_be[3]) regs[wr_idx][31:24] <= reg_wr_data[31:24];
end
end
// Read — 1-cycle latency
always_ff @(posedge clk) begin
if (!rst_n) begin
reg_rd_data <= 32'd0;
reg_rd_valid <= 1'b0;
end else begin
reg_rd_valid <= reg_rd_en;
if (reg_rd_en) reg_rd_data <= regs[rd_idx];
end
end
// Trace — write wins same-cycle collision (defensive; map enforces
// mutual exclusion)
always_ff @(posedge clk) begin
if (!rst_n) begin
ev_valid <= 1'b0;
ev_subsys <= SUBSYS_MEM;
ev_event <= EV_WRITE;
ev_arg0 <= 64'd0;
ev_arg1 <= 64'd0;
ev_arg2 <= 64'd0;
ev_arg3 <= 64'd0;
ev_flags <= 32'd0;
end else if (reg_wr_en) begin
ev_valid <= 1'b1;
ev_subsys <= SUBSYS_MEM;
ev_event <= EV_WRITE;
ev_arg0 <= {52'd0, reg_wr_addr};
ev_arg1 <= {32'd0, reg_wr_data};
ev_arg2 <= {60'd0, reg_wr_be};
ev_arg3 <= REGION_EE_BIU;
ev_flags <= 32'h0000_0001;
end else if (reg_rd_en) begin
ev_valid <= 1'b1;
ev_subsys <= SUBSYS_MEM;
ev_event <= EV_READ;
ev_arg0 <= {52'd0, reg_rd_addr};
ev_arg1 <= {32'd0, regs[rd_idx]};
ev_arg2 <= 64'd0;
ev_arg3 <= REGION_EE_BIU;
ev_flags <= 32'd0;
end else begin
ev_valid <= 1'b0;
end
end
endmodule : ee_biu_mmio_stub