Initial Commit - Forked from PeakRDL-regblock @ a440cc19769069be831d267505da4f3789a26695
This commit is contained in:
0
tests/test_external/__init__.py
Normal file
0
tests/test_external/__init__.py
Normal file
56
tests/test_external/regblock.rdl
Normal file
56
tests/test_external/regblock.rdl
Normal file
@@ -0,0 +1,56 @@
|
||||
addrmap top {
|
||||
reg my_reg {
|
||||
field {sw=rw; hw=r;} whatever[32] = 0;
|
||||
};
|
||||
reg my_reg_alt {
|
||||
field {sw=r; hw=w;} whatever_a[3:2] = 0;
|
||||
field {sw=w; hw=r;} whatever_b[4:4] = 0;
|
||||
field {sw=rw; hw=r;} whatever_c[15:8] = 0;
|
||||
};
|
||||
reg my_wide_reg {
|
||||
regwidth = 64;
|
||||
accesswidth = 32;
|
||||
field {sw=rw; hw=r;} whatever = 0;
|
||||
};
|
||||
|
||||
external my_reg_alt 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;
|
||||
|
||||
reg my_ro_reg {
|
||||
field {sw=r; hw=w;} whatever[32] = 0;
|
||||
};
|
||||
reg my_wo_reg {
|
||||
field {sw=w; hw=r;} whatever[32] = 0;
|
||||
};
|
||||
external my_ro_reg ro_reg @ 0x4000;
|
||||
external my_wo_reg wo_reg @ 0x4004;
|
||||
|
||||
reg my_wide_ro_reg {
|
||||
regwidth = 64;
|
||||
accesswidth = 32;
|
||||
field {sw=r; hw=w;} whatever[32] = 0;
|
||||
};
|
||||
reg my_wide_wo_reg {
|
||||
regwidth = 64;
|
||||
accesswidth = 32;
|
||||
field {sw=w; hw=r;} whatever[32] = 0;
|
||||
};
|
||||
external my_wide_ro_reg wide_ro_reg @ 0x4010;
|
||||
external my_wide_wo_reg wide_wo_reg @ 0x4018;
|
||||
};
|
||||
311
tests/test_external/tb_template.sv
Normal file
311
tests/test_external/tb_template.sv
Normal file
@@ -0,0 +1,311 @@
|
||||
{% 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)
|
||||
);
|
||||
|
||||
external_reg wo_reg_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
.req(hwif_out.wo_reg.req),
|
||||
.req_is_wr(hwif_out.wo_reg.req_is_wr),
|
||||
.wr_data(hwif_out.wo_reg.wr_data),
|
||||
.wr_biten(hwif_out.wo_reg.wr_biten),
|
||||
.rd_ack(),
|
||||
.rd_data(),
|
||||
.wr_ack(hwif_in.wo_reg.wr_ack)
|
||||
);
|
||||
|
||||
external_reg ro_reg_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
.req(hwif_out.ro_reg.req),
|
||||
.req_is_wr(hwif_out.ro_reg.req_is_wr),
|
||||
.wr_data(32'b0),
|
||||
.wr_biten(32'b0),
|
||||
.rd_ack(hwif_in.ro_reg.rd_ack),
|
||||
.rd_data(hwif_in.ro_reg.rd_data),
|
||||
.wr_ack()
|
||||
);
|
||||
|
||||
external_reg #(
|
||||
.SUBWORDS(2)
|
||||
) wide_wo_reg_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
.req(hwif_out.wide_wo_reg.req),
|
||||
.req_is_wr(hwif_out.wide_wo_reg.req_is_wr),
|
||||
.wr_data(hwif_out.wide_wo_reg.wr_data),
|
||||
.wr_biten(hwif_out.wide_wo_reg.wr_biten),
|
||||
.rd_ack(),
|
||||
.rd_data(),
|
||||
.wr_ack(hwif_in.wide_wo_reg.wr_ack)
|
||||
);
|
||||
|
||||
external_reg #(
|
||||
.SUBWORDS(2)
|
||||
) wide_ro_reg_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
.req(hwif_out.wide_ro_reg.req),
|
||||
.req_is_wr(hwif_out.wide_ro_reg.req_is_wr),
|
||||
.wr_data(32'b0),
|
||||
.wr_biten(32'b0),
|
||||
.rd_ack(hwif_in.wide_ro_reg.rd_ack),
|
||||
.rd_data(hwif_in.wide_ro_reg.rd_data),
|
||||
.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
|
||||
|
||||
repeat(20) begin
|
||||
x = $urandom();
|
||||
ro_reg_inst.value <= x;
|
||||
cpuif.write('h4000, ~x);
|
||||
cpuif.assert_read('h4000, x);
|
||||
assert(ro_reg_inst.value == x);
|
||||
end
|
||||
|
||||
repeat(20) begin
|
||||
x = $urandom();
|
||||
cpuif.write('h4004, x);
|
||||
cpuif.assert_read('h4004, 0);
|
||||
assert(wo_reg_inst.value == x);
|
||||
end
|
||||
|
||||
for(int i=0; i<2; i++) begin
|
||||
repeat(20) begin
|
||||
x = $urandom();
|
||||
wide_ro_reg_inst.value[i] <= x;
|
||||
cpuif.write('h4010 + i*4, ~x);
|
||||
cpuif.assert_read('h4010 + i*4, x);
|
||||
assert(wide_ro_reg_inst.value[i] == x);
|
||||
end
|
||||
end
|
||||
|
||||
for(int i=0; i<2; i++) begin
|
||||
repeat(20) begin
|
||||
x = $urandom();
|
||||
cpuif.write('h4018 + i*4, x);
|
||||
cpuif.assert_read('h4018 + i*4, 0);
|
||||
assert(wide_wo_reg_inst.value[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;
|
||||
|
||||
// Check register struct bit-order
|
||||
repeat(32) begin
|
||||
regblock_pkg::top__my_reg_alt__external__fields__in_t fields_in;
|
||||
regblock_pkg::top__my_reg_alt__external__fields__out_t fields_out;
|
||||
fields_in = $urandom();
|
||||
fields_out = $urandom();
|
||||
|
||||
assert(fields_in.whatever_a == fields_in[3:2]);
|
||||
assert(fields_in.whatever_c == fields_in[15:8]);
|
||||
|
||||
assert(fields_out.whatever_b == fields_out[4]);
|
||||
assert(fields_out.whatever_c == fields_out[15:8]);
|
||||
end
|
||||
|
||||
{% endblock %}
|
||||
29
tests/test_external/testcase.py
Normal file
29
tests/test_external/testcase.py
Normal file
@@ -0,0 +1,29 @@
|
||||
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
|
||||
|
||||
@parameterized_class(get_permutations({
|
||||
"cpuif": [
|
||||
APB4(),
|
||||
AXI4Lite(),
|
||||
Passthrough(),
|
||||
],
|
||||
"retime_read_fanin": [True, False],
|
||||
"retime_read_response": [True, False],
|
||||
"retime_external": [True, False],
|
||||
}))
|
||||
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()
|
||||
Reference in New Issue
Block a user