Snapshot: fog implementation + fidelity tooling baseline (pre bilinear-clamp fix)

Per-vertex GS fog end-to-end (gs_stub emit incl. persp_emit5, gs_prim_list_feeder
XYZ2->XYZF2 on PRIM.FGE, gs_make_sh3_scheduler_fixture.py F/FGE packing), new fog
TBs, fidelity attribution tooling. Functional baseline before removing the dead
bilinear lerp8 clamps (Codex: 161-node comb loop -> -0.042ns setup fail).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-20 19:56:46 -04:00
parent ec82764bef
commit ba74bbd5aa
476 changed files with 696247 additions and 130119 deletions
+84 -9
View File
@@ -195,12 +195,13 @@ module top_psmct32_raster_demo_bram
// Default 0 generate-guards all perspective logic out (zero cost); only the
// GS_PERSP_DEMO board profile sets it 1.
parameter bit PERSPECTIVE_CORRECT = 1'b0,
parameter bit SUBPIXEL_XY = 1'b0,
parameter int PERSP_RECIP_IDX_BITS = 8, // Ch351 — perspective reciprocal LUT width (far-W -> 11)
parameter int GRAD_DIV_CYCLES = 1, // Ch352 — triangle-setup divide settle cycles (board fits -> 4)
parameter bit GRAD_SEQ_DIVIDER = 1'b0, // Ch352 — sequential gradient divider (board fits -> 1)
// Ch344 — TEXTURED + source-over ALPHA SPRITE path (forwarded to gs_stub). Default 0 -> byte-identical.
parameter bit SPRITE_TEX_ALPHA = 1'b0,
parameter bit SPRITE_TEX_ALPHA_CLUT = 1'b0, // Ch347 — admit PSMT8 (CLUT) textures into the alpha-sprite path
parameter bit SPRITE_TEX_ALPHA_CLUT = 1'b0, // Ch408 — admit PSMT8/PSMT4 CLUT textures into alpha sprites
parameter bit CLUT_CSM1_ENABLE = 1'b0, // Ch350 — CSM1 16x16 CT32 grid CLUT load (SH3 indexed env path)
// Ch302 — COMBINED textured+alpha+depth probe (forwarded to gs_stub). When 1,
// a TME+ABE+ZTE triangle runs the multi-beat per-pixel FSM (Zread->Ztest->
@@ -237,6 +238,11 @@ module top_psmct32_raster_demo_bram
// dead logic, byte-identical for every existing profile.
parameter bit FEEDER_ENABLE = 1'b0,
parameter int FEEDER_STG_WORDS = 256,
// Ch353 — auto-start the FIRST feeder render at C_SETUP (default, byte-identical). Set 0 ONLY for
// the GS_SH3_LPDDR_FB profile: the disarmed boot render would otherwise leave a pending EOF that
// falsely asserts frame_drained the instant the host later arms the writer. With AUTOSTART=0,
// C_SETUP transitions straight to C_READY (no render) and every render waits for an explicit GO.
parameter bit FEEDER_AUTOSTART = 1'b1,
// Ch315 — primitive FIFO / per-tile bin depth (capacity). Power-of-2, default
// 4 = byte-identical. GS_TILE_CAP_DEMO sets 8 to scale capacity past the old 4.
parameter int TILE_FIFO_DEPTH = 4,
@@ -366,7 +372,16 @@ module top_psmct32_raster_demo_bram
output logic [31:0] flush_addr_o, // linear FB byte address
output logic [15:0] flush_pix16_o,
output logic [31:0] flush_color32_o, // Ch323 — full 32-bit flushed color (for spill round-trip capture)
output logic [3:0] flush_be_o, // FRAME.FBMSK-compressed byte enables
output logic [5:0] flush_psm_o,
output logic [11:0] flush_x_o, // Ch357 — fragment x/y/z for the external LPDDR-Z ROP (perspective path)
output logic [11:0] flush_y_o,
output logic [31:0] flush_z_o,
output logic flush_abe_o,
output logic [16:0] flush_alpha_o,
output logic flush_ztest_o,
output logic [1:0] flush_ztst_o,
output logic flush_zmsk_o,
// Ch323 — tile Z-FLUSH stream (TILE_SPILL_ENABLE; the de25 routes it to an LPDDR Z-backing
// writer). z_flush_addr_o is Z-backing-relative (pixel_index*4, 32-bit Z). Inert/0 unless
// spilling; unused (left open) by every existing consumer.
@@ -416,7 +431,15 @@ module top_psmct32_raster_demo_bram
input logic feeder_go_i, // retrigger pulse (honoured only in C_READY)
output logic feeder_ready_o, // control FSM is in C_READY (a new list may start)
output logic [15:0] feeder_records_o, // primitives emitted by the current list
output logic [31:0] feeder_waits_o // cycles the feeder paused under fifo_full
output logic [31:0] feeder_waits_o, // cycles the feeder paused under fifo_full
// Ch367 -- runtime palette residency. The design-clock staging copier
// owns this writer while busy; the legacy TEX0/VRAM loader remains the
// sole writer at every other time.
input logic runtime_clut_wr_en_i,
input logic [7:0] runtime_clut_wr_idx_i,
input logic [31:0] runtime_clut_wr_data_i,
input logic runtime_clut_busy_i
);
localparam int RAM_ADDR_W = $clog2(RAM_SIZE_BYTES);
@@ -805,7 +828,12 @@ module top_psmct32_raster_demo_bram
fdr_start <= 1'b0;
unique case (cst)
C_SETUP: if (dma_done_seen && !xfer_busy) begin // bootlet setup + TRX/IMAGE done
fdr_start <= 1'b1; grid_ran <= 1'b0; cst <= C_RUN; end
if (FEEDER_AUTOSTART) begin
fdr_start <= 1'b1; grid_ran <= 1'b0; cst <= C_RUN; // auto boot render
end else begin
grid_ran <= 1'b0; cst <= C_READY; // Ch353: no boot render — await explicit GO
end
end
C_RUN: begin if (gs_scene_busy) grid_ran <= 1'b1;
if (fdr_done) cst <= C_DRAIN; end
// Ch337 — gate on gs_scene_busy (NOT gs_raster_active): a >FIFO_DEPTH scene
@@ -883,15 +911,39 @@ module top_psmct32_raster_demo_bram
logic raster_pixel_emit;
logic [63:0] raster_pixel_color_q;
logic [31:0] raster_pixel_fb_addr_q;
logic [11:0] raster_pixel_x_q, raster_pixel_y_q;
logic [31:0] raster_pixel_z_q;
logic [3:0] raster_pixel_be_q;
logic [31:0] raster_pixel_mask_q;
logic [63:0] gs_frame_1_q;
logic [5:0] raster_pixel_psm_q;
logic raster_pixel_abe_q;
logic [16:0] raster_pixel_alpha_q;
logic raster_pixel_ztest_q;
logic [1:0] raster_pixel_ztst_q;
logic raster_pixel_zmsk_q;
// Ch318 — expose the flush stream for an external LPDDR AXI writer (de25 top).
assign flush_emit_o = raster_pixel_emit;
assign flush_addr_o = raster_pixel_fb_addr_q;
assign flush_pix16_o = raster_pixel_color_q[15:0];
assign flush_color32_o = raster_pixel_color_q[31:0]; // Ch323 — full color for spill capture
// The production LPDDR ROP supports the byte-granular FBMSK subset used
// by the captured SH3 frame. A set mask byte preserves that destination
// byte; partial-bit mask bytes are rejected by fixture generation.
wire [3:0] frame_byte_be = {gs_frame_1_q[63:56] == 8'h00,
gs_frame_1_q[55:48] == 8'h00,
gs_frame_1_q[47:40] == 8'h00,
gs_frame_1_q[39:32] == 8'h00};
assign flush_be_o = raster_pixel_be_q & frame_byte_be;
assign flush_x_o = raster_pixel_x_q; // Ch357 — fragment coords + Z for the LPDDR-Z ROP
assign flush_y_o = raster_pixel_y_q;
assign flush_z_o = raster_pixel_z_q;
assign flush_abe_o = raster_pixel_abe_q;
assign flush_alpha_o = raster_pixel_alpha_q;
assign flush_ztest_o = raster_pixel_ztest_q;
assign flush_ztst_o = raster_pixel_ztst_q;
assign flush_zmsk_o = raster_pixel_zmsk_q;
assign flush_psm_o = raster_pixel_psm_q;
// Ch295 — texture-sampler read port out of gs_stub. Wired to
@@ -921,6 +973,11 @@ module top_psmct32_raster_demo_bram
// that consumes it as clut_load_busy to hold the FIFO pop while the
// VRAM->CLUT load runs). Driven by clut_loader_stub.load_busy below.
logic clut_ld_busy;
// Existing unit tops leave the new runtime ports open. Treat only a
// driven-one as active so those legacy fixtures stay byte-identical.
wire runtime_clut_busy = (runtime_clut_busy_i === 1'b1);
wire runtime_clut_wr_en = (runtime_clut_wr_en_i === 1'b1);
wire clut_busy = clut_ld_busy | runtime_clut_busy;
// Ch296 — gs_stub TEX0_1 decode taps that feed clut_loader_stub: the
// 1-cycle commit pulse + CBP/CPSM/CSM/CSA/CLD that decide when (and
@@ -960,6 +1017,7 @@ module top_psmct32_raster_demo_bram
.FB_RD_REGISTERED (1'b1),
.Z_RD_REGISTERED (1'b1),
.PERSPECTIVE_CORRECT(PERSPECTIVE_CORRECT), // Ch301 — forwarded board param (default 0)
.SUBPIXEL_XY (SUBPIXEL_XY), // Ch416 — native GS 12.4 coverage (default 0)
.PERSP_RECIP_IDX_BITS(PERSP_RECIP_IDX_BITS), // Ch351 — perspective reciprocal LUT width (far-W -> 11)
.GRAD_DIV_CYCLES(GRAD_DIV_CYCLES), // Ch352 — triangle-setup divide settle cycles (board -> 4)
.GRAD_SEQ_DIVIDER(GRAD_SEQ_DIVIDER), // Ch352 — sequential gradient divider (board -> 1)
@@ -997,7 +1055,7 @@ module top_psmct32_raster_demo_bram
.pmode_q(pmode_q), .dispfb1_q(dispfb1_q), .display1_q(display1_q),
.prim_q(), .rgbaq_q(),
.xyz2_q(), .xyzf2_q(),
.frame_1_q(), .zbuf_1_q(),
.frame_1_q(gs_frame_1_q), .zbuf_1_q(),
.tex0_1_q(), .tex0_1_cbp_q(gs_tex0_cbp), .tex0_1_cpsm_q(gs_tex0_cpsm),
.tex0_1_csm_q(gs_tex0_csm), .tex0_1_csa_q(gs_tex0_csa),
.tex0_1_cld_q(gs_tex0_cld), .tex0_1_wr_q(gs_tex0_wr),
@@ -1018,12 +1076,18 @@ module top_psmct32_raster_demo_bram
.pixel_fbp_q(), .pixel_fbw_q(), .pixel_psm_q(), .pixel_fb_addr_q(),
.raster_pixel_emit(raster_pixel_emit),
.raster_pixel_emit_count(),
.raster_pixel_x_q(), .raster_pixel_y_q(),
.raster_pixel_x_q(raster_pixel_x_q), .raster_pixel_y_q(raster_pixel_y_q),
.raster_pixel_color_q(raster_pixel_color_q),
.raster_pixel_fb_addr_q(raster_pixel_fb_addr_q),
.raster_pixel_z_q(raster_pixel_z_q),
.raster_pixel_be_q(raster_pixel_be_q),
.raster_pixel_mask_q(raster_pixel_mask_q),
.raster_pixel_psm_q(raster_pixel_psm_q),
.raster_pixel_abe_q(raster_pixel_abe_q),
.raster_pixel_alpha_q(raster_pixel_alpha_q),
.raster_pixel_ztest_q(raster_pixel_ztest_q),
.raster_pixel_ztst_q(raster_pixel_ztst_q),
.raster_pixel_zmsk_q(raster_pixel_zmsk_q),
.z_flush_emit_o(z_flush_emit_o), // Ch323 — tile Z-flush stream (de25 Z-writer)
.z_flush_addr_o(z_flush_addr_o),
.z_flush_data_o(z_flush_data_o),
@@ -1047,7 +1111,7 @@ module top_psmct32_raster_demo_bram
.tex_rd_data(gs_tex_rd_data),
.clut_rd_idx (gs_clut_rd_idx),
.clut_rd_data(gs_clut_rd_data),
.clut_load_busy(clut_ld_busy), // hold pop while VRAM->CLUT load runs
.clut_load_busy(clut_busy), // hold pop while either CLUT writer runs
.fb_rd_en (gs_fb_rd_en),
.fb_rd_addr(gs_fb_rd_addr),
.fb_rd_data(gs_fb_rd_data),
@@ -1422,11 +1486,22 @@ module top_psmct32_raster_demo_bram
end
end
wire clut_wr_en = runtime_clut_wr_en ? 1'b1 : clut_ld_wr_en_q;
wire [7:0] clut_wr_idx = runtime_clut_wr_en ? runtime_clut_wr_idx_i : clut_ld_wr_idx_q;
wire [31:0] clut_wr_data = runtime_clut_wr_en ? runtime_clut_wr_data_i : clut_ld_wr_data_c;
// synthesis translate_off
always_ff @(posedge clk) begin
if (rst_n && runtime_clut_wr_en && clut_ld_wr_en_q)
$error("runtime CLUT copy collided with TEX0 CLUT loader");
end
// synthesis translate_on
clut_stub u_clut (
.clk(clk), .rst_n(rst_n),
.write_en (clut_ld_wr_en_q),
.write_idx(clut_ld_wr_idx_q),
.write_data(clut_ld_wr_data_c), // LIVE registered-read data
.write_en (clut_wr_en),
.write_idx(clut_wr_idx),
.write_data(clut_wr_data),
// pcrtc scanout read port — unused in this textured-board top
// (PCRTC clut_enable=0). Tie its index to 0.
.read_idx (8'd0),