// retroDE_ps2 — tb_gs_fog_disabled // // Proves the FOG_ENABLE=0 compile gate: with gs_stub #(.FOG_ENABLE(1'b0)), // a PRIM.FGE=1 primitive carrying real per-vertex fog + a nonzero FOGCOL emits // the RAW (unfogged) post-texture/Gouraud color. Because FOG_ENABLE is a param // constant, `(FOG_ENABLE && ras_fge)` folds to 0 and each fog mux selects the // raw color — the exact pre-fog datapath the synthesizer keeps (fog cone, // including s2_fog_f, pruned). Functional equivalence to the raw color here is // the observable proof that the fold target is the pre-fog path. `timescale 1ns/1ps module tb_gs_fog_disabled; logic clk; logic rst_n; initial clk = 1'b0; always #5 clk = ~clk; logic gif_reg_wr_en; logic [7:0] gif_reg_num; logic [63:0] gif_reg_data; logic [7:0] bg_r, bg_g, bg_b; logic [63:0] prim_q, rgbaq_q, xyz2_q, xyzf2_q, frame_1_q, zbuf_1_q; logic prim_complete; logic [31:0] prim_complete_count; logic [63:0] prim_v0_q, prim_v1_q, prim_v2_q, prim_color_q; logic [63:0] prim_color_v0_q, prim_color_v1_q, prim_color_v2_q; trace_pkg::vertex_t prim_v0_decoded_q, prim_v1_decoded_q, prim_v2_decoded_q; trace_pkg::color_t prim_v0_color_decoded_q, prim_v1_color_decoded_q, prim_v2_color_decoded_q; logic pixel_emit; logic [31:0] pixel_emit_count; logic [11:0] pixel_x_q, pixel_y_q; logic [63:0] pixel_color_q; logic [8:0] pixel_fbp_q; logic [5:0] pixel_fbw_q, pixel_psm_q; logic [31:0] pixel_fb_addr_q; logic raster_pixel_emit; logic [31:0] raster_pixel_emit_count; logic [11:0] raster_pixel_x_q, raster_pixel_y_q; logic [63:0] raster_pixel_color_q; logic [31:0] raster_pixel_fb_addr_q; logic [3:0] raster_pixel_be_q; logic [31:0] raster_pixel_mask_q; logic [5:0] raster_pixel_psm_q; logic raster_active, raster_overflow, raster_fifo_full, raster_degenerate; logic tex_rd_en; logic [31:0] tex_rd_addr; logic fb_rd_en; logic [31:0] fb_rd_addr; logic z_rd_en; logic [31:0] z_rd_addr; logic ev_valid; trace_pkg::subsys_e ev_subsys; trace_pkg::event_e ev_event; logic [63:0] ev_arg0, ev_arg1, ev_arg2, ev_arg3; logic [31:0] ev_flags; // Fog compiled OUT. gs_stub #(.FOG_ENABLE(1'b0)) u_gs ( .clk(clk), .rst_n(rst_n), .reg_wr_en(1'b0), .reg_wr_addr(16'd0), .reg_wr_data(64'd0), .gif_reg_wr_en(gif_reg_wr_en), .gif_reg_num(gif_reg_num), .gif_reg_data(gif_reg_data), .bg_r(bg_r), .bg_g(bg_g), .bg_b(bg_b), .prim_q(prim_q), .rgbaq_q(rgbaq_q), .xyz2_q(xyz2_q), .xyzf2_q(xyzf2_q), .frame_1_q(frame_1_q), .zbuf_1_q(zbuf_1_q), .prim_complete(prim_complete), .prim_complete_count(prim_complete_count), .prim_v0_q(prim_v0_q), .prim_v1_q(prim_v1_q), .prim_v2_q(prim_v2_q), .prim_color_q(prim_color_q), .prim_color_v0_q(prim_color_v0_q), .prim_color_v1_q(prim_color_v1_q), .prim_color_v2_q(prim_color_v2_q), .prim_v0_decoded_q(prim_v0_decoded_q), .prim_v1_decoded_q(prim_v1_decoded_q), .prim_v2_decoded_q(prim_v2_decoded_q), .prim_v0_color_decoded_q(prim_v0_color_decoded_q), .prim_v1_color_decoded_q(prim_v1_color_decoded_q), .prim_v2_color_decoded_q(prim_v2_color_decoded_q), .pixel_emit(pixel_emit), .pixel_emit_count(pixel_emit_count), .pixel_x_q(pixel_x_q), .pixel_y_q(pixel_y_q), .pixel_color_q(pixel_color_q), .pixel_fbp_q(pixel_fbp_q), .pixel_fbw_q(pixel_fbw_q), .pixel_psm_q(pixel_psm_q), .pixel_fb_addr_q(pixel_fb_addr_q), .raster_pixel_emit(raster_pixel_emit), .raster_pixel_emit_count(raster_pixel_emit_count), .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_be_q(raster_pixel_be_q), .raster_pixel_mask_q(raster_pixel_mask_q), .raster_pixel_psm_q(raster_pixel_psm_q), .raster_active(raster_active), .raster_overflow(raster_overflow), .raster_fifo_full(raster_fifo_full), .raster_degenerate(raster_degenerate), .tex_rd_en(tex_rd_en), .tex_rd_addr(tex_rd_addr), .tex_rd_data(32'd0), .fb_rd_en(fb_rd_en), .fb_rd_addr(fb_rd_addr), .fb_rd_data(32'd0), .z_rd_en(z_rd_en), .z_rd_addr(z_rd_addr), .z_rd_data(32'd0), .ev_valid(ev_valid), .ev_subsys(ev_subsys), .ev_event(ev_event), .ev_arg0(ev_arg0), .ev_arg1(ev_arg1), .ev_arg2(ev_arg2), .ev_arg3(ev_arg3), .ev_flags(ev_flags)); task automatic drive_reg(input logic [7:0] num, input logic [63:0] data); @(negedge clk); gif_reg_wr_en=1'b1; gif_reg_num=num; gif_reg_data=data; @(posedge clk); endtask task automatic drive_idle(); @(negedge clk); gif_reg_wr_en=1'b0; gif_reg_num=8'd0; gif_reg_data=64'd0; @(posedge clk); endtask function automatic logic [63:0] xyzf2(input int x, input int y, input int f); return {8'(f), 24'd0, 12'(y), 4'd0, 12'(x), 4'd0}; endfunction function automatic logic [63:0] rgbaq(input int r, input int g, input int b, input int a); return {32'd0, 8'(a), 8'(b), 8'(g), 8'(r)}; endfunction localparam logic [7:0] R_PRIM=8'h00, R_RGBAQ=8'h01, R_XYZF2=8'h04, R_FOGCOL=8'h3D, R_FRAME_1=8'h4C; localparam logic [63:0] PRIM_TRI_FGE = 64'd3 | (64'd1<<5); localparam logic [63:0] FRAME_1_VAL = 64'h0000_0000_0001_0000; localparam int TC_R=8'hC0, TC_G=8'h80, TC_B=8'h30, TC_A=8'hFF; bit covered [0:15][0:15]; logic [31:0] cap_c [0:15][0:15]; bit cap_armed; always_ff @(posedge clk) if (rst_n && cap_armed && raster_pixel_emit && raster_pixel_x_q < 16 && raster_pixel_y_q < 16) begin covered[raster_pixel_y_q][raster_pixel_x_q] <= 1'b1; cap_c [raster_pixel_y_q][raster_pixel_x_q] <= raster_pixel_color_q[31:0]; end int errors, checks; task automatic chk_raw(input int x, input int y); // With FOG_ENABLE=0, even FGE=1 + FOGCOL!=0 must emit the RAW flat color. if (!covered[y][x]) begin $error("[fogoff] (%0d,%0d) not covered", x, y); errors++; end else if (cap_c[y][x][7:0]!==TC_R[7:0] || cap_c[y][x][15:8]!==TC_G[7:0] || cap_c[y][x][23:16]!==TC_B[7:0] || cap_c[y][x][31:24]!==TC_A[7:0]) begin $error("[fogoff] (%0d,%0d) got %08x expected RAW (%0d,%0d,%0d,a=%0d) — fog NOT pruned", x, y, cap_c[y][x], TC_R, TC_G, TC_B, TC_A); errors++; end else begin $display("[fogoff] (%0d,%0d) RAW color (fog pruned) OK", x, y); checks++; end endtask initial begin errors=0; checks=0; cap_armed=0; for (int y=0;y<16;y++) for (int x=0;x<16;x++) begin covered[y][x]=0; cap_c[y][x]=0; end rst_n=0; gif_reg_wr_en=0; gif_reg_num=0; gif_reg_data=0; repeat(4) @(posedge clk); rst_n=1; repeat(2) @(posedge clk); // FGE=1 triangle with DISTINCT per-vertex F and a NONZERO FOGCOL: if fog // were active these would be visibly blended; with FOG_ENABLE=0 they are not. cap_armed=1; drive_reg(R_FOGCOL, 64'h00_60_40_20); // nonzero FOGCOL (would change pixels if fog on) drive_reg(R_PRIM, PRIM_TRI_FGE); drive_reg(R_FRAME_1, FRAME_1_VAL); drive_reg(R_RGBAQ, rgbaq(TC_R,TC_G,TC_B,TC_A)); drive_reg(R_XYZF2, xyzf2(2,1,8'h10)); drive_reg(R_RGBAQ, rgbaq(TC_R,TC_G,TC_B,TC_A)); drive_reg(R_XYZF2, xyzf2(13,2,8'hF0)); drive_reg(R_RGBAQ, rgbaq(TC_R,TC_G,TC_B,TC_A)); drive_reg(R_XYZF2, xyzf2(5,7,8'h80)); // closes drive_idle(); repeat(300) @(posedge clk); cap_armed=0; @(posedge clk); chk_raw(7,3); chk_raw(5,4); chk_raw(6,2); if (checks==0) begin $error("[fogoff] no interior pixels verified"); errors++; end $display("[tb_gs_fog_disabled] checks=%0d errors=%0d", checks, errors); if (errors==0) $display("[tb_gs_fog_disabled] PASS"); else $display("[tb_gs_fog_disabled] FAIL"); $finish; end initial begin #3000000; $error("[tb_gs_fog_disabled] timeout"); $finish; end endmodule : tb_gs_fog_disabled