// retroDE_ps2 — tb_ee_install_agent_smoke (Ch55) // // Ch55 unit verification: the boot_install_agent_stub, when driven once, // streams its Ch54-image payload through sif_dma_ee_ram_bridge_stub into // the EE memory map, where the new bridge→useg_shadow shadowing path // deposits the image into useg_shadow_mem. The EE CPU read port reads // the image back byte-exact. // // Chain (no IOP, no DMAC — install agent is the dumb producer): // boot_install_agent_stub (32-bit beats) // └─► sif_dma_ee_ram_bridge_stub (4×32 → 128 qword) // └─► ee_memory_map_stub (bridge_wr_* → useg_shadow_mem) // └─► ee_ram_stub (also written; verified via readback // through the EE CPU port) // // PASS criteria: // 1. boot agent asserts done_o. // 2. sif bridge's last_seen_o asserts. // 3. Reading useg addresses 0x80..0x1FC via the EE CPU read port // returns the exact Ch54 image word-for-word (96 words). // 4. No FAIL prints, no timeout. `timescale 1ns/1ps module tb_ee_install_agent_smoke; import trace_pkg::*; localparam int EE_RAM_BYTES = 8 * 1024; localparam int EE_RAM_ADDR_W = $clog2(EE_RAM_BYTES); localparam int TOTAL_WORDS = 96; localparam logic [31:0] DEST_BASE_BYTES = 32'h0000_0080; localparam logic [31:0] USEG_BASE_ADDR = 32'h0000_0080; // kuseg phys 0x80 logic clk; logic rst_n; initial clk = 1'b0; always #5 clk = ~clk; // ------------------------------------------------------------------ // Expected payload mirror (built the same way boot_install_agent_stub // builds its ROM). Used purely for post-install comparison. // ------------------------------------------------------------------ logic [31:0] expected [0:TOTAL_WORDS-1]; initial begin expected[0] = 32'h401A7000; expected[1] = 32'h275A0004; expected[2] = 32'h03400008; expected[3] = 32'h42000010; for (int i = 4; i < TOTAL_WORDS; i = i + 2) begin expected[i] = 32'h03E00008; expected[i + 1] = 32'h00000000; end end // ------------------------------------------------------------------ // Install agent // ------------------------------------------------------------------ logic go; logic agent_valid; logic [31:0] agent_data; logic agent_last; logic agent_ready; logic agent_busy; logic agent_done; logic agent_ev_valid; subsys_e agent_ev_subsys; event_e agent_ev_event; logic [63:0] agent_ev_arg0, agent_ev_arg1, agent_ev_arg2, agent_ev_arg3; logic [31:0] agent_ev_flags; boot_install_agent_stub #( .TOTAL_WORDS(TOTAL_WORDS), .MASTER_ID(8'd6) ) u_agent ( .clk(clk), .rst_n(rst_n), .go_i(go), .out_valid(agent_valid), .out_data(agent_data), .out_last(agent_last), .out_ready(agent_ready), .busy_o(agent_busy), .done_o(agent_done), .ev_valid(agent_ev_valid), .ev_subsys(agent_ev_subsys), .ev_event(agent_ev_event), .ev_arg0(agent_ev_arg0), .ev_arg1(agent_ev_arg1), .ev_arg2(agent_ev_arg2), .ev_arg3(agent_ev_arg3), .ev_flags(agent_ev_flags) ); // ------------------------------------------------------------------ // SIF EE-RAM bridge (agent → 128-bit map write) // ------------------------------------------------------------------ logic br_wr_en; logic [31:0] br_wr_addr; logic [127:0] br_wr_data; logic [15:0] br_wr_be; logic [7:0] br_master_id; logic br_last_seen; sif_dma_ee_ram_bridge_stub #( .DEST_BASE_ADDR(DEST_BASE_BYTES), .MASTER_ID(8'd5) ) u_bridge ( .clk(clk), .rst_n(rst_n), .in_valid(agent_valid), .in_data(agent_data), .in_last(agent_last), .in_ready(agent_ready), .bridge_wr_en(br_wr_en), .bridge_wr_addr(br_wr_addr), .bridge_wr_data(br_wr_data), .bridge_wr_be(br_wr_be), .bridge_master_id(br_master_id), .last_seen_o(br_last_seen) ); // ------------------------------------------------------------------ // EE memory map + EE RAM // ------------------------------------------------------------------ logic ee_rd_en; logic [31:0] ee_rd_addr; logic [31:0] ee_rd_data; logic ee_rd_valid; logic ram_rd_en; logic [24:0] ram_rd_addr; logic [127:0] ram_rd_data; logic ram_rd_valid; logic ram_wr_en; logic [24:0] ram_wr_addr; logic [127:0] ram_wr_data; logic [15:0] ram_wr_be; logic [7:0] ram_master_id; logic map_ev_valid; subsys_e map_ev_subsys; event_e map_ev_event; logic [63:0] map_ev_arg0, map_ev_arg1, map_ev_arg2, map_ev_arg3; logic [31:0] map_ev_flags; ee_memory_map_stub u_ee_map ( .clk(clk), .rst_n(rst_n), .ee_rd_en(ee_rd_en), .ee_rd_addr(ee_rd_addr), .ee_rd_data(ee_rd_data), .ee_rd_valid(ee_rd_valid), .ee_wr_en(1'b0), .ee_wr_addr(32'd0), .ee_wr_data(32'd0), .ee_wr_be(4'd0), .dmac_rd_en(1'b0), .dmac_rd_addr(32'd0), .dmac_rd_data(), .dmac_rd_valid(), .bridge_wr_en(br_wr_en), .bridge_wr_addr(br_wr_addr), .bridge_wr_data(br_wr_data), .bridge_wr_be(br_wr_be), .bridge_master_id(br_master_id), .bios_rd_en(), .bios_rd_addr(), .bios_rd_data(32'd0), .bios_rd_valid(1'b0), .ram_rd_en(ram_rd_en), .ram_rd_addr(ram_rd_addr), .ram_rd_data(ram_rd_data), .ram_rd_valid(ram_rd_valid), .ram_wr_en(ram_wr_en), .ram_wr_addr(ram_wr_addr), .ram_wr_data(ram_wr_data), .ram_wr_be(ram_wr_be), .ram_master_id(ram_master_id), .ee_dmac_ch2_wr_en(), .ee_dmac_ch2_wr_addr(), .ee_dmac_ch2_wr_data(), .ee_dmac_ch2_rd_en(), .ee_dmac_ch2_rd_addr(), .ee_dmac_ch2_rd_data(32'd0), .ee_dmac_ch2_rd_valid(1'b0), .ee_intc_wr_en(), .ee_intc_wr_addr(), .ee_intc_wr_data(), .ee_intc_rd_en(), .ee_intc_rd_addr(), .ee_intc_rd_data(32'd0), .ee_intc_rd_valid(1'b0), .ee_misc_mmio_wr_en(), .ee_misc_mmio_wr_addr(), .ee_misc_mmio_wr_data(), .ee_misc_mmio_wr_be(), .ee_misc_mmio_rd_en(), .ee_misc_mmio_rd_addr(), .ee_misc_mmio_rd_data(32'd0), .ee_misc_mmio_rd_valid(1'b0), .ee_biu_wr_en(), .ee_biu_wr_addr(), .ee_biu_wr_data(), .ee_biu_wr_be(), .ee_biu_rd_en(), .ee_biu_rd_addr(), .ee_biu_rd_data(32'd0), .ee_biu_rd_valid(1'b0), .ev_valid(map_ev_valid), .ev_subsys(map_ev_subsys), .ev_event(map_ev_event), .ev_arg0(map_ev_arg0), .ev_arg1(map_ev_arg1), .ev_arg2(map_ev_arg2), .ev_arg3(map_ev_arg3), .ev_flags(map_ev_flags) ); ee_ram_stub #(.SIZE_BYTES(EE_RAM_BYTES)) u_ee_ram ( .clk(clk), .rst_n(rst_n), .rd_en(ram_rd_en), .rd_addr(ram_rd_addr[EE_RAM_ADDR_W-1:0]), .rd_data(ram_rd_data), .rd_valid(ram_rd_valid), .wr_en(ram_wr_en), .wr_addr(ram_wr_addr[EE_RAM_ADDR_W-1:0]), .wr_data(ram_wr_data), .wr_be(ram_wr_be), .master_id(ram_master_id), .ev_valid(), .ev_subsys(), .ev_event(), .ev_arg0(), .ev_arg1(), .ev_arg2(), .ev_arg3(), .ev_flags() ); // ------------------------------------------------------------------ // Counters / observation // ------------------------------------------------------------------ int agent_start_count; int agent_beat_count; int agent_done_count; int map_useg_writes; initial begin agent_start_count = 0; agent_beat_count = 0; agent_done_count = 0; map_useg_writes = 0; end always_ff @(posedge clk) begin if (rst_n && agent_ev_valid && agent_ev_subsys == SUBSYS_SIF) begin case (agent_ev_event) EV_DMA_START: agent_start_count <= agent_start_count + 1; EV_DMA_BEAT: agent_beat_count <= agent_beat_count + 1; EV_DMA_DONE: agent_done_count <= agent_done_count + 1; default: ; endcase end if (rst_n && map_ev_valid && map_ev_subsys == SUBSYS_MEM && map_ev_event == EV_WRITE && map_ev_arg3[7:0] == 8'd1) begin // bridge writes to ee_ram emit REGION_EE_RAM; the shadowing // side-effect is internal (no separate ev tag). Count these // as evidence that bridge actually drove the map. map_useg_writes <= map_useg_writes + 1; end end // ------------------------------------------------------------------ // Readback via EE CPU port (1-cycle latency) // ------------------------------------------------------------------ task automatic ee_read_word(input logic [31:0] addr, output logic [31:0] data); @(negedge clk); ee_rd_en = 1'b1; ee_rd_addr = addr; @(negedge clk); ee_rd_en = 1'b0; ee_rd_addr = 32'd0; @(posedge clk); data = ee_rd_data; endtask // ------------------------------------------------------------------ // Main // ------------------------------------------------------------------ int errors; int timeout_cycles; initial begin rst_n = 1'b0; go = 1'b0; ee_rd_en = 1'b0; ee_rd_addr = 32'd0; errors = 0; timeout_cycles = 0; // Reset repeat (4) @(posedge clk); rst_n = 1'b1; repeat (2) @(posedge clk); // Kick the installer @(negedge clk); go = 1'b1; @(negedge clk); go = 1'b0; // Wait for done or timeout while (!agent_done && timeout_cycles < 2000) begin @(posedge clk); timeout_cycles = timeout_cycles + 1; end if (!agent_done) begin $display("[tb_ee_install_agent_smoke] FAIL: timeout waiting for agent done (cyc=%0d)", timeout_cycles); errors = errors + 1; end // Drain any in-flight bridge beats (the last qword emit takes // one extra cycle after the accumulator fills). repeat (8) @(posedge clk); if (!br_last_seen) begin $display("[tb_ee_install_agent_smoke] FAIL: bridge last_seen never asserted"); errors = errors + 1; end // Byte-compare all 96 words through the EE CPU read port. for (int i = 0; i < TOTAL_WORDS; i++) begin logic [31:0] got; ee_read_word(USEG_BASE_ADDR + i * 4, got); if (got !== expected[i]) begin $display("[tb_ee_install_agent_smoke] FAIL word %0d @0x%08x: got %08x exp %08x", i, USEG_BASE_ADDR + i * 4, got, expected[i]); errors = errors + 1; end end $display("[tb_ee_install_agent_smoke] start_events=%0d beat_events=%0d done_events=%0d bridge_writes=%0d", agent_start_count, agent_beat_count, agent_done_count, map_useg_writes); if (agent_start_count != 1) begin $display("[tb_ee_install_agent_smoke] FAIL: expected 1 start event, got %0d", agent_start_count); errors = errors + 1; end if (agent_beat_count != TOTAL_WORDS) begin $display("[tb_ee_install_agent_smoke] FAIL: expected %0d beat events, got %0d", TOTAL_WORDS, agent_beat_count); errors = errors + 1; end if (agent_done_count != 1) begin $display("[tb_ee_install_agent_smoke] FAIL: expected 1 done event, got %0d", agent_done_count); errors = errors + 1; end // 96 words / 4 words per qword = 24 bridge qword writes expected if (map_useg_writes != TOTAL_WORDS / 4) begin $display("[tb_ee_install_agent_smoke] FAIL: expected %0d bridge qword writes, got %0d", TOTAL_WORDS / 4, map_useg_writes); errors = errors + 1; end if (errors == 0) $display("[tb_ee_install_agent_smoke] PASS"); else $display("[tb_ee_install_agent_smoke] FAIL total=%0d", errors); $finish; end initial begin #200000; $display("[tb_ee_install_agent_smoke] FAIL: absolute timeout"); $finish; end endmodule : tb_ee_install_agent_smoke