Skip to content

Commit

Permalink
axi_mcast_xbar: Extend testbench to test multiple rules per slave
Browse files Browse the repository at this point in the history
  • Loading branch information
colluca committed Apr 26, 2023
1 parent 9a2cb6b commit 1f9f9ce
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 33 deletions.
20 changes: 12 additions & 8 deletions test/tb_axi_mcast_xbar.sv
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ module tb_axi_mcast_xbar #(
UniqueIds: TbUniqueIds,
AxiAddrWidth: TbAxiAddrWidth,
AxiDataWidth: TbAxiDataWidth,
NoAddrRules: TbNumSlaves,
NoMulticastRules: TbNumSlaves,
NoAddrRules: TbNumSlaves * 2,
NoMulticastRules: TbNumSlaves * 2,
NoMulticastPorts: TbNumSlaves
};
typedef logic [TbAxiIdWidthMasters-1:0] id_mst_t;
Expand Down Expand Up @@ -108,14 +108,15 @@ module tb_axi_mcast_xbar #(
`AXI_TYPEDEF_RESP_T(slv_resp_t, b_chan_slv_t, r_chan_slv_t)

// Each slave has its own address range:
localparam rule_t [xbar_cfg.NoAddrRules-1:0] AddrMap = addr_map_gen();
localparam rule_t [xbar_cfg.NoAddrRules-1:0] AddrMap = {addr_map_gen(32'h1000_0000, 32'h10_0000),
addr_map_gen(32'h0b00_0000, 32'h1_0000)};

function rule_t [xbar_cfg.NoAddrRules-1:0] addr_map_gen ();
for (int unsigned i = 0; i < xbar_cfg.NoAddrRules; i++) begin
function rule_t [xbar_cfg.NoMstPorts-1:0] addr_map_gen (addr_t base, addr_t offset);
for (int unsigned i = 0; i < xbar_cfg.NoMstPorts; i++) begin
addr_map_gen[i] = rule_t'{
idx: unsigned'(i),
start_addr: i * 32'h0000_2000,
end_addr: (i+1) * 32'h0000_2000,
start_addr: base + offset * i,
end_addr: base + offset * (i + 1),
default: '0
};
end
Expand Down Expand Up @@ -225,9 +226,12 @@ module tb_axi_mcast_xbar #(
axi_rand_master[i] = new( master_dv[i] );
end_of_sim[i] <= 1'b0;
axi_rand_master[i].add_memory_region(AddrMap[0].start_addr,
AddrMap[xbar_cfg.NoMstPorts-1].end_addr,
axi_pkg::DEVICE_NONBUFFERABLE);
axi_rand_master[i].add_memory_region(AddrMap[xbar_cfg.NoMstPorts].start_addr,
AddrMap[xbar_cfg.NoAddrRules-1].end_addr,
axi_pkg::DEVICE_NONBUFFERABLE);
axi_rand_master[i].set_multicast_probability(0.5);
axi_rand_master[i].set_multicast_probability(50);
axi_rand_master[i].reset();
@(posedge rst_n);
axi_rand_master[i].run(TbNumReads, TbNumWrites);
Expand Down
67 changes: 42 additions & 25 deletions test/tb_axi_mcast_xbar_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -155,20 +155,21 @@ package tb_axi_mcast_xbar_pkg;
// populates the expected b response in its own id_queue and in case the atomic bit [5]
// is set it also injects an expected response in the R channel.
task automatic monitor_mst_aw(input int unsigned i);
axi_addr_t aw_addr;
axi_addr_t aw_mcast;
axi_addr_t rule_addr;
axi_addr_t rule_mask;
axi_addr_t aw_addr_masked;
axi_addr_t addrmap_masked;
idx_slv_t to_slave_idx[$];
int unsigned num_slaves_matched;
axi_addr_t addr_to_slave[$];
axi_addr_t mask_to_slave[$];
bit decerr;
exp_ax_t exp_aw;
slv_axi_id_t exp_aw_id;
string slaves_str;
axi_addr_t aw_addr;
axi_addr_t aw_mcast;
axi_addr_t rule_addr;
axi_addr_t rule_mask;
axi_addr_t aw_addr_masked;
axi_addr_t addrmap_masked;
idx_slv_t to_slave_idx[$];
axi_addr_t addr_to_slave[$];
axi_addr_t mask_to_slave[$];
bit [NoSlaves-1:0] matched_slaves;
int unsigned num_slaves_matched;
bit decerr;
exp_ax_t exp_aw;
slv_axi_id_t exp_aw_id;
string slaves_str;

master_exp_t exp_b;

Expand All @@ -180,29 +181,45 @@ package tb_axi_mcast_xbar_pkg;

// Check to which slaves the transaction is directed or if it should go to a decerror.
// Store the indices of the selected slaves (to_slave_idx) and the filtered address
// sets {addr, mask} to be forwarded to each slave (addr_to_slave, mask_to_slave).
// sets {addr, mask} to be forwarded to each slave (addr_queue, mask_queue).

// Get address information from request
aw_addr = masters_axi[i].aw_addr;
aw_mcast = masters_axi[i].aw_user[AxiAddrWidth-1:0];
for (int k = 0; k < AxiAddrWidth; k++)
aw_addr_masked[k] = aw_mcast[k] ? 1'bx : aw_addr[k];
$display("Trying to match: %b", aw_addr_masked);
for (int unsigned j = 0; j < NoAddrRules; j++) begin
// convert rule to mask (NAPOT) form
rule_mask = {'0, {$clog2(AddrMap[j].end_addr - AddrMap[j].start_addr){1'b1}}};

// Compare request against each address rule. We look at the rules starting from the
// last ones. In case of multiple rules matching for the same slave, we want only
// the last rule to have effect
for (int j = (NoAddrRules - 1); j >= 0; j--) begin

// Convert address rule to mask (NAPOT) form
rule_mask = AddrMap[j].end_addr - AddrMap[j].start_addr - 1;
rule_addr = AddrMap[j].start_addr;
// request goes to the slave if all bits match, out of those which are neither masked
// in the request nor in the addrmap rule
for (int k = 0; k < AxiAddrWidth; k++)
addrmap_masked[k] = rule_mask[k] ? 1'bx : rule_addr[k];
$display("With slave %3d : %b", AddrMap[j].idx, addrmap_masked);

// Request goes to the slave if all bits match, out of those which are neither masked
// in the request nor in the addrmap rule
if (&(~(aw_addr ^ rule_addr) | rule_mask | aw_mcast)) begin
to_slave_idx.push_back(AddrMap[j].idx);
mask_to_slave.push_back(aw_mcast & rule_mask);
addr_to_slave.push_back((~aw_mcast & aw_addr) | (aw_mcast & rule_addr));
$display(" Push mask : %b", aw_mcast & rule_mask);
$display(" Push address : %b", (~aw_mcast & aw_addr) | (aw_mcast & rule_addr));
int unsigned slave_idx = AddrMap[j].idx;

// Only push the request if we haven't already matched it with a previous rule
// for the same slave
if (!matched_slaves[slave_idx]) begin
matched_slaves[slave_idx] = 1'b1;
to_slave_idx.push_back(slave_idx);
mask_to_slave.push_back(aw_mcast & rule_mask);
addr_to_slave.push_back((~aw_mcast & aw_addr) | (aw_mcast & rule_addr));
$display(" Push mask : %32b", aw_mcast & rule_mask);
$display(" Push address : %32b", (~aw_mcast & aw_addr) | (aw_mcast & rule_addr));
end
end
end

num_slaves_matched = to_slave_idx.size();
decerr = num_slaves_matched == 0;

Expand Down

0 comments on commit 1f9f9ce

Please sign in to comment.