feate: add fabric monitor and enhance AXI4 data crossbar tests

- Introduced  and its corresponding testbench  to monitor fabric interactions.
- Updated  to include additional checks for ACL and QoS, enhancing the test coverage.
- Modified  to include the new fabric monitor file.
- Created a new test file  to validate the functionality of the fabric monitor.
- Updated  to integrate the fabric monitor interface.
- Adjusted  to reflect changes in the AXI4 data crossbar test output.
- Enhanced  to ensure proper generation of connections for the fabric monitor.
- Updated user extension tests to account for new local SRAM and stream definitions.
This commit is contained in:
maksyuki committed 2026-08-31 10:02:19 +08:00
1 parent 62d112c4e6
commit d164a562ad
46 files changed
+2443 -1375

No files matched your search

+162 -24
View File
@@ -17,6 +17,8 @@ module axi4_data_crossbar_tb;
logic [31:0] fault_addr_o;
logic fault_write_o;
logic [ 3:0] fault_reason_o;
logic recovery_i = 1'b0;
logic [ 7:0] monitor_master_promotion_o;
axi4_if #(
.ADDR_WIDTH(32),
@@ -44,29 +46,36 @@ module axi4_data_crossbar_tb;
$fatal(1, "AXI4 data crossbar test timed out");
end
axi4_data_crossbar u_dut (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.block_new_i (1'b0),
.master_block_i (master_block_i),
.recovery_i (1'b0),
.mem_pad_mode_i (2'd1),
.ext_h_read_base_i (32'h3000_0000),
.ext_h_read_limit_i (32'h4FFF_FFFF),
.ext_h_write_base_i (32'h3000_0000),
.ext_h_write_limit_i(32'h4FFF_FFFF),
.masters (masters),
.targets (targets),
.idle_o (idle_o),
.master_idle_o (master_idle_o),
.outstanding_read_o (outstanding_read_o),
.outstanding_write_o(outstanding_write_o),
.fault_valid_o (fault_valid_o),
.fault_master_o (fault_master_o),
.fault_target_o (fault_target_o),
.fault_addr_o (fault_addr_o),
.fault_write_o (fault_write_o),
.fault_reason_o (fault_reason_o)
axi4_data_crossbar #(
.StarvationCycles (4),
.ReadTargetMask (40'b1111100000111111111111111111111111111111),
.WriteTargetMask (40'b0111100000011110111101111011110111100000),
.AllowInstruction (8'b00000001),
.RequireNoncacheable(8'b11111100)
) u_dut (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.block_new_i (1'b0),
.master_block_i (master_block_i),
.recovery_i (recovery_i),
.mem_pad_mode_i (2'd1),
.ext_h_read_base_i (32'h3000_0000),
.ext_h_read_limit_i (32'h4FFF_FFFF),
.ext_h_write_base_i (32'h3000_0000),
.ext_h_write_limit_i (32'h4FFF_FFFF),
.masters (masters),
.targets (targets),
.idle_o (idle_o),
.master_idle_o (master_idle_o),
.outstanding_read_o (outstanding_read_o),
.outstanding_write_o (outstanding_write_o),
.fault_valid_o (fault_valid_o),
.fault_master_o (fault_master_o),
.fault_target_o (fault_target_o),
.fault_addr_o (fault_addr_o),
.fault_write_o (fault_write_o),
.fault_reason_o (fault_reason_o),
.monitor_master_promotion_o(monitor_master_promotion_o)
);
task automatic issue_master1_read(input logic [5:0] id, input logic [31:0] addr);
@@ -109,6 +118,19 @@ module axi4_data_crossbar_tb;
end
endtask
task automatic return_target5_read(input logic [5:0] id);
begin
@(negedge clk_i);
targets[5].rid = id;
targets[5].rresp = 2'b10;
targets[5].rlast = 1'b1;
targets[5].rvalid = 1'b1;
do @(posedge clk_i); while (!targets[5].rready);
@(negedge clk_i);
targets[5].rvalid = 1'b0;
end
endtask
`define INIT_MASTER(index) \
masters[index].awid = '0; \
masters[index].awaddr = '0; \
@@ -266,7 +288,123 @@ module axi4_data_crossbar_tb;
@(negedge clk_i);
targets[5].rvalid = 1'b0;
$display("AXI4 data crossbar concurrency and ACL test passed");
@(negedge clk_i);
masters[2].arid = 6'b010_001;
masters[2].araddr = 32'h3000_0000;
masters[2].arcache = 4'b0011;
masters[2].arvalid = 1'b1;
do @(posedge clk_i); while (!masters[2].arready);
#1;
if (!fault_valid_o || (fault_master_o != 3'd2) || (fault_reason_o != 4'd3)) begin
$fatal(1, "cache-attribute ACL fault attribution mismatch");
end
@(negedge clk_i);
masters[2].arvalid = 1'b0;
masters[2].arcache = 4'd0;
return_target5_read(6'b010_001);
@(negedge clk_i);
masters[1].arid = 6'b001_100;
masters[1].araddr = 32'h3000_0000;
masters[1].arprot = 3'b100;
masters[1].arvalid = 1'b1;
do @(posedge clk_i); while (!masters[1].arready);
#1;
if (!fault_valid_o || (fault_master_o != 3'd1) || (fault_reason_o != 4'd3)) begin
$fatal(1, "instruction ACL fault attribution mismatch");
end
@(negedge clk_i);
masters[1].arvalid = 1'b0;
masters[1].arprot = 3'd0;
return_target5_read(6'b001_100);
@(negedge clk_i);
masters[1].awid = 6'b001_101;
masters[1].awaddr = 32'h5000_0000;
masters[1].awvalid = 1'b1;
do @(posedge clk_i); while (!masters[1].awready);
#1;
if (!fault_valid_o || (fault_master_o != 3'd1) || (fault_reason_o != 4'd3) ||
!fault_write_o) begin
$fatal(1, "write-target ACL fault attribution mismatch");
end
@(negedge clk_i);
masters[1].awvalid = 1'b0;
masters[1].wdata = 64'hA5A5_5A5A_1122_3344;
masters[1].wstrb = 8'hFF;
masters[1].wvalid = 1'b1;
do @(posedge clk_i); while (!masters[1].wready);
@(negedge clk_i);
masters[1].wvalid = 1'b0;
targets[5].bid = 6'b001_101;
targets[5].bresp = 2'b10;
targets[5].bvalid = 1'b1;
do @(posedge clk_i); while (!targets[5].bready);
@(negedge clk_i);
targets[5].bvalid = 1'b0;
target0_recovery_priority : begin
@(negedge clk_i);
recovery_i = 1'b1;
targets[0].arready = 1'b0;
masters[0].arid = 6'b000_100;
masters[0].araddr = 32'h3000_0100;
masters[0].arvalid = 1'b1;
masters[5].arid = 6'b101_000;
masters[5].araddr = 32'h3000_0180;
masters[5].arvalid = 1'b1;
#1;
if (!targets[0].arvalid || (targets[0].arid != 6'b101_000)) begin
$fatal(1, "recovery master did not receive emergency priority");
end
targets[0].arready = 1'b1;
do @(posedge clk_i); while (!masters[5].arready);
@(negedge clk_i);
masters[5].arvalid = 1'b0;
do @(posedge clk_i); while (!masters[0].arready);
@(negedge clk_i);
masters[0].arvalid = 1'b0;
recovery_i = 1'b0;
return_target0_read(6'b101_000, 64'h5555_5555_5555_5555);
return_target0_read(6'b000_100, 64'h0000_0000_0000_0100);
end
target0_starvation_bound : begin
@(negedge clk_i);
targets[0].arready = 1'b0;
masters[5].arid = 6'b101_001;
masters[5].araddr = 32'h3000_0200;
masters[5].arvalid = 1'b1;
repeat (4) @(posedge clk_i);
@(negedge clk_i);
masters[0].arid = 6'b000_101;
masters[0].araddr = 32'h3000_0280;
masters[0].arvalid = 1'b1;
#1;
if (!targets[0].arvalid || (targets[0].arid != 6'b101_001)) begin
$fatal(1, "aged LP request did not override a newer latency request");
end
targets[0].arready = 1'b1;
#1;
if (!monitor_master_promotion_o[5]) begin
$fatal(1, "aged LP service was not reported as a promotion");
end
do @(posedge clk_i); while (!masters[5].arready);
@(negedge clk_i);
masters[5].arvalid = 1'b0;
do @(posedge clk_i); while (!masters[0].arready);
@(negedge clk_i);
masters[0].arvalid = 1'b0;
return_target0_read(6'b101_001, 64'h5555_5555_0000_0200);
return_target0_read(6'b000_101, 64'h0000_0000_0000_0280);
end
@(negedge clk_i);
if (!idle_o || (outstanding_read_o != 8'd0) || (outstanding_write_o != 8'd0)) begin
$fatal(1, "ACL and QoS transactions did not drain the crossbar");
end
$display("AXI4 data crossbar concurrency, ACL, and QoS test passed");
$finish;
end
+189
View File
@@ -0,0 +1,189 @@
`timescale 1ns / 1ps
module fabric_monitor_tb;
logic clk_i = 1'b0;
logic rst_n_i = 1'b0;
logic [ 7:0] master_read_accept_i = '0;
logic [ 7:0] master_write_accept_i = '0;
logic [ 7:0] master_read_beat_i = '0;
logic [ 7:0] master_write_beat_i = '0;
logic [ 7:0] master_wait_i = '0;
logic [ 7:0] master_promotion_i = '0;
logic [ 7:0][2:0] master_read_outstanding_i = '0;
logic [ 7:0][2:0] master_write_outstanding_i = '0;
logic [ 5:0] target_read_accept_i = '0;
logic [ 5:0] target_write_accept_i = '0;
logic [ 5:0] target_read_beat_i = '0;
logic [ 5:0] target_write_beat_i = '0;
logic [ 5:0] target_wait_i = '0;
logic [ 5:0] target_timeout_i = '0;
logic [ 5:0] target_isolated_i = '0;
logic [ 5:0][2:0] target_read_outstanding_i = '0;
logic [ 5:0][2:0] target_write_outstanding_i = '0;
logic fault_valid_i = 1'b0;
logic [31:0] read_data;
apb4_if apb4 (
.pclk (clk_i),
.presetn(rst_n_i)
);
always #5 clk_i = ~clk_i;
fabric_monitor u_dut (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.idle_i (1'b0),
.recovery_i (1'b1),
.flush_busy_i (1'b0),
.flush_i (target_timeout_i[5]),
.outstanding_read_i (8'd2),
.outstanding_write_i (8'd1),
.fault_valid_i (fault_valid_i),
.fault_master_i (3'd5),
.fault_target_i (3'd2),
.fault_addr_i (32'h4000_0040),
.fault_write_i (1'b1),
.fault_reason_i (4'd5),
.master_read_accept_i (master_read_accept_i),
.master_write_accept_i (master_write_accept_i),
.master_read_beat_i (master_read_beat_i),
.master_write_beat_i (master_write_beat_i),
.master_wait_i (master_wait_i),
.master_promotion_i (master_promotion_i),
.master_read_outstanding_i (master_read_outstanding_i),
.master_write_outstanding_i(master_write_outstanding_i),
.target_read_accept_i (target_read_accept_i),
.target_write_accept_i (target_write_accept_i),
.target_read_beat_i (target_read_beat_i),
.target_write_beat_i (target_write_beat_i),
.target_wait_i (target_wait_i),
.target_timeout_i (target_timeout_i),
.target_isolated_i (target_isolated_i),
.target_read_outstanding_i (target_read_outstanding_i),
.target_write_outstanding_i(target_write_outstanding_i),
.apb4 (apb4)
);
task automatic apb_write(input logic [11:0] offset, input logic [31:0] data);
begin
@(negedge clk_i);
apb4.paddr = {20'd0, offset};
apb4.pwrite = 1'b1;
apb4.pwdata = data;
apb4.pstrb = 4'hF;
apb4.psel = 1'b1;
apb4.penable = 1'b1;
do @(posedge clk_i); while (!apb4.pready);
if (apb4.pslverr) $fatal(1, "fabric monitor write failed at %h", offset);
@(negedge clk_i);
apb4.psel = 1'b0;
apb4.penable = 1'b0;
apb4.pwrite = 1'b0;
apb4.pstrb = '0;
end
endtask
task automatic apb_read(input logic [11:0] offset, output logic [31:0] data);
begin
@(negedge clk_i);
apb4.paddr = {20'd0, offset};
apb4.pwrite = 1'b0;
apb4.pstrb = '0;
apb4.psel = 1'b1;
apb4.penable = 1'b1;
do @(posedge clk_i); while (!apb4.pready);
if (apb4.pslverr) $fatal(1, "fabric monitor read failed at %h", offset);
data = apb4.prdata;
@(negedge clk_i);
apb4.psel = 1'b0;
apb4.penable = 1'b0;
end
endtask
initial begin
apb4.paddr = '0;
apb4.pprot = '0;
apb4.psel = 1'b0;
apb4.penable = 1'b0;
apb4.pwrite = 1'b0;
apb4.pwdata = '0;
apb4.pstrb = '0;
repeat (3) @(posedge clk_i);
rst_n_i = 1'b1;
apb_write(12'h00C, 32'h0000_0001);
@(negedge clk_i);
master_read_accept_i[0] = 1'b1;
master_read_beat_i[0] = 1'b1;
master_promotion_i[0] = 1'b1;
master_read_outstanding_i[0] = 3'd3;
target_read_accept_i[2] = 1'b1;
target_read_beat_i[2] = 1'b1;
target_read_outstanding_i[2] = 3'd2;
@(negedge clk_i);
master_read_accept_i = '0;
master_read_beat_i = '0;
master_promotion_i = '0;
target_read_accept_i = '0;
target_read_beat_i = '0;
repeat (3) begin
master_wait_i[0] = 1'b1;
target_wait_i[2] = 1'b1;
@(negedge clk_i);
end
master_wait_i = '0;
target_wait_i = '0;
target_timeout_i[2] = 1'b1;
target_isolated_i[2] = 1'b1;
fault_valid_i = 1'b1;
@(negedge clk_i);
target_timeout_i[2] = 1'b0;
fault_valid_i = 1'b0;
target_timeout_i[5] = 1'b1;
@(negedge clk_i);
target_timeout_i[5] = 1'b0;
apb_write(12'h00C, 32'h0000_0009);
apb_read(12'h100, read_data);
if (read_data != 32'd1) $fatal(1, "master read request count mismatch");
apb_read(12'h110, read_data);
if (read_data != 32'd3) $fatal(1, "master wait count mismatch");
apb_read(12'h114, read_data);
if (read_data != 32'd3) $fatal(1, "master max wait mismatch");
apb_read(12'h118, read_data);
if (read_data != 32'd1) $fatal(1, "master promotion count mismatch");
apb_read(12'h11C, read_data);
if (read_data[2:0] != 3'd3) $fatal(1, "master high-water mismatch");
apb_read(12'h340, read_data);
if (read_data != 32'd1) $fatal(1, "target read request count mismatch");
apb_read(12'h350, read_data);
if (read_data != 32'd3) $fatal(1, "target wait count mismatch");
apb_read(12'h354, read_data);
if (read_data != 32'd1) $fatal(1, "target timeout count mismatch");
apb_read(12'h358, read_data);
if (read_data != 32'd1) $fatal(1, "target isolation mismatch");
apb_read(12'h01C, read_data);
if (read_data != 32'd1) $fatal(1, "flush count mismatch");
apb_read(12'h018, read_data);
if (read_data != 32'h4000_0040) $fatal(1, "fault address mismatch");
apb_read(12'h014, read_data);
if (read_data != 32'h0000_0557) $fatal(1, "sticky fault attribution mismatch");
apb_read(12'h020, read_data);
if (read_data != 32'd1) $fatal(1, "fault count mismatch");
apb_write(12'h00C, 32'h0000_0005);
apb_read(12'h100, read_data);
if (read_data != 32'd0) $fatal(1, "snapshot did not clear");
apb_read(12'h014, read_data);
if (read_data != 32'd0) $fatal(1, "sticky fault did not clear");
$display("Fabric Monitor counter, snapshot, and clear test passed");
$finish;
end
initial begin
repeat (400) @(posedge clk_i);
$fatal(1, "Fabric Monitor test timed out");
end
endmodule
+52 -47
View File
@@ -21,58 +21,63 @@ module rib2apb_tb;
apb4_pure_if ext_l ();
apb4_pure_if ext_h ();
apb4_pure_if resource_ctrl ();
apb4_pure_if fabric_monitor ();
always #5 clk_i = ~clk_i;
assign archinfo.pready = 1'b0;
assign archinfo.prdata = '0;
assign archinfo.pslverr = 1'b0;
assign rng.pready = rng_ready;
assign rng.prdata = rng_rdata;
assign rng.pslverr = rng_slverr;
assign pwm.pready = 1'b0;
assign pwm.prdata = '0;
assign pwm.pslverr = 1'b0;
assign ps2.pready = 1'b0;
assign ps2.prdata = '0;
assign ps2.pslverr = 1'b0;
assign rtc.pready = 1'b0;
assign rtc.prdata = '0;
assign rtc.pslverr = 1'b0;
assign wdg.pready = 1'b0;
assign wdg.prdata = '0;
assign wdg.pslverr = 1'b0;
assign crc.pready = 1'b0;
assign crc.prdata = '0;
assign crc.pslverr = 1'b0;
assign user_ip.pready = 1'b0;
assign user_ip.prdata = '0;
assign user_ip.pslverr = 1'b0;
assign ext_l.pready = 1'b0;
assign ext_l.prdata = '0;
assign ext_l.pslverr = 1'b0;
assign ext_h.pready = 1'b0;
assign ext_h.prdata = '0;
assign ext_h.pslverr = 1'b0;
assign resource_ctrl.pready = 1'b0;
assign resource_ctrl.prdata = '0;
assign resource_ctrl.pslverr = 1'b0;
assign archinfo.pready = 1'b0;
assign archinfo.prdata = '0;
assign archinfo.pslverr = 1'b0;
assign rng.pready = rng_ready;
assign rng.prdata = rng_rdata;
assign rng.pslverr = rng_slverr;
assign pwm.pready = 1'b0;
assign pwm.prdata = '0;
assign pwm.pslverr = 1'b0;
assign ps2.pready = 1'b0;
assign ps2.prdata = '0;
assign ps2.pslverr = 1'b0;
assign rtc.pready = 1'b0;
assign rtc.prdata = '0;
assign rtc.pslverr = 1'b0;
assign wdg.pready = 1'b0;
assign wdg.prdata = '0;
assign wdg.pslverr = 1'b0;
assign crc.pready = 1'b0;
assign crc.prdata = '0;
assign crc.pslverr = 1'b0;
assign user_ip.pready = 1'b0;
assign user_ip.prdata = '0;
assign user_ip.pslverr = 1'b0;
assign ext_l.pready = 1'b0;
assign ext_l.prdata = '0;
assign ext_l.pslverr = 1'b0;
assign ext_h.pready = 1'b0;
assign ext_h.prdata = '0;
assign ext_h.pslverr = 1'b0;
assign resource_ctrl.pready = 1'b0;
assign resource_ctrl.prdata = '0;
assign resource_ctrl.pslverr = 1'b0;
assign fabric_monitor.pready = 1'b0;
assign fabric_monitor.prdata = '0;
assign fabric_monitor.pslverr = 1'b0;
rib2apb u_rib2apb (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.rib (rib),
.archinfo (archinfo),
.rng (rng),
.pwm (pwm),
.ps2 (ps2),
.rtc (rtc),
.wdg (wdg),
.crc (crc),
.user_ip (user_ip),
.ext_l (ext_l),
.ext_h (ext_h),
.resource_ctrl(resource_ctrl)
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.rib (rib),
.archinfo (archinfo),
.rng (rng),
.pwm (pwm),
.ps2 (ps2),
.rtc (rtc),
.wdg (wdg),
.crc (crc),
.user_ip (user_ip),
.ext_l (ext_l),
.ext_h (ext_h),
.resource_ctrl (resource_ctrl),
.fabric_monitor(fabric_monitor)
);
task automatic send_command(input logic [31:0] address, input logic write,