ec82764bef
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>
129 lines
4.4 KiB
Systemverilog
129 lines
4.4 KiB
Systemverilog
// retroDE_ps2 — iop_fetch_stub
|
|
//
|
|
// Minimal IOP-side sequential fetcher. Mirrors ee_fetch_stub in shape and
|
|
// discipline — just the smallest honest primitive that produces visible
|
|
// IOP-side execution-flow traffic. Not a CPU. Explicitly NOT a BIOS boot
|
|
// stub: the default reset vector lives in IOP RAM, not in BIOS space.
|
|
//
|
|
// Contract refs:
|
|
// docs/contracts/iop.md (IOP CPU execution, required debug
|
|
// visibility: PC stream)
|
|
//
|
|
// Behavior:
|
|
// - On reset, PC = RESET_VECTOR (default 0x00000000, the low end of
|
|
// IOP RAM).
|
|
// - Each cycle while `enable` is high: issue a 32-bit read at PC,
|
|
// advance PC += 4. No decode, no branches, no exceptions, no FPU.
|
|
// - Responses return 1 cycle later via rd_valid/rd_data from the
|
|
// map. The issued address is latched (pc_d1) so trace lines pair
|
|
// address with data.
|
|
//
|
|
// Non-goals:
|
|
// - full decode
|
|
// - branch / exception / interrupt handling
|
|
// - real IOP R3000 pipeline timing
|
|
// - BIOS fetch (use a BIOS-pointing RESET_VECTOR param override if
|
|
// needed, but that's intentionally not the default)
|
|
//
|
|
// Trace payload schema (matches ee_fetch_stub structure under SUBSYS_IOP):
|
|
// IOP RESET arg0=reset_vector
|
|
// IOP IFETCH arg0=pc arg1=data arg2=resp_kind arg3=-
|
|
// resp_kind: 0=OK (only path in this scope)
|
|
|
|
`timescale 1ns/1ps
|
|
|
|
module iop_fetch_stub
|
|
import trace_pkg::*;
|
|
#(
|
|
parameter logic [31:0] RESET_VECTOR = 32'h0000_0000
|
|
) (
|
|
input logic clk,
|
|
input logic rst_n,
|
|
input logic enable,
|
|
|
|
// Map-facing fetch port
|
|
output logic rd_en,
|
|
output logic [31:0] rd_addr,
|
|
input logic [31:0] rd_data,
|
|
input logic 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
|
|
);
|
|
|
|
// ------------------------------------------------------------------
|
|
// PC and issued-address shadow (same pattern as ee_fetch_stub):
|
|
// pc is the address being issued THIS cycle (rd_addr)
|
|
// pc_d1 is the address whose response arrives THIS cycle on rd_valid
|
|
// pc_d1 only advances alongside pc when enable is high, so it stays
|
|
// aligned with the in-flight request.
|
|
// ------------------------------------------------------------------
|
|
|
|
logic [31:0] pc;
|
|
logic [31:0] pc_d1;
|
|
|
|
always_ff @(posedge clk) begin
|
|
if (!rst_n) begin
|
|
pc <= RESET_VECTOR;
|
|
pc_d1 <= RESET_VECTOR;
|
|
end else if (enable) begin
|
|
pc_d1 <= pc;
|
|
pc <= pc + 32'd4;
|
|
end
|
|
end
|
|
|
|
assign rd_en = enable;
|
|
assign rd_addr = pc;
|
|
|
|
// ------------------------------------------------------------------
|
|
// Trace
|
|
// - Single EV_RESET pulse at reset exit.
|
|
// - EV_IFETCH one cycle after each rd_valid response.
|
|
// ------------------------------------------------------------------
|
|
|
|
logic reset_emit_pending;
|
|
|
|
always_ff @(posedge clk) begin
|
|
if (!rst_n) begin
|
|
ev_valid <= 1'b0;
|
|
ev_subsys <= SUBSYS_IOP;
|
|
ev_event <= EV_RESET;
|
|
ev_arg0 <= 64'd0;
|
|
ev_arg1 <= 64'd0;
|
|
ev_arg2 <= 64'd0;
|
|
ev_arg3 <= 64'd0;
|
|
ev_flags <= 32'd0;
|
|
reset_emit_pending <= 1'b1;
|
|
end else if (reset_emit_pending) begin
|
|
ev_valid <= 1'b1;
|
|
ev_subsys <= SUBSYS_IOP;
|
|
ev_event <= EV_RESET;
|
|
ev_arg0 <= {32'd0, RESET_VECTOR};
|
|
ev_arg1 <= 64'd0;
|
|
ev_arg2 <= 64'd0;
|
|
ev_arg3 <= 64'd0;
|
|
ev_flags <= 32'd0;
|
|
reset_emit_pending <= 1'b0;
|
|
end else if (rd_valid) begin
|
|
ev_valid <= 1'b1;
|
|
ev_subsys <= SUBSYS_IOP;
|
|
ev_event <= EV_IFETCH;
|
|
ev_arg0 <= {32'd0, pc_d1};
|
|
ev_arg1 <= {32'd0, rd_data};
|
|
ev_arg2 <= 64'd0;
|
|
ev_arg3 <= 64'd0;
|
|
ev_flags <= 32'd0;
|
|
end else begin
|
|
ev_valid <= 1'b0;
|
|
end
|
|
end
|
|
|
|
endmodule : iop_fetch_stub
|