Skip to content

Commit 042a029

Browse files
robertszczepanskitmichalak
authored andcommitted
Add initial AXI bus stress tests
1 parent 676fc8e commit 042a029

File tree

4 files changed

+207
-3
lines changed

4 files changed

+207
-3
lines changed

verification/cocotb/block/axi_adapter/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ MODULE ?= $(subst $(space),$(comma),$(subst .py,,$(TEST_FILES)))
1616
TOPLEVEL = axi_adapter_wrapper
1717

1818
VERILOG_SOURCES = \
19+
$(CALIPTRA_ROOT)/src/caliptra_prim/rtl/caliptra_prim_pkg.sv \
20+
$(CALIPTRA_ROOT)/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv \
1921
$(SRC_DIR)/i3c_pkg.sv \
2022
$(SRC_DIR)/libs/axi/axi_pkg.sv \
2123
$(SRC_DIR)/libs/axi/axi_if.sv \

verification/cocotb/block/axi_adapter/axi_adapter_wrapper.sv

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ module axi_adapter_wrapper
5858
output logic [ 1:0] bresp,
5959
output logic [AxiIdWidth-1:0] bid,
6060
output logic bvalid,
61-
input logic bready
61+
input logic bready,
62+
63+
output logic [ 6:0] fifo_depth_o
6264
);
6365
// I3C SW CSR access interface
6466
logic s_cpuif_req;
@@ -164,6 +166,35 @@ module axi_adapter_wrapper
164166
.hwif_out(hwif_out)
165167
);
166168

169+
logic fifo_wvalid;
170+
logic fifo_wready;
171+
logic [31:0] fifo_wdata;
172+
logic fifo_rvalid;
173+
logic fifo_rready;
174+
logic [31:0] fifo_rdata;
175+
176+
logic unused_err, unused_full;
177+
178+
// FIFO for stress testing AXI
179+
caliptra_prim_fifo_sync #(
180+
.Width(32),
181+
.Pass (1'b0),
182+
.Depth(64)
183+
) fifo (
184+
.clk_i(aclk),
185+
.rst_ni(areset_n),
186+
.clr_i('0),
187+
.wvalid_i(fifo_wvalid),
188+
.wready_o(fifo_wready),
189+
.wdata_i(fifo_wdata),
190+
.depth_o(fifo_depth_o),
191+
.rvalid_o(fifo_rvalid),
192+
.rready_i(fifo_rready),
193+
.rdata_o(fifo_rdata),
194+
.full_o(unused_full),
195+
.err_o(unused_err)
196+
);
197+
167198
// TODO: These write-enable signals were not combo-driven or initialized on reset.
168199
// This is a placeholder driver. They require either unimplemented drivers or changes in RDL.
169200
always_comb begin : missing_csr_we_inits
@@ -214,13 +245,21 @@ module axi_adapter_wrapper
214245
hwif_in.I3C_EC.TTI.TX_DESC_QUEUE_PORT.wr_ack = 0;
215246
hwif_in.I3C_EC.TTI.TX_DATA_PORT.wr_ack = 0;
216247
hwif_in.I3C_EC.TTI.IBI_PORT.wr_ack = 0;
217-
hwif_in.I3C_EC.SecFwRecoveryIf.INDIRECT_FIFO_DATA.rd_ack = '0;
218-
hwif_in.I3C_EC.SecFwRecoveryIf.INDIRECT_FIFO_DATA.wr_ack = '0;
219248

220249
// Unhandled wr/rd_ack (drivers are mising)
221250
hwif_in.DAT.rd_ack = 0;
222251
hwif_in.DAT.wr_ack = 0;
223252
hwif_in.DCT.rd_ack = 0;
224253
hwif_in.DCT.wr_ack = 0;
225254
end : other_uninit_signals
255+
256+
always_comb begin : connect_inidrect_fifo
257+
fifo_wvalid = hwif_out.I3C_EC.SecFwRecoveryIf.INDIRECT_FIFO_DATA.req & hwif_out.I3C_EC.SecFwRecoveryIf.INDIRECT_FIFO_DATA.req_is_wr;
258+
fifo_wdata = hwif_out.I3C_EC.SecFwRecoveryIf.INDIRECT_FIFO_DATA.wr_data;
259+
hwif_in.I3C_EC.SecFwRecoveryIf.INDIRECT_FIFO_DATA.wr_ack = fifo_wvalid & fifo_wready;
260+
261+
fifo_rready = hwif_out.I3C_EC.SecFwRecoveryIf.INDIRECT_FIFO_DATA.req & ~hwif_out.I3C_EC.SecFwRecoveryIf.INDIRECT_FIFO_DATA.req_is_wr;
262+
hwif_in.I3C_EC.SecFwRecoveryIf.INDIRECT_FIFO_DATA.rd_data = fifo_rdata;
263+
hwif_in.I3C_EC.SecFwRecoveryIf.INDIRECT_FIFO_DATA.rd_ack = fifo_rvalid & fifo_rready;
264+
end
226265
endmodule
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
import logging
4+
import random
5+
6+
from bus2csr import (
7+
FrontBusTestInterface,
8+
compare_values,
9+
dword2int,
10+
get_frontend_bus_if,
11+
int2bytes,
12+
int2dword,
13+
)
14+
from utils import mask_bits, rand_bits, rand_bits32
15+
16+
import cocotb
17+
from cocotb.handle import SimHandleBase
18+
from cocotb.triggers import ClockCycles, Combine, Event, RisingEdge, Timer, with_timeout
19+
from cocotb_helpers import reset_n
20+
21+
22+
async def timeout_task(timeout):
23+
await Timer(timeout, "us")
24+
raise RuntimeError("Test timeout!")
25+
26+
27+
async def initialize(dut, timeout=50):
28+
"""
29+
Common test initialization routine which sets up environment and starts a timeout coroutine
30+
to observe whether the test did not fall in infinite loop.
31+
"""
32+
33+
cocotb.log.setLevel(logging.DEBUG)
34+
35+
# Start the background timeout task
36+
await cocotb.start(timeout_task(timeout))
37+
38+
# Initialize inputs
39+
dut.araddr.value = 0
40+
dut.arburst.value = 0
41+
dut.arsize.value = 0
42+
dut.arlen.value = 0
43+
dut.aruser.value = 0
44+
dut.arid.value = 0
45+
dut.arlock.value = 0
46+
dut.arvalid.value = 0
47+
dut.rready.value = 0
48+
dut.awaddr.value = 0
49+
dut.awburst.value = 0
50+
dut.awsize.value = 0
51+
dut.awlen.value = 0
52+
dut.awuser.value = 0
53+
dut.awid.value = 0
54+
dut.awlock.value = 0
55+
dut.awvalid.value = 0
56+
dut.wdata.value = 0
57+
dut.wstrb.value = 0
58+
dut.wlast.value = 0
59+
dut.wvalid.value = 0
60+
dut.bready.value = 0
61+
62+
# Configure testbench
63+
tb = get_frontend_bus_if()(dut)
64+
tb.log = dut._log
65+
await tb.register_test_interfaces()
66+
await ClockCycles(tb.clk, 20)
67+
await reset_n(tb.clk, tb.rst_n, cycles=5)
68+
69+
data_len = random.randint(10, 100)
70+
test_data = [random.randint(0, 2**32 - 1) for _ in range(data_len)]
71+
72+
return tb, data_len, test_data
73+
74+
75+
@cocotb.test()
76+
async def test_collision_with_write(dut):
77+
tb, data_len, test_data = await initialize(dut)
78+
79+
fifo_addr = tb.reg_map.I3C_EC.SECFWRECOVERYIF.INDIRECT_FIFO_DATA.base_addr
80+
81+
tb.log.info(f"Generated {data_len} dwords to transfer.")
82+
83+
async def writer():
84+
# Write sequence should just write data
85+
for d in test_data:
86+
await tb.write_csr(fifo_addr, int2bytes(d))
87+
88+
async def reader(return_data):
89+
# Read sequence should read data on each write data
90+
for _ in test_data:
91+
# Awaiting `awvalid` causes reading simultaneously with write data channel activity
92+
await RisingEdge(dut.awvalid)
93+
return_data.append(dword2int(await tb.read_csr(fifo_addr)))
94+
95+
received_data = []
96+
w = cocotb.start_soon(writer())
97+
r = cocotb.start_soon(reader(received_data))
98+
99+
await Combine(w, r)
100+
101+
assert received_data == test_data, "Recieved data does not match sent data!"
102+
103+
tb.log.info("Test finished!")
104+
105+
106+
@cocotb.test(skip=True)
107+
async def test_collision_with_read(dut):
108+
tb, data_len, test_data = await initialize(dut)
109+
110+
fifo_addr = tb.reg_map.I3C_EC.SECFWRECOVERYIF.INDIRECT_FIFO_DATA.base_addr
111+
112+
tb.log.info(f"Generated {data_len} dwords to transfer.")
113+
114+
async def writer():
115+
# Write sequence should write data on each read data
116+
for i, d in enumerate(test_data):
117+
# Awaiting `arvalid` causes writing simultaneously with read data channel activity
118+
if i >= 2:
119+
await RisingEdge(dut.arvalid)
120+
await tb.write_csr(fifo_addr, int2bytes(d))
121+
122+
async def reader(return_data):
123+
# Wait until there is data in FIFO
124+
while dut.fifo_depth_o.value < 2:
125+
continue
126+
127+
# Read sequence should just read data
128+
for i in range(data_len):
129+
wvalid = RisingEdge(dut.wvalid)
130+
wready = RisingEdge(dut.wready)
131+
await Combine(wvalid, wready)
132+
return_data.append(dword2int(await tb.read_csr(fifo_addr)))
133+
134+
received_data = []
135+
w = cocotb.start_soon(writer())
136+
r = cocotb.start_soon(reader(received_data))
137+
138+
await Combine(w, r)
139+
140+
assert received_data == test_data, "Recieved data does not match sent data!"
141+
142+
tb.log.info("Test finished!")
143+
144+
145+
@cocotb.test(skip=True)
146+
async def test_write_burst(dut):
147+
tb = await initialize(dut)
148+
149+
150+
@cocotb.test(skip=True)
151+
async def test_read_burst(dut):
152+
tb = await initialize(dut)
153+
154+
155+
@cocotb.test(skip=True)
156+
async def test_read_burst_collision_with_write(dut):
157+
tb = await initialize(dut)
158+
159+
160+
@cocotb.test(skip=True)
161+
async def test_write_burst_collision_with_read(dut):
162+
tb = await initialize(dut)

verification/cocotb/noxfile.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ def ahb_if_verify(session, test_group, test_name, coverage, simulator):
100100
"test_name",
101101
[
102102
"test_csr_sw_access",
103+
"test_bus_stress",
103104
],
104105
)
105106
@nox.parametrize("coverage", coverage_types)

0 commit comments

Comments
 (0)