Add support for external components. (#4 & #36)

This commit is contained in:
Alex Mykyta
2023-05-03 21:57:25 -07:00
parent f1a75f8d38
commit ca9185dac7
35 changed files with 1341 additions and 78 deletions

View File

View File

@@ -0,0 +1,29 @@
addrmap top {
reg my_reg {
field {sw=rw; hw=r;} whatever[32] = 0;
};
reg my_wide_reg {
regwidth = 64;
accesswidth = 32;
field {sw=rw; hw=r;} whatever = 0;
};
external my_reg ext_reg @ 0x00;
my_reg int_reg @ 0x04;
external my_wide_reg wide_ext_reg @ 0x10;
external my_reg ext_reg_array[32] @ 0x100 += 4;
external regfile {
my_reg placeholder @ 8*4-4;
} rf @ 0x1000;
addrmap {
my_reg placeholder @ 8*4-4;
} am @ 0x2000;
external mem {
memwidth = 32;
mementries = 8;
} mm @ 0x3000;
};

View File

@@ -0,0 +1,207 @@
{% extends "lib/tb_base.sv" %}
{%- block dut_support %}
{% sv_line_anchor %}
external_reg ext_reg_inst (
.clk(clk),
.rst(rst),
.req(hwif_out.ext_reg.req),
.req_is_wr(hwif_out.ext_reg.req_is_wr),
.wr_data(hwif_out.ext_reg.wr_data),
.wr_biten(hwif_out.ext_reg.wr_biten),
.rd_ack(hwif_in.ext_reg.rd_ack),
.rd_data(hwif_in.ext_reg.rd_data),
.wr_ack(hwif_in.ext_reg.wr_ack)
);
external_reg #(
.SUBWORDS(2)
) wide_ext_reg_inst (
.clk(clk),
.rst(rst),
.req(hwif_out.wide_ext_reg.req),
.req_is_wr(hwif_out.wide_ext_reg.req_is_wr),
.wr_data(hwif_out.wide_ext_reg.wr_data),
.wr_biten(hwif_out.wide_ext_reg.wr_biten),
.rd_ack(hwif_in.wide_ext_reg.rd_ack),
.rd_data(hwif_in.wide_ext_reg.rd_data),
.wr_ack(hwif_in.wide_ext_reg.wr_ack)
);
for(genvar i=0; i<32; i++) begin : array
external_reg ext_reg_inst (
.clk(clk),
.rst(rst),
.req(hwif_out.ext_reg_array[i].req),
.req_is_wr(hwif_out.ext_reg_array[i].req_is_wr),
.wr_data(hwif_out.ext_reg_array[i].wr_data),
.wr_biten(hwif_out.ext_reg_array[i].wr_biten),
.rd_ack(hwif_in.ext_reg_array[i].rd_ack),
.rd_data(hwif_in.ext_reg_array[i].rd_data),
.wr_ack(hwif_in.ext_reg_array[i].wr_ack)
);
end
external_block #(
.ADDR_WIDTH(5)
) rf_inst (
.clk(clk),
.rst(rst),
.req(hwif_out.rf.req),
.req_is_wr(hwif_out.rf.req_is_wr),
.addr(hwif_out.rf.addr),
.wr_data(hwif_out.rf.wr_data),
.wr_biten(hwif_out.rf.wr_biten),
.rd_ack(hwif_in.rf.rd_ack),
.rd_data(hwif_in.rf.rd_data),
.wr_ack(hwif_in.rf.wr_ack)
);
external_block #(
.ADDR_WIDTH(5)
) am_inst (
.clk(clk),
.rst(rst),
.req(hwif_out.am.req),
.req_is_wr(hwif_out.am.req_is_wr),
.addr(hwif_out.am.addr),
.wr_data(hwif_out.am.wr_data),
.wr_biten(hwif_out.am.wr_biten),
.rd_ack(hwif_in.am.rd_ack),
.rd_data(hwif_in.am.rd_data),
.wr_ack(hwif_in.am.wr_ack)
);
external_block #(
.ADDR_WIDTH(5)
) mm_inst (
.clk(clk),
.rst(rst),
.req(hwif_out.mm.req),
.req_is_wr(hwif_out.mm.req_is_wr),
.addr(hwif_out.mm.addr),
.wr_data(hwif_out.mm.wr_data),
.wr_biten(hwif_out.mm.wr_biten),
.rd_ack(hwif_in.mm.rd_ack),
.rd_data(hwif_in.mm.rd_data),
.wr_ack(hwif_in.mm.wr_ack)
);
{%- endblock %}
{% block seq %}
logic [31:0] x;
{% sv_line_anchor %}
##1;
cb.rst <= '0;
##1;
//--------------------------------------------------------------------------
// Simple read/write tests
//--------------------------------------------------------------------------
repeat(20) begin
x = $urandom();
cpuif.write('h00, x);
cpuif.assert_read('h00, x);
assert(ext_reg_inst.value == x);
end
for(int i=0; i<2; i++) begin
repeat(20) begin
x = $urandom();
cpuif.write('h10 + i*4, x);
cpuif.assert_read('h10 + i*4, x);
assert(wide_ext_reg_inst.value[i] == x);
end
end
for(int i=0; i<32; i++) begin
repeat(20) begin
x = $urandom();
cpuif.write('h100 + i*4, x);
cpuif.assert_read('h100 + i*4, x);
end
end
for(int i=0; i<8; i++) begin
repeat(20) begin
x = $urandom();
cpuif.write('h1000 + i*4, x);
cpuif.assert_read('h1000 + i*4, x);
assert(rf_inst.mem[i] == x);
end
end
for(int i=0; i<8; i++) begin
repeat(20) begin
x = $urandom();
cpuif.write('h2000 + i*4, x);
cpuif.assert_read('h2000 + i*4, x);
assert(am_inst.mem[i] == x);
end
end
for(int i=0; i<8; i++) begin
repeat(20) begin
x = $urandom();
cpuif.write('h3000 + i*4, x);
cpuif.assert_read('h3000 + i*4, x);
assert(mm_inst.mem[i] == x);
end
end
//--------------------------------------------------------------------------
// Pipelined access
//--------------------------------------------------------------------------
// init array with unique known value
cpuif.write('h4, 'h1234);
for(int i=0; i<32; i++) begin
cpuif.write('h100 + i*4, 'h100 + i);
end
for(int i=0; i<8; i++) begin
cpuif.write('h1000 + i*4, 'h1000 + i);
cpuif.write('h2000 + i*4, 'h2000 + i);
cpuif.write('h3000 + i*4, 'h3000 + i);
end
// random pipelined read/writes
repeat(256) begin
fork
begin
automatic int i, j;
i = $urandom_range(31, 0);
j = $urandom_range(7, 0);
case($urandom_range(9,0))
// external reg
0: cpuif.write('h100 + i*4, 'h100 + i);
1: cpuif.assert_read('h100 + i*4, 'h100 + i);
// internal reg
2: cpuif.write('h4, 'h1234);
3: cpuif.assert_read('h4, 'h1234);
// external regfile
4: cpuif.write('h1000 + j*4, 'h1000 + j);
5: cpuif.assert_read('h1000 + j*4, 'h1000 + j);
// external addrmap
6: cpuif.write('h2000 + j*4, 'h2000 + j);
7: cpuif.assert_read('h2000 + j*4, 'h2000 + j);
// external mem
8: cpuif.write('h3000 + j*4, 'h3000 + j);
9: cpuif.assert_read('h3000 + j*4, 'h3000 + j);
endcase
end
join_none
end
wait fork;
{% endblock %}

View File

@@ -0,0 +1,31 @@
from parameterized import parameterized_class
from ..lib.sim_testcase import SimTestCase
from ..lib.test_params import get_permutations
from ..lib.cpuifs.apb4 import APB4
from ..lib.cpuifs.axi4lite import AXI4Lite
from ..lib.cpuifs.passthrough import Passthrough
TEST_PARAMS = get_permutations({
"cpuif": [
APB4(),
AXI4Lite(),
Passthrough(),
],
"retime_read_fanin": [True, False],
"retime_read_response": [True, False],
"retime_external": [True, False],
})
@parameterized_class(TEST_PARAMS)
class Test(SimTestCase):
extra_tb_files = [
"../lib/external_reg.sv",
"../lib/external_block.sv",
]
init_hwif_in = False
clocking_hwif_in = False
timeout_clk_cycles = 30000
def test_dut(self):
self.run_test()