Skip to content

Commit dafd693

Browse files
committed
OBI: Add testcase support. #157
1 parent f782c65 commit dafd693

File tree

4 files changed

+261
-0
lines changed

4 files changed

+261
-0
lines changed

tests/lib/cpuifs/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from .apb4 import APB4, FlatAPB4
44
from .axi4lite import AXI4Lite, FlatAXI4Lite
55
from .avalon import Avalon, FlatAvalon
6+
from .obi import OBI, FlatOBI
67

78
ALL_CPUIF = [
89
Passthrough(),
@@ -14,4 +15,6 @@
1415
FlatAXI4Lite(),
1516
Avalon(),
1617
FlatAvalon(),
18+
OBI(),
19+
FlatOBI(),
1720
]

tests/lib/cpuifs/obi/__init__.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from ..base import CpuifTestMode
2+
3+
from peakrdl_regblock.cpuif.obi import OBI_Cpuif, OBI_Cpuif_flattened
4+
5+
class OBI(CpuifTestMode):
6+
cpuif_cls = OBI_Cpuif
7+
rtl_files = [
8+
"../../../../hdl-src/obi_intf.sv",
9+
]
10+
tb_files = [
11+
"../../../../hdl-src/obi_intf.sv",
12+
"obi_intf_driver.sv",
13+
]
14+
tb_template = "tb_inst.sv"
15+
16+
class FlatOBI(OBI):
17+
cpuif_cls = OBI_Cpuif_flattened
18+
rtl_files = []
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
interface obi_intf_driver #(
2+
parameter DATA_WIDTH = 32,
3+
parameter ADDR_WIDTH = 32,
4+
parameter ID_WIDTH = 1
5+
)(
6+
input wire clk,
7+
input wire rst,
8+
obi_intf.manager m_obi
9+
);
10+
11+
timeunit 1ps;
12+
timeprecision 1ps;
13+
14+
logic req;
15+
logic gnt;
16+
logic [ADDR_WIDTH-1:0] addr;
17+
logic we;
18+
logic [DATA_WIDTH/8-1:0] be;
19+
logic [DATA_WIDTH-1:0] wdata;
20+
logic [ID_WIDTH-1:0] aid;
21+
22+
logic rvalid;
23+
logic rready;
24+
logic [DATA_WIDTH-1:0] rdata;
25+
logic err;
26+
logic [ID_WIDTH-1:0] rid;
27+
28+
assign m_obi.req = req;
29+
assign gnt = m_obi.gnt;
30+
assign m_obi.addr = addr;
31+
assign m_obi.we = we;
32+
assign m_obi.be = be;
33+
assign m_obi.wdata = wdata;
34+
assign m_obi.aid = aid;
35+
36+
assign rvalid = m_obi.rvalid;
37+
assign m_obi.rready = rready;
38+
assign rdata = m_obi.rdata;
39+
assign err = m_obi.err;
40+
assign rid = m_obi.rid;
41+
42+
default clocking cb @(posedge clk);
43+
default input #1step output #1;
44+
output req;
45+
input gnt;
46+
output addr;
47+
output we;
48+
output be;
49+
output wdata;
50+
output aid;
51+
52+
input rvalid;
53+
inout rready;
54+
input rdata;
55+
input err;
56+
input rid;
57+
endclocking
58+
59+
task automatic reset();
60+
cb.req <= '0;
61+
cb.addr <= '0;
62+
cb.we <= '0;
63+
cb.be <= '0;
64+
cb.wdata <= '0;
65+
cb.aid <= '0;
66+
endtask
67+
68+
initial forever begin
69+
cb.rready <= $urandom_range(1, 0);
70+
@cb;
71+
end
72+
73+
//--------------------------------------------------------------------------
74+
typedef struct {
75+
logic [DATA_WIDTH-1:0] rdata;
76+
logic err;
77+
logic [ID_WIDTH-1:0] rid;
78+
} response_t;
79+
80+
class request_t;
81+
mailbox #(response_t) response_mbx;
82+
logic [ID_WIDTH-1:0] aid;
83+
function new();
84+
this.response_mbx = new();
85+
endfunction
86+
endclass
87+
88+
semaphore txn_req_mutex = new(1);
89+
request_t request_queue[$];
90+
91+
// Listen for responses
92+
initial forever begin
93+
@cb;
94+
while(rst || !(cb.rready === 1'b1 && cb.rvalid === 1'b1)) @cb;
95+
if(request_queue.size() != 0) begin
96+
// Can match this response with an existing request.
97+
// Send response to requestor
98+
request_t req;
99+
response_t resp;
100+
req = request_queue.pop_front();
101+
resp.rdata = cb.rdata;
102+
resp.err = cb.err;
103+
resp.rid = cb.rid;
104+
105+
assert(resp.rid == req.aid) else $error("Got incorrect RID! %0d != %0d", resp.rid, req.aid);
106+
107+
req.response_mbx.put(resp);
108+
end else begin
109+
$error("Got unexpected response");
110+
end
111+
end
112+
113+
//--------------------------------------------------------------------------
114+
task automatic read(logic [ADDR_WIDTH-1:0] addr, output logic [DATA_WIDTH-1:0] data);
115+
request_t req;
116+
response_t resp;
117+
logic [ID_WIDTH-1:0] id;
118+
119+
txn_req_mutex.get();
120+
121+
// Issue read request
122+
id = $urandom();
123+
##0;
124+
cb.req <= '1;
125+
cb.we <= '0;
126+
cb.addr <= addr;
127+
cb.aid <= id;
128+
@(cb);
129+
while(cb.gnt !== 1'b1) @(cb);
130+
cb.req <= '0;
131+
132+
// Push new request into queue
133+
req = new();
134+
req.aid = id;
135+
request_queue.push_back(req);
136+
txn_req_mutex.put();
137+
138+
// Wait for response
139+
req.response_mbx.get(resp);
140+
141+
assert(!$isunknown(resp.rdata)) else $error("Read from 0x%0x returned X's on rdata", addr);
142+
assert(!$isunknown(resp.err)) else $error("Read from 0x%0x returned X's on err", addr);
143+
assert(!$isunknown(resp.rid)) else $error("Read from 0x%0x returned X's on rid", addr);
144+
data = resp.rdata;
145+
endtask
146+
147+
task automatic assert_read(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] expected_data, logic [DATA_WIDTH-1:0] mask = '1);
148+
logic [DATA_WIDTH-1:0] data;
149+
read(addr, data);
150+
data &= mask;
151+
assert(data == expected_data) else $error("Read from 0x%x returned 0x%x. Expected 0x%x", addr, data, expected_data);
152+
endtask
153+
154+
//--------------------------------------------------------------------------
155+
task automatic write(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] data, logic [DATA_WIDTH/8-1:0] strb = '1);
156+
request_t req;
157+
response_t resp;
158+
logic [ID_WIDTH-1:0] id;
159+
160+
txn_req_mutex.get();
161+
162+
// Issue write request
163+
id = $urandom();
164+
##0;
165+
cb.req <= '1;
166+
cb.we <= '1;
167+
cb.be <= strb;
168+
cb.wdata <= data;
169+
cb.addr <= addr;
170+
cb.aid <= id;
171+
@(cb);
172+
while(cb.gnt !== 1'b1) @(cb);
173+
cb.req <= '0;
174+
175+
// Push new request into queue
176+
req = new();
177+
req.aid = id;
178+
request_queue.push_back(req);
179+
txn_req_mutex.put();
180+
181+
// Wait for response
182+
req.response_mbx.get(resp);
183+
184+
assert(!$isunknown(resp.err)) else $error("Read from 0x%0x returned X's on err", addr);
185+
assert(!$isunknown(resp.rid)) else $error("Read from 0x%0x returned X's on rid", addr);
186+
endtask
187+
188+
//--------------------------------------------------------------------------
189+
initial begin
190+
reset();
191+
end
192+
193+
initial forever begin
194+
@cb;
195+
if(!rst) assert(!$isunknown(cb.gnt)) else $error("Saw X on gnt!");
196+
if(!rst) assert(!$isunknown(cb.rvalid)) else $error("Saw X on rvalid!");
197+
end
198+
199+
endinterface

tests/lib/cpuifs/obi/tb_inst.sv

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{% sv_line_anchor %}
2+
obi_intf #(
3+
.DATA_WIDTH({{exporter.cpuif.data_width}}),
4+
.ADDR_WIDTH({{exporter.cpuif.addr_width}})
5+
) obi();
6+
obi_intf_driver #(
7+
.DATA_WIDTH({{exporter.cpuif.data_width}}),
8+
.ADDR_WIDTH({{exporter.cpuif.addr_width}})
9+
) cpuif (
10+
.clk(clk),
11+
.rst(rst),
12+
.m_obi(obi)
13+
);
14+
{% if type(cpuif).__name__.startswith("Flat") %}
15+
{% sv_line_anchor %}
16+
17+
wire obi_req;
18+
wire obi_gnt;
19+
wire [{{exporter.cpuif.addr_width - 1}}:0] obi_addr;
20+
wire obi_we;
21+
wire [{{exporter.cpuif.data_width_bytes - 1}}:0] obi_be;
22+
wire [{{exporter.cpuif.data_width - 1}}:0] obi_wdata;
23+
wire [0:0] obi_aid;
24+
wire obi_rvalid;
25+
wire obi_rready;
26+
wire [{{exporter.cpuif.data_width - 1}}:0] obi_rdata;
27+
wire obi_err;
28+
wire [0:0] obi_rid;
29+
assign obi_req = obi.req;
30+
assign obi.gnt = obi_gnt;
31+
assign obi_addr = obi.addr;
32+
assign obi_we = obi.we;
33+
assign obi_be = obi.be;
34+
assign obi_wdata = obi.wdata;
35+
assign obi_aid = obi.aid;
36+
assign obi.rvalid = obi_rvalid;
37+
assign obi_rready = obi.rready;
38+
assign obi.rdata = obi_rdata;
39+
assign obi.err = obi_err;
40+
assign obi.rid = obi_rid;
41+
{% endif %}

0 commit comments

Comments
 (0)