mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-06 14:55:14 +00:00
feat: add APU-P1 support and enhance test coverage
- Introduced new task in for handling high-performance APU writes with access fault checks. - Updated to support an expanded resource count, including ownership and IRQ routing for the new APU resource. - Enhanced to validate IRQ expectations for the newly added APU resource. - Created for directed verification of APU-P1 APB4 register shell and integrated IRQ ownership topology. - Added to ensure synchronization between RTL and SDK register ABI. - Modified to parameterize tests for product modes, improving flexibility in testing. - Updated to reflect changes in APU memory mapping and ensure correct assertions. - Enhanced to validate the complete IRQ and resource allocations for the APU.
This commit is contained in:
41 files changed
+2385
-134
No files matched your search
@@ -16,7 +16,7 @@ module apb4_topology_tb;
|
||||
begin
|
||||
s_decode_addr = address;
|
||||
#1;
|
||||
if (s_psel_comb !== (20'd1 << slot)) begin
|
||||
if (s_psel_comb !== (28'd1 << slot)) begin
|
||||
$fatal(1, "unexpected APB4 target slot for %h: got %b", address, s_psel_comb);
|
||||
end
|
||||
end
|
||||
@@ -44,7 +44,7 @@ module apb4_topology_tb;
|
||||
expect_select(`SOC_ADDR_APB4_SDIO1_BASE, 18);
|
||||
expect_select(`SOC_ADDR_APB4_CRYPTO_BASE, 19);
|
||||
expect_disabled(`SOC_ADDR_APB4_GA_BASE);
|
||||
expect_disabled(`SOC_ADDR_APB4_APU_BASE);
|
||||
expect_select(`SOC_ADDR_APB4_APU_BASE, 27);
|
||||
$display("SoC topology APB4 routing test passed");
|
||||
$finish;
|
||||
end
|
||||
|
||||
@@ -0,0 +1,271 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
`include "apu_define.svh"
|
||||
`include "soc_irq_config.svh"
|
||||
|
||||
module apu_irq_topology_tb;
|
||||
localparam logic [31:0] ApuBase = 32'h1001_3000;
|
||||
localparam logic [11:0] Resource7Owner = 12'h1e0;
|
||||
localparam logic [11:0] Resource7Control = 12'h1e4;
|
||||
localparam logic [11:0] Resource7Fault = 12'h1ec;
|
||||
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
logic s_apu_idle;
|
||||
logic s_apu_irq_raw;
|
||||
logic [ 7:0] s_resource_idle;
|
||||
logic [ 7:0] s_resource_block_ack;
|
||||
logic [ 7:0] s_resource_irq_raw;
|
||||
logic [ 7:0][1:0] s_resource_owner;
|
||||
logic [ 7:0] s_resource_owner_lock;
|
||||
logic [ 7:0] s_resource_quiesce;
|
||||
logic [ 7:0] s_resource_reset;
|
||||
logic [ 7:0] s_resource_irq_lp;
|
||||
logic [ 7:0] s_resource_irq_hp;
|
||||
logic [ 6:0] s_resource_irq_lp_compact;
|
||||
logic [ 6:0] s_resource_irq_hp_compact;
|
||||
logic s_resource_fault_irq;
|
||||
logic s_cache_clean;
|
||||
logic [`SOC_IRQ_APB4_PERIPH_WIDTH-1:0] s_apb4_periph_irq;
|
||||
logic [`SOC_IRQ_APB4_SYSTEM_WIDTH-1:0] s_apb4_system_irq;
|
||||
logic [ `SOC_IRQ_VECTOR_WIDTH-1:0] s_irq;
|
||||
logic [ 31:0] s_hp_plic_source;
|
||||
logic [ 1:0] s_hp_plic_context_irq;
|
||||
logic [ 31:0] s_value;
|
||||
|
||||
apb4_if u_apu_apb4_if (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
);
|
||||
apb4_if u_resource_apb4_if (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
);
|
||||
apb4_if u_plic_apb4_if (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
);
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
assign s_resource_idle = {s_apu_idle, 7'h7f};
|
||||
assign s_resource_block_ack = {
|
||||
s_apu_idle && (s_resource_quiesce[7] || s_resource_reset[7]), 7'd0
|
||||
};
|
||||
assign s_resource_irq_raw = {s_apu_irq_raw, 7'd0};
|
||||
assign s_resource_irq_lp_compact = {s_resource_irq_lp[7:6], s_resource_irq_lp[4:0]};
|
||||
assign s_resource_irq_hp_compact = {s_resource_irq_hp[7:6], s_resource_irq_hp[4:0]};
|
||||
assign s_apb4_periph_irq = {s_resource_irq_lp_compact[6], 23'd0};
|
||||
assign s_apb4_system_irq = '0;
|
||||
assign s_hp_plic_source = {21'd0, s_resource_irq_hp_compact[6], 10'd0};
|
||||
|
||||
`include "soc_irq_wiring.svh"
|
||||
|
||||
apb4_apu u_apu (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.owner_i (s_resource_owner[7]),
|
||||
.owner_lock_i (s_resource_owner_lock[7]),
|
||||
.quiesce_i (s_resource_quiesce[7]),
|
||||
.resource_reset_i(s_resource_reset[7]),
|
||||
.apb4 (u_apu_apb4_if),
|
||||
.idle_o (s_apu_idle),
|
||||
.irq_o (s_apu_irq_raw)
|
||||
);
|
||||
|
||||
resource_controller #(
|
||||
.ResourceCount(8)
|
||||
) u_resource_controller (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.idle_i (s_resource_idle),
|
||||
.block_ack_i (s_resource_block_ack),
|
||||
.irq_i (s_resource_irq_raw),
|
||||
.cache_request_i(1'b0),
|
||||
.cache_clean_o (s_cache_clean),
|
||||
.owner_o (s_resource_owner),
|
||||
.owner_lock_o (s_resource_owner_lock),
|
||||
.quiesce_o (s_resource_quiesce),
|
||||
.reset_o (s_resource_reset),
|
||||
.irq_lp_o (s_resource_irq_lp),
|
||||
.irq_hp_o (s_resource_irq_hp),
|
||||
.fault_irq_o (s_resource_fault_irq),
|
||||
.apb4 (u_resource_apb4_if)
|
||||
);
|
||||
|
||||
apb4_plic u_hp_plic (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.source_i (s_hp_plic_source),
|
||||
.apb4 (u_plic_apb4_if),
|
||||
.context_irq_o(s_hp_plic_context_irq)
|
||||
);
|
||||
|
||||
task automatic drive_apb_idle;
|
||||
begin
|
||||
u_apu_apb4_if.paddr = 32'd0;
|
||||
u_apu_apb4_if.pprot = 3'd0;
|
||||
u_apu_apb4_if.psel = 1'b0;
|
||||
u_apu_apb4_if.penable = 1'b0;
|
||||
u_apu_apb4_if.pwrite = 1'b0;
|
||||
u_apu_apb4_if.pwdata = 32'd0;
|
||||
u_apu_apb4_if.pstrb = 4'd0;
|
||||
u_resource_apb4_if.paddr = 32'd0;
|
||||
u_resource_apb4_if.pprot = 3'd0;
|
||||
u_resource_apb4_if.psel = 1'b0;
|
||||
u_resource_apb4_if.penable = 1'b0;
|
||||
u_resource_apb4_if.pwrite = 1'b0;
|
||||
u_resource_apb4_if.pwdata = 32'd0;
|
||||
u_resource_apb4_if.pstrb = 4'd0;
|
||||
u_plic_apb4_if.paddr = 32'd0;
|
||||
u_plic_apb4_if.pprot = 3'd0;
|
||||
u_plic_apb4_if.psel = 1'b0;
|
||||
u_plic_apb4_if.penable = 1'b0;
|
||||
u_plic_apb4_if.pwrite = 1'b0;
|
||||
u_plic_apb4_if.pwdata = 32'd0;
|
||||
u_plic_apb4_if.pstrb = 4'd0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic apu_write(input logic [11:0] offset_i, input logic [31:0] data_i);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
u_apu_apb4_if.paddr = ApuBase + offset_i;
|
||||
u_apu_apb4_if.pwdata = data_i;
|
||||
u_apu_apb4_if.pstrb = 4'hf;
|
||||
u_apu_apb4_if.pwrite = 1'b1;
|
||||
u_apu_apb4_if.psel = 1'b1;
|
||||
u_apu_apb4_if.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
u_apu_apb4_if.penable = 1'b1;
|
||||
while (!u_apu_apb4_if.pready) @(negedge clk_i);
|
||||
if (u_apu_apb4_if.pslverr) $fatal(1, "APU topology write failed at %h", offset_i);
|
||||
@(negedge clk_i);
|
||||
u_apu_apb4_if.psel = 1'b0;
|
||||
u_apu_apb4_if.penable = 1'b0;
|
||||
u_apu_apb4_if.pwrite = 1'b0;
|
||||
u_apu_apb4_if.pstrb = 4'd0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic resource_write(input logic [11:0] offset_i, input logic [31:0] data_i,
|
||||
input logic expected_err_i);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
u_resource_apb4_if.paddr = {20'd0, offset_i};
|
||||
u_resource_apb4_if.pwdata = data_i;
|
||||
u_resource_apb4_if.pstrb = 4'hf;
|
||||
u_resource_apb4_if.pwrite = 1'b1;
|
||||
u_resource_apb4_if.psel = 1'b1;
|
||||
u_resource_apb4_if.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
u_resource_apb4_if.penable = 1'b1;
|
||||
while (!u_resource_apb4_if.pready) @(negedge clk_i);
|
||||
if (u_resource_apb4_if.pslverr != expected_err_i) begin
|
||||
$fatal(1, "Resource topology write response mismatch at %h", offset_i);
|
||||
end
|
||||
@(negedge clk_i);
|
||||
u_resource_apb4_if.psel = 1'b0;
|
||||
u_resource_apb4_if.penable = 1'b0;
|
||||
u_resource_apb4_if.pwrite = 1'b0;
|
||||
u_resource_apb4_if.pstrb = 4'd0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic plic_write(input logic [25:0] offset_i, input logic [31:0] data_i);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
u_plic_apb4_if.paddr = {6'd0, offset_i};
|
||||
u_plic_apb4_if.pwdata = data_i;
|
||||
u_plic_apb4_if.pstrb = 4'hf;
|
||||
u_plic_apb4_if.pwrite = 1'b1;
|
||||
u_plic_apb4_if.psel = 1'b1;
|
||||
u_plic_apb4_if.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
u_plic_apb4_if.penable = 1'b1;
|
||||
while (!u_plic_apb4_if.pready) @(negedge clk_i);
|
||||
if (u_plic_apb4_if.pslverr) $fatal(1, "PLIC topology write failed at %h", offset_i);
|
||||
@(negedge clk_i);
|
||||
u_plic_apb4_if.psel = 1'b0;
|
||||
u_plic_apb4_if.penable = 1'b0;
|
||||
u_plic_apb4_if.pwrite = 1'b0;
|
||||
u_plic_apb4_if.pstrb = 4'd0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic plic_read(input logic [25:0] offset_i, output logic [31:0] data_o);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
u_plic_apb4_if.paddr = {6'd0, offset_i};
|
||||
u_plic_apb4_if.pstrb = 4'd0;
|
||||
u_plic_apb4_if.pwrite = 1'b0;
|
||||
u_plic_apb4_if.psel = 1'b1;
|
||||
u_plic_apb4_if.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
u_plic_apb4_if.penable = 1'b1;
|
||||
while (!u_plic_apb4_if.pready) @(negedge clk_i);
|
||||
if (u_plic_apb4_if.pslverr) $fatal(1, "PLIC topology read failed at %h", offset_i);
|
||||
data_o = u_plic_apb4_if.prdata;
|
||||
@(negedge clk_i);
|
||||
u_plic_apb4_if.psel = 1'b0;
|
||||
u_plic_apb4_if.penable = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
drive_apb_idle();
|
||||
repeat (4) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
|
||||
plic_write(26'h000028, 32'd3);
|
||||
plic_write(26'h002000, 32'h0000_0400);
|
||||
plic_write(26'h200000, 32'd0);
|
||||
apu_write(`APB4_APU__IRQ_ENABLE, 32'h0000_0001);
|
||||
apu_write(`APB4_APU__IRQ_TEST, 32'h0000_0001);
|
||||
repeat (2) @(posedge clk_i);
|
||||
#1;
|
||||
if ((s_resource_owner[7] != 2'd0) || !s_resource_irq_lp[7] || s_resource_irq_hp[7] ||
|
||||
!s_apb4_periph_irq[23] || !s_irq[31] || s_hp_plic_source[10] ||
|
||||
s_hp_plic_context_irq[0]) begin
|
||||
$fatal(1, "APU event was not delivered exclusively to LP IRQ31");
|
||||
end
|
||||
|
||||
resource_write(Resource7Control, 32'h0000_0001, 1'b0);
|
||||
resource_write(Resource7Owner, 32'h0000_0101, 1'b0);
|
||||
repeat (2) @(posedge clk_i);
|
||||
#1;
|
||||
if ((s_resource_owner[7] != 2'd1) || !s_resource_owner_lock[7] ||
|
||||
s_resource_irq_lp[7] || !s_resource_irq_hp[7] || s_apb4_periph_irq[23] ||
|
||||
s_irq[31] || !s_hp_plic_source[10] || !s_hp_plic_context_irq[0]) begin
|
||||
$fatal(1, "APU event was not delivered exclusively to HP PLIC source 10");
|
||||
end
|
||||
plic_read(26'h200004, s_value);
|
||||
if (s_value != 32'd10) $fatal(1, "HP PLIC did not claim APU source 10");
|
||||
|
||||
resource_write(Resource7Owner, 32'd0, 1'b1);
|
||||
if ((s_resource_owner[7] != 2'd1) || !s_resource_owner_lock[7] || !s_resource_fault_irq) begin
|
||||
$fatal(1, "APU owner lock did not preserve HP ownership");
|
||||
end
|
||||
resource_write(Resource7Fault, 32'h0000_0001, 1'b0);
|
||||
if (s_resource_fault_irq) $fatal(1, "APU resource fault did not clear");
|
||||
|
||||
resource_write(Resource7Control, 32'h0000_0003, 1'b0);
|
||||
repeat (2) @(posedge clk_i);
|
||||
#1;
|
||||
if (s_resource_irq_lp[7] || s_resource_irq_hp[7] || s_apb4_periph_irq[23] || s_irq[31] ||
|
||||
s_hp_plic_source[10]) begin
|
||||
$fatal(1, "APU resource reset did not mask both interrupt routes");
|
||||
end
|
||||
|
||||
if (s_resource_fault_irq || s_cache_clean) begin
|
||||
$fatal(1, "APU topology test left an unrelated controller output asserted");
|
||||
end
|
||||
$display("APU-P1 integrated IRQ ownership topology passed");
|
||||
$finish;
|
||||
end
|
||||
|
||||
initial begin
|
||||
repeat (1000) @(posedge clk_i);
|
||||
$fatal(1, "APU-P1 IRQ ownership topology timed out");
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,542 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
`include "apu_define.svh"
|
||||
|
||||
module apu_reg_tb;
|
||||
localparam logic [31:0] ApuBase = 32'h1001_3000;
|
||||
localparam int unsigned RegisterCount = 95;
|
||||
localparam logic [1:0] AccessRo = 2'd0;
|
||||
localparam logic [1:0] AccessWo = 2'd1;
|
||||
localparam logic [1:0] AccessRw = 2'd2;
|
||||
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
logic [ 1:0] owner_i = 2'd0;
|
||||
logic owner_lock_i = 1'b0;
|
||||
logic quiesce_i = 1'b0;
|
||||
logic resource_reset_i = 1'b0;
|
||||
logic idle_o;
|
||||
logic irq_o;
|
||||
logic [31:0] s_value;
|
||||
logic [11:0] s_reg_offset [RegisterCount];
|
||||
logic [ 1:0] s_reg_access [RegisterCount];
|
||||
logic [31:0] s_reg_reset [RegisterCount];
|
||||
logic s_reg_full_strobe [RegisterCount];
|
||||
int unsigned s_reg_count;
|
||||
|
||||
apb4_if apb4 (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
);
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
apb4_apu u_dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.owner_i (owner_i),
|
||||
.owner_lock_i (owner_lock_i),
|
||||
.quiesce_i (quiesce_i),
|
||||
.resource_reset_i(resource_reset_i),
|
||||
.apb4 (apb4),
|
||||
.idle_o (idle_o),
|
||||
.irq_o (irq_o)
|
||||
);
|
||||
|
||||
function automatic logic [31:0] legal_write_value(input logic [11:0] offset_i);
|
||||
case (offset_i)
|
||||
`APB4_APU__IRQ_STATE: legal_write_value = 32'h0000_07ff;
|
||||
`APB4_APU__IRQ_ENABLE: legal_write_value = 32'h0000_0005;
|
||||
`APB4_APU__ERROR_STATUS: legal_write_value = 32'h0000_0001;
|
||||
`APB4_APU__SEQUENCER_TIMEOUT: legal_write_value = 32'h1234_5678;
|
||||
`APB4_APU__STREAM_ROUTE: legal_write_value = 32'd0;
|
||||
`APB4_APU__READ_BASE: legal_write_value = 32'h3000_0000;
|
||||
`APB4_APU__READ_LIMIT: legal_write_value = 32'h3000_ffff;
|
||||
`APB4_APU__WRITE_BASE: legal_write_value = 32'h3001_0000;
|
||||
`APB4_APU__WRITE_LIMIT: legal_write_value = 32'h3001_ffff;
|
||||
`APB4_APU__DMA_TIMEOUT: legal_write_value = 32'h8765_4321;
|
||||
`APB4_APU__MC_IMAGE_ADDRESS: legal_write_value = 32'h3002_0000;
|
||||
`APB4_APU__MC_IMAGE_SIZE: legal_write_value = 32'h0000_0040;
|
||||
`APB4_APU__MC_EXPECTED_CRC: legal_write_value = 32'ha5a5_5a5a;
|
||||
`APB4_APU__JOB_CONTROL: legal_write_value = 32'h0000_0121;
|
||||
`APB4_APU__JOB_INPUT_ADDRESS: legal_write_value = 32'h3003_0000;
|
||||
`APB4_APU__JOB_INPUT_LENGTH: legal_write_value = 32'h0000_0100;
|
||||
`APB4_APU__JOB_OUTPUT_ADDRESS: legal_write_value = 32'h3003_1000;
|
||||
`APB4_APU__JOB_OUTPUT_CAPACITY: legal_write_value = 32'h0000_1000;
|
||||
`APB4_APU__JOB_INPUT_CONFIG: legal_write_value = 32'h0012_3456;
|
||||
`APB4_APU__JOB_OUTPUT_CONFIG: legal_write_value = 32'h0001_2345;
|
||||
`APB4_APU__JOB_FLAGS: legal_write_value = 32'h0000_0001;
|
||||
`APB4_APU__RING_BASE: legal_write_value = 32'h3004_0000;
|
||||
`APB4_APU__RING_SIZE: legal_write_value = 32'h0000_0008;
|
||||
`APB4_APU__RING_TAIL: legal_write_value = 32'h0000_0003;
|
||||
`APB4_APU__RING_CONTROL: legal_write_value = 32'h0000_0001;
|
||||
`APB4_APU__RING_COALESCE: legal_write_value = 32'h0004_0002;
|
||||
`APB4_APU__KWS_MODEL_ADDRESS: legal_write_value = 32'h3005_0000;
|
||||
`APB4_APU__KWS_MODEL_SIZE: legal_write_value = 32'h0000_0100;
|
||||
`APB4_APU__KWS_MODEL_EXPECTED_CRC: legal_write_value = 32'h5a5a_a5a5;
|
||||
`APB4_APU__KWS_CONTROL: legal_write_value = 32'h0000_0004;
|
||||
`APB4_APU__KWS_CONFIG: legal_write_value = 32'h0000_0590;
|
||||
`APB4_APU__PERF_CONTROL: legal_write_value = 32'h0000_0001;
|
||||
default: legal_write_value = 32'd0;
|
||||
endcase
|
||||
endfunction
|
||||
|
||||
function automatic logic [31:0] legal_readback_value(input logic [11:0] offset_i);
|
||||
case (offset_i)
|
||||
`APB4_APU__IRQ_STATE, `APB4_APU__ERROR_STATUS, `APB4_APU__STREAM_ROUTE,
|
||||
`APB4_APU__KWS_CONTROL:
|
||||
legal_readback_value = 32'd0;
|
||||
default: legal_readback_value = legal_write_value(offset_i);
|
||||
endcase
|
||||
endfunction
|
||||
|
||||
function automatic logic [31:0] reset_or_preserved_value(input logic [11:0] offset_i,
|
||||
input logic [31:0] reset_i);
|
||||
case (offset_i)
|
||||
`APB4_APU__READ_BASE, `APB4_APU__READ_LIMIT, `APB4_APU__WRITE_BASE, `APB4_APU__WRITE_LIMIT:
|
||||
reset_or_preserved_value = legal_write_value(offset_i);
|
||||
default: reset_or_preserved_value = reset_i;
|
||||
endcase
|
||||
endfunction
|
||||
|
||||
task automatic add_register(input logic [11:0] offset_i, input logic [1:0] access_i,
|
||||
input logic [31:0] reset_i, input logic full_strobe_i);
|
||||
begin
|
||||
if (s_reg_count >= RegisterCount) $fatal(1, "APU register table overflow");
|
||||
s_reg_offset[s_reg_count] = offset_i;
|
||||
s_reg_access[s_reg_count] = access_i;
|
||||
s_reg_reset[s_reg_count] = reset_i;
|
||||
s_reg_full_strobe[s_reg_count] = full_strobe_i;
|
||||
s_reg_count++;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic initialize_register_table;
|
||||
begin
|
||||
s_reg_count = 0;
|
||||
add_register(`APB4_APU__IP_ID, AccessRo, 32'h4150_5530, 1'b0);
|
||||
add_register(`APB4_APU__IP_VERSION, AccessRo, 32'h0001_0000, 1'b0);
|
||||
add_register(`APB4_APU__CAPABILITY0, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__CAPABILITY1, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__COMMAND, AccessWo, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__STATUS, AccessRo, 32'h0000_0100, 1'b0);
|
||||
add_register(`APB4_APU__IRQ_STATE, AccessRw, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__IRQ_ENABLE, AccessRw, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__IRQ_TEST, AccessWo, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__ERROR_STATUS, AccessRw, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__ERROR_ADDRESS, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__ERROR_DETAIL, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__SEQUENCER_TIMEOUT, AccessRw, 32'h0000_ffff, 1'b0);
|
||||
add_register(`APB4_APU__STREAM_ROUTE, AccessRw, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__STREAM_STATUS, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__OWNER_STATUS, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__READ_BASE, AccessRw, 32'hffff_ffff, 1'b1);
|
||||
add_register(`APB4_APU__READ_LIMIT, AccessRw, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__WRITE_BASE, AccessRw, 32'hffff_ffff, 1'b1);
|
||||
add_register(`APB4_APU__WRITE_LIMIT, AccessRw, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__DMA_TIMEOUT, AccessRw, 32'h0000_ffff, 1'b0);
|
||||
add_register(`APB4_APU__ABI_DIGEST, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__SEQUENCER_STATUS, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__SEQUENCER_RETIRED, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__MC_IMAGE_ADDRESS, AccessRw, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__MC_IMAGE_SIZE, AccessRw, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__MC_EXPECTED_CRC, AccessRw, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__MC_STATUS, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__MC_ABI, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__MC_BUILD_ID_LO, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__MC_BUILD_ID_HI, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__MC_LOCK, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__MC_ACTUAL_CRC, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__MC_LOAD_COUNT, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__JOB_CONTROL, AccessRw, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__JOB_INPUT_ADDRESS, AccessRw, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__JOB_INPUT_LENGTH, AccessRw, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__JOB_OUTPUT_ADDRESS, AccessRw, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__JOB_OUTPUT_CAPACITY, AccessRw, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__JOB_INPUT_CONFIG, AccessRw, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__JOB_OUTPUT_CONFIG, AccessRw, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__JOB_FLAGS, AccessRw, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__JOB_STATUS, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__JOB_INPUT_USED, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__JOB_OUTPUT_BYTES, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__JOB_FRAMES, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__JOB_SOURCE_INFO, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__JOB_CYCLES, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__JOB_DETAIL, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__RING_BASE, AccessRw, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__RING_SIZE, AccessRw, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__RING_HEAD, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__RING_TAIL, AccessRw, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__RING_CONTROL, AccessRw, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__RING_STATUS, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__RING_COMPLETED, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__RING_COALESCE, AccessRw, 32'h0001_0001, 1'b1);
|
||||
add_register(`APB4_APU__RING_DOORBELL, AccessWo, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__KWS_MODEL_ADDRESS, AccessRw, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__KWS_MODEL_SIZE, AccessRw, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__KWS_MODEL_EXPECTED_CRC, AccessRw, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__KWS_CONTROL, AccessRw, 32'd0, 1'b1);
|
||||
add_register(`APB4_APU__KWS_CONFIG, AccessRw, 32'h0000_0380, 1'b0);
|
||||
add_register(`APB4_APU__KWS_STATUS, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__KWS_RESULT, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__KWS_TIMESTAMP_LO, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__KWS_TIMESTAMP_HI, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__KWS_FRAME_COUNT, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__KWS_INFERENCE_COUNT, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__KWS_HIT_COUNT, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__KWS_OVERRUN_COUNT, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__KWS_MODEL_STATUS, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__KWS_MODEL_ACTUAL_CRC, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_CONTROL, AccessRw, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_STATUS, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_ACTIVE_CYCLES_LO, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_ACTIVE_CYCLES_HI, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_INPUT_BYTES_LO, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_INPUT_BYTES_HI, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_OUTPUT_BYTES_LO, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_OUTPUT_BYTES_HI, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_DECODED_FRAMES_LO, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_DECODED_FRAMES_HI, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_DMA_READ_STALLS_LO, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_DMA_READ_STALLS_HI, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_DMA_WRITE_STALLS_LO, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_DMA_WRITE_STALLS_HI, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_STREAM_STALLS_LO, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_STREAM_STALLS_HI, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_SEQUENCER_INSTR_LO, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_SEQUENCER_INSTR_HI, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_KWS_CYCLES_LO, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_KWS_CYCLES_HI, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_FAULTS_LO, AccessRo, 32'd0, 1'b0);
|
||||
add_register(`APB4_APU__PERF_FAULTS_HI, AccessRo, 32'd0, 1'b0);
|
||||
if (s_reg_count != RegisterCount) begin
|
||||
$fatal(1, "APU register table has %0d entries, expected %0d", s_reg_count, RegisterCount);
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic drive_apb_idle;
|
||||
begin
|
||||
apb4.paddr = 32'd0;
|
||||
apb4.pprot = 3'd0;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.pwdata = 32'd0;
|
||||
apb4.pstrb = 4'd0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic hard_reset;
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
drive_apb_idle();
|
||||
owner_i = 2'd0;
|
||||
owner_lock_i = 1'b0;
|
||||
quiesce_i = 1'b0;
|
||||
resource_reset_i = 1'b0;
|
||||
rst_n_i = 1'b0;
|
||||
repeat (2) @(posedge clk_i);
|
||||
@(negedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic apb_write(input logic [11:0] offset_i, input logic [31:0] data_i,
|
||||
input logic [3:0] strobe_i, input logic expected_err_i);
|
||||
int unsigned s_wait_cycles;
|
||||
logic s_response_err;
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
apb4.paddr = ApuBase + offset_i;
|
||||
apb4.pwdata = data_i;
|
||||
apb4.pstrb = strobe_i;
|
||||
apb4.pwrite = 1'b1;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
#1;
|
||||
if (apb4.pready) $fatal(1, "APU PREADY asserted during write setup at %h", offset_i);
|
||||
@(negedge clk_i);
|
||||
apb4.penable = 1'b1;
|
||||
s_wait_cycles = 0;
|
||||
#1;
|
||||
while (!apb4.pready) begin
|
||||
s_wait_cycles++;
|
||||
if (s_wait_cycles > 4) $fatal(1, "APU write wait timeout at %h", offset_i);
|
||||
@(negedge clk_i);
|
||||
#1;
|
||||
end
|
||||
if (s_wait_cycles != 1) begin
|
||||
$fatal(1, "APU write wait count mismatch at %h: %0d", offset_i, s_wait_cycles);
|
||||
end
|
||||
if (apb4.pslverr != expected_err_i) $fatal(1, "APU write response mismatch at %h", offset_i);
|
||||
s_response_err = apb4.pslverr;
|
||||
#2;
|
||||
if (!apb4.pready || (apb4.pslverr != s_response_err)) begin
|
||||
$fatal(1, "APU write response was not retained through completion at %h", offset_i);
|
||||
end
|
||||
@(negedge clk_i);
|
||||
drive_apb_idle();
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic apb_read(input logic [11:0] offset_i, output logic [31:0] data_o,
|
||||
input logic expected_err_i);
|
||||
int unsigned s_wait_cycles;
|
||||
logic [31:0] s_response_data;
|
||||
logic s_response_err;
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
apb4.paddr = ApuBase + offset_i;
|
||||
apb4.pstrb = 4'd0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
#1;
|
||||
if (apb4.pready) $fatal(1, "APU PREADY asserted during read setup at %h", offset_i);
|
||||
@(negedge clk_i);
|
||||
apb4.penable = 1'b1;
|
||||
s_wait_cycles = 0;
|
||||
#1;
|
||||
while (!apb4.pready) begin
|
||||
s_wait_cycles++;
|
||||
if (s_wait_cycles > 4) $fatal(1, "APU read wait timeout at %h", offset_i);
|
||||
@(negedge clk_i);
|
||||
#1;
|
||||
end
|
||||
if (s_wait_cycles != 1) begin
|
||||
$fatal(1, "APU read wait count mismatch at %h: %0d", offset_i, s_wait_cycles);
|
||||
end
|
||||
if (apb4.pslverr != expected_err_i) $fatal(1, "APU read response mismatch at %h", offset_i);
|
||||
s_response_data = apb4.prdata;
|
||||
s_response_err = apb4.pslverr;
|
||||
#2;
|
||||
if (!apb4.pready || (apb4.prdata != s_response_data) ||
|
||||
(apb4.pslverr != s_response_err)) begin
|
||||
$fatal(1, "APU read response was not retained through completion at %h", offset_i);
|
||||
end
|
||||
data_o = s_response_data;
|
||||
@(negedge clk_i);
|
||||
drive_apb_idle();
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic expect_read(input logic [11:0] offset_i, input logic [31:0] expected_i);
|
||||
begin
|
||||
apb_read(offset_i, s_value, 1'b0);
|
||||
if (s_value != expected_i) begin
|
||||
$fatal(1, "APU read mismatch at %h: got %h expected %h", offset_i, s_value, expected_i);
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic program_rw_registers;
|
||||
begin
|
||||
for (int unsigned register_index = 0; register_index < RegisterCount; register_index++) begin
|
||||
if (s_reg_access[register_index] == AccessRw) begin
|
||||
apb_write(s_reg_offset[register_index], legal_write_value(s_reg_offset[register_index]),
|
||||
4'hf, 1'b0);
|
||||
end
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic check_reset_state(input logic preserve_acl_i);
|
||||
logic [31:0] s_expected;
|
||||
begin
|
||||
for (int unsigned register_index = 0; register_index < RegisterCount; register_index++) begin
|
||||
if (s_reg_access[register_index] != AccessWo) begin
|
||||
s_expected = preserve_acl_i ?
|
||||
reset_or_preserved_value(s_reg_offset[register_index], s_reg_reset[register_index]) :
|
||||
s_reg_reset[register_index];
|
||||
expect_read(s_reg_offset[register_index], s_expected);
|
||||
end
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic check_rejected_write(input logic [11:0] offset_i,
|
||||
input logic [31:0] rejected_value_i,
|
||||
input logic [5:0] error_code_i);
|
||||
logic [31:0] s_before;
|
||||
begin
|
||||
hard_reset();
|
||||
apb_write(`APB4_APU__SEQUENCER_TIMEOUT, 32'h1234_5678, 4'hf, 1'b0);
|
||||
if ((offset_i != `APB4_APU__COMMAND) && (offset_i != `APB4_APU__IRQ_TEST) &&
|
||||
(offset_i != `APB4_APU__RING_DOORBELL)) begin
|
||||
apb_read(offset_i, s_before, 1'b0);
|
||||
end else begin
|
||||
s_before = 32'd0;
|
||||
end
|
||||
apb_write(offset_i, rejected_value_i, 4'hf, 1'b1);
|
||||
expect_read(`APB4_APU__SEQUENCER_TIMEOUT, 32'h1234_5678);
|
||||
expect_read(`APB4_APU__ERROR_STATUS, 32'd1 | (32'(error_code_i) << 1));
|
||||
expect_read(`APB4_APU__ERROR_ADDRESS, ApuBase + offset_i);
|
||||
if ((offset_i != `APB4_APU__COMMAND) && (offset_i != `APB4_APU__IRQ_TEST) &&
|
||||
(offset_i != `APB4_APU__RING_DOORBELL) && (offset_i != `APB4_APU__IRQ_STATE) &&
|
||||
(offset_i != `APB4_APU__ERROR_STATUS) && (offset_i != `APB4_APU__ERROR_ADDRESS) &&
|
||||
(offset_i != `APB4_APU__ERROR_DETAIL)) begin
|
||||
expect_read(offset_i, s_before);
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
initialize_register_table();
|
||||
drive_apb_idle();
|
||||
hard_reset();
|
||||
if (!idle_o || irq_o) $fatal(1, "APU reset lifecycle outputs mismatch");
|
||||
|
||||
for (int unsigned register_index = 0; register_index < RegisterCount; register_index++) begin
|
||||
hard_reset();
|
||||
if (s_reg_access[register_index] == AccessWo) begin
|
||||
apb_read(s_reg_offset[register_index], s_value, 1'b1);
|
||||
end else begin
|
||||
expect_read(s_reg_offset[register_index], s_reg_reset[register_index]);
|
||||
end
|
||||
end
|
||||
|
||||
for (int unsigned register_index = 0; register_index < RegisterCount; register_index++) begin
|
||||
hard_reset();
|
||||
case (s_reg_access[register_index])
|
||||
AccessRo: begin
|
||||
apb_write(`APB4_APU__SEQUENCER_TIMEOUT, 32'h1234_5678, 4'hf, 1'b0);
|
||||
apb_write(s_reg_offset[register_index], 32'd0, 4'hf, 1'b1);
|
||||
expect_read(`APB4_APU__SEQUENCER_TIMEOUT, 32'h1234_5678);
|
||||
if ((s_reg_offset[register_index] != `APB4_APU__ERROR_ADDRESS) &&
|
||||
(s_reg_offset[register_index] != `APB4_APU__ERROR_DETAIL)) begin
|
||||
expect_read(s_reg_offset[register_index], s_reg_reset[register_index]);
|
||||
end
|
||||
end
|
||||
AccessWo: begin
|
||||
apb_read(s_reg_offset[register_index], s_value, 1'b1);
|
||||
hard_reset();
|
||||
if (s_reg_offset[register_index] == `APB4_APU__COMMAND) begin
|
||||
apb_write(s_reg_offset[register_index], 32'h0000_0004, 4'hf, 1'b0);
|
||||
end else if (s_reg_offset[register_index] == `APB4_APU__IRQ_TEST) begin
|
||||
apb_write(s_reg_offset[register_index], 32'd0, 4'hf, 1'b0);
|
||||
end else begin
|
||||
apb_write(s_reg_offset[register_index], 32'h0000_0001, 4'hf, 1'b1);
|
||||
end
|
||||
end
|
||||
AccessRw: begin
|
||||
apb_write(s_reg_offset[register_index], legal_write_value(s_reg_offset[register_index]),
|
||||
4'hf, 1'b0);
|
||||
expect_read(s_reg_offset[register_index], legal_readback_value(
|
||||
s_reg_offset[register_index]));
|
||||
end
|
||||
default: $fatal(1, "APU register table has invalid access class");
|
||||
endcase
|
||||
end
|
||||
|
||||
hard_reset();
|
||||
apb_write(`APB4_APU__SEQUENCER_TIMEOUT, 32'h0000_00aa, 4'h1, 1'b0);
|
||||
expect_read(`APB4_APU__SEQUENCER_TIMEOUT, 32'h0000_ffaa);
|
||||
apb_write(`APB4_APU__SEQUENCER_TIMEOUT, 32'h0000_bb00, 4'h2, 1'b0);
|
||||
expect_read(`APB4_APU__SEQUENCER_TIMEOUT, 32'h0000_bbaa);
|
||||
apb_write(`APB4_APU__SEQUENCER_TIMEOUT, 32'h00cc_0000, 4'h4, 1'b0);
|
||||
expect_read(`APB4_APU__SEQUENCER_TIMEOUT, 32'h00cc_bbaa);
|
||||
apb_write(`APB4_APU__SEQUENCER_TIMEOUT, 32'hdd00_0000, 4'h8, 1'b0);
|
||||
expect_read(`APB4_APU__SEQUENCER_TIMEOUT, 32'hddcc_bbaa);
|
||||
|
||||
for (int unsigned register_index = 0; register_index < RegisterCount; register_index++) begin
|
||||
if (s_reg_full_strobe[register_index]) begin
|
||||
hard_reset();
|
||||
apb_write(`APB4_APU__SEQUENCER_TIMEOUT, 32'h1234_5678, 4'hf, 1'b0);
|
||||
apb_write(s_reg_offset[register_index], legal_write_value(s_reg_offset[register_index]),
|
||||
4'h7, 1'b1);
|
||||
expect_read(`APB4_APU__SEQUENCER_TIMEOUT, 32'h1234_5678);
|
||||
if (s_reg_access[register_index] == AccessRw) begin
|
||||
expect_read(s_reg_offset[register_index], s_reg_reset[register_index]);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
check_rejected_write(`APB4_APU__COMMAND, 32'h0000_0080, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
for (int bit_index = 0; bit_index < 6; bit_index++) begin
|
||||
if ((bit_index != `APB4_APU__COMMAND_SOFT_RESET) &&
|
||||
(bit_index != `APB4_APU__COMMAND_CLEAR_COUNTERS)) begin
|
||||
check_rejected_write(`APB4_APU__COMMAND, 32'd1 << bit_index,
|
||||
`APB4_APU__ERROR_CODE_UNSUPPORTED);
|
||||
end
|
||||
end
|
||||
check_rejected_write(`APB4_APU__IRQ_STATE, 32'h0000_0800, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__IRQ_ENABLE, 32'h0000_0800,
|
||||
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__IRQ_TEST, 32'h0000_0800, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__ERROR_STATUS, 32'h0000_0002,
|
||||
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__SEQUENCER_TIMEOUT, 32'd0, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__STREAM_ROUTE, 32'h0000_0001, `APB4_APU__ERROR_CODE_UNSUPPORTED);
|
||||
check_rejected_write(`APB4_APU__STREAM_ROUTE, 32'h0000_0004, `APB4_APU__ERROR_CODE_UNSUPPORTED);
|
||||
check_rejected_write(`APB4_APU__DMA_TIMEOUT, 32'd0, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__MC_IMAGE_ADDRESS, 32'h3002_0001,
|
||||
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__MC_IMAGE_SIZE, 32'd0, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__JOB_CONTROL, 32'h8000_0000,
|
||||
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__JOB_INPUT_CONFIG, 32'h8000_0000,
|
||||
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__JOB_OUTPUT_CONFIG, 32'h8000_0000,
|
||||
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__JOB_FLAGS, 32'h0000_0002, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__RING_BASE, 32'h3004_0001, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__RING_SIZE, 32'h0000_0003, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__RING_TAIL, 32'h0000_0100, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__RING_CONTROL, 32'h0000_0004,
|
||||
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__RING_COALESCE, 32'd0, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__RING_DOORBELL, 32'h0000_0001,
|
||||
`APB4_APU__ERROR_CODE_UNSUPPORTED);
|
||||
check_rejected_write(`APB4_APU__KWS_MODEL_ADDRESS, 32'h3005_0001,
|
||||
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__KWS_MODEL_SIZE, 32'd0, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__KWS_CONTROL, 32'h0000_0001, `APB4_APU__ERROR_CODE_UNSUPPORTED);
|
||||
check_rejected_write(`APB4_APU__KWS_CONTROL, 32'h0000_0002, `APB4_APU__ERROR_CODE_UNSUPPORTED);
|
||||
check_rejected_write(`APB4_APU__KWS_CONTROL, 32'h0000_0008,
|
||||
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__KWS_CONFIG, 32'h0000_0080,
|
||||
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
check_rejected_write(`APB4_APU__PERF_CONTROL, 32'h0000_0008,
|
||||
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||
|
||||
hard_reset();
|
||||
apb_write(`APB4_APU__IRQ_TEST, 32'h0000_0001, 4'hf, 1'b0);
|
||||
force u_dut.u_apu_reg.s_irq_set = 11'h001;
|
||||
apb_write(`APB4_APU__IRQ_STATE, 32'h0000_0001, 4'h1, 1'b0);
|
||||
release u_dut.u_apu_reg.s_irq_set;
|
||||
expect_read(`APB4_APU__IRQ_STATE, 32'h0000_0001);
|
||||
apb_write(`APB4_APU__IRQ_STATE, 32'h0000_0001, 4'h1, 1'b0);
|
||||
expect_read(`APB4_APU__IRQ_STATE, 32'd0);
|
||||
|
||||
hard_reset();
|
||||
program_rw_registers();
|
||||
apb_write(`APB4_APU__COMMAND, 32'h0000_0004, 4'hf, 1'b0);
|
||||
check_reset_state(1'b1);
|
||||
|
||||
hard_reset();
|
||||
program_rw_registers();
|
||||
@(negedge clk_i);
|
||||
resource_reset_i = 1'b1;
|
||||
@(posedge clk_i);
|
||||
@(negedge clk_i);
|
||||
resource_reset_i = 1'b0;
|
||||
check_reset_state(1'b1);
|
||||
|
||||
hard_reset();
|
||||
owner_i = 2'd1;
|
||||
owner_lock_i = 1'b1;
|
||||
quiesce_i = 1'b1;
|
||||
expect_read(`APB4_APU__OWNER_STATUS, 32'h0000_0301);
|
||||
apb_read(12'h060, s_value, 1'b1);
|
||||
apb_read(12'h001, s_value, 1'b1);
|
||||
|
||||
$display("APU-P1 complete APB register matrix passed");
|
||||
$finish;
|
||||
end
|
||||
|
||||
initial begin
|
||||
repeat (20000) @(posedge clk_i);
|
||||
$fatal(1, "APU-P1 APB register matrix timed out");
|
||||
end
|
||||
endmodule
|
||||
@@ -180,6 +180,41 @@ module axi4_interconnect_tb;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic issue_hp_apu_write(input logic [31:0] address, input logic [1:0] expected_response,
|
||||
input logic expected_access_fault);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
masters[6].awaddr = address;
|
||||
masters[6].awlen = 8'd0;
|
||||
masters[6].awvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!masters[6].awready);
|
||||
@(negedge clk_i);
|
||||
masters[6].awvalid = 1'b0;
|
||||
masters[6].wdata = 32'h1234_5678;
|
||||
masters[6].wstrb = 4'hf;
|
||||
masters[6].wlast = 1'b1;
|
||||
masters[6].wvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!masters[6].wready);
|
||||
@(negedge clk_i);
|
||||
masters[6].wvalid = 1'b0;
|
||||
masters[6].bready = 1'b1;
|
||||
while (!masters[6].bvalid) @(negedge clk_i);
|
||||
#1;
|
||||
if ((masters[6].bresp != expected_response) ||
|
||||
(fault_valid_o != expected_access_fault) ||
|
||||
(expected_access_fault &&
|
||||
(!fault_access_o || (fault_addr_o != address) || (fault_master_o != 3'd6) ||
|
||||
(fault_code_o != `RIB_RESP_PROTERR)))) begin
|
||||
$fatal(
|
||||
1,
|
||||
"HP APU access policy mismatch at %h: resp=%0d fault=%0d access=%0d master=%0d code=%0d",
|
||||
address, masters[6].bresp, fault_valid_o, fault_access_o, fault_master_o, fault_code_o);
|
||||
end
|
||||
@(negedge clk_i);
|
||||
masters[6].bready = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic issue_management_with_idle_sdio;
|
||||
integer cycles;
|
||||
begin
|
||||
@@ -347,7 +382,12 @@ module axi4_interconnect_tb;
|
||||
issue_management_with_idle_sdio();
|
||||
issue_mgmt_error_read(32'hA000_0000, 8'd0, `AXI4_RESP_DECODE_ERROR, `RIB_RESP_DECERR);
|
||||
issue_mgmt_error_read(32'h3000_0000, 8'd16, `AXI4_RESP_SLAVE_ERROR, `RIB_RESP_BURSTERR);
|
||||
`ifdef MINI_PRODUCT
|
||||
issue_hp_apu_write(32'h1001_301C, `AXI4_RESP_OKAY, 1'b0);
|
||||
issue_hp_apu_write(32'h1001_3040, `AXI4_RESP_SLAVE_ERROR, 1'b1);
|
||||
`else
|
||||
issue_denied_user_write(32'h1000_B000);
|
||||
`endif
|
||||
issue_contending_sdio_faults();
|
||||
issue_hp_accesses();
|
||||
|
||||
|
||||
@@ -3,16 +3,17 @@
|
||||
module resource_controller_tb;
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
logic [ 5:0] idle_i = '0;
|
||||
logic [ 5:0] block_ack_i = '0;
|
||||
logic [ 5:0] irq_i = '0;
|
||||
logic [ 7:0] idle_i = '0;
|
||||
logic [ 7:0] block_ack_i = '0;
|
||||
logic [ 7:0] irq_i = '0;
|
||||
logic cache_request_i = 1'b0;
|
||||
logic cache_clean_o;
|
||||
logic [ 5:0][1:0] owner_o;
|
||||
logic [ 5:0] quiesce_o;
|
||||
logic [ 5:0] reset_o;
|
||||
logic [ 5:0] irq_lp_o;
|
||||
logic [ 5:0] irq_hp_o;
|
||||
logic [ 7:0][1:0] owner_o;
|
||||
logic [ 7:0] owner_lock_o;
|
||||
logic [ 7:0] quiesce_o;
|
||||
logic [ 7:0] reset_o;
|
||||
logic [ 7:0] irq_lp_o;
|
||||
logic [ 7:0] irq_hp_o;
|
||||
logic fault_irq_o;
|
||||
logic [31:0] read_data;
|
||||
|
||||
@@ -32,6 +33,7 @@ module resource_controller_tb;
|
||||
.cache_request_i(cache_request_i),
|
||||
.cache_clean_o (cache_clean_o),
|
||||
.owner_o (owner_o),
|
||||
.owner_lock_o (owner_lock_o),
|
||||
.quiesce_o (quiesce_o),
|
||||
.reset_o (reset_o),
|
||||
.irq_lp_o (irq_lp_o),
|
||||
@@ -90,7 +92,7 @@ module resource_controller_tb;
|
||||
|
||||
repeat (3) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
idle_i = 6'h3F;
|
||||
idle_i = 8'hFF;
|
||||
|
||||
apb_read(12'h000, read_data);
|
||||
if (read_data != 32'h5253_4354) $fatal(1, "resource controller ID mismatch");
|
||||
@@ -135,6 +137,16 @@ module resource_controller_tb;
|
||||
$fatal(1, "resource lifecycle controls did not update");
|
||||
end
|
||||
|
||||
irq_i[7] = 1'b1;
|
||||
#1;
|
||||
if (!irq_lp_o[7] || irq_hp_o[7]) $fatal(1, "APU reset owner routing mismatch");
|
||||
block_ack_i[7] = 1'b1;
|
||||
apb_write(12'h1E4, 32'h0000_0001, 1'b0);
|
||||
apb_write(12'h1E0, 32'h0000_0101, 1'b0);
|
||||
if ((owner_o[7] != 2'd1) || !owner_lock_o[7] || irq_lp_o[7] || !irq_hp_o[7]) begin
|
||||
$fatal(1, "APU resource index 7 ownership or IRQ routing mismatch");
|
||||
end
|
||||
|
||||
$display("Resource Controller ownership, IRQ, and cache handshake test passed");
|
||||
$finish;
|
||||
end
|
||||
|
||||
@@ -43,6 +43,7 @@ module soc_irq_topology_tb;
|
||||
20: expect_irq(32'd1 << 25);
|
||||
21: expect_irq(32'd1 << 26);
|
||||
22: expect_irq(32'd1 << 30);
|
||||
23: expect_irq(32'd1 << 31);
|
||||
default: expect_irq(32'd1 << (bit_index + 7));
|
||||
endcase
|
||||
end
|
||||
@@ -70,7 +71,7 @@ module soc_irq_topology_tb;
|
||||
$fatal(1, "SDIO core IRQ bits are not low when sources are low: IRQ10=%b IRQ21=%b",
|
||||
s_irq[10], s_irq[21]);
|
||||
end
|
||||
if ((s_irq[31] !== 1'b0) || (s_irq[19:18] !== '0)) begin
|
||||
if (s_irq[19:18] !== '0) begin
|
||||
$fatal(1, "unallocated core IRQ bits are not low: %h", s_irq);
|
||||
end
|
||||
|
||||
|
||||
Reference in new issue
Block a user