@@ -36,6 +36,7 @@ class BaseTestCase(unittest.TestCase):
|
||||
retime_read_fanin = False
|
||||
retime_read_response = False
|
||||
reuse_hwif_typedefs = True
|
||||
retime_external = False
|
||||
|
||||
#: this gets auto-loaded via the _load_request autouse fixture
|
||||
request = None # type: pytest.FixtureRequest
|
||||
@@ -105,7 +106,11 @@ class BaseTestCase(unittest.TestCase):
|
||||
cpuif_cls=cls.cpuif.cpuif_cls,
|
||||
retime_read_fanin=cls.retime_read_fanin,
|
||||
retime_read_response=cls.retime_read_response,
|
||||
reuse_hwif_typedefs=cls.reuse_hwif_typedefs
|
||||
reuse_hwif_typedefs=cls.reuse_hwif_typedefs,
|
||||
retime_external_reg=cls.retime_external,
|
||||
retime_external_regfile=cls.retime_external,
|
||||
retime_external_mem=cls.retime_external,
|
||||
retime_external_addrmap=cls.retime_external,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
|
||||
73
tests/lib/external_block.sv
Normal file
73
tests/lib/external_block.sv
Normal file
@@ -0,0 +1,73 @@
|
||||
module external_block #(
|
||||
parameter WIDTH = 32,
|
||||
parameter ADDR_WIDTH = 8
|
||||
)(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
input wire req,
|
||||
input wire req_is_wr,
|
||||
input wire [ADDR_WIDTH-1:0] addr,
|
||||
input wire [WIDTH-1:0] wr_data,
|
||||
input wire [WIDTH-1:0] wr_biten,
|
||||
output logic rd_ack,
|
||||
output logic [WIDTH-1:0] rd_data,
|
||||
output logic wr_ack
|
||||
);
|
||||
timeunit 1ns;
|
||||
timeprecision 1ps;
|
||||
|
||||
localparam ADDR_SHIFT = $clog2(WIDTH/8);
|
||||
localparam N_ENTRIES = 2**(ADDR_WIDTH - ADDR_SHIFT);
|
||||
logic [WIDTH-1:0] mem[N_ENTRIES];
|
||||
|
||||
|
||||
task do_write(int idx, logic [WIDTH-1:0] data, logic [WIDTH-1:0] biten);
|
||||
automatic int delay;
|
||||
// Random delay
|
||||
delay = $urandom_range(3,0);
|
||||
repeat(delay) @(posedge clk)
|
||||
$info("Write delay: %d", delay);
|
||||
|
||||
for(int b=0; b<WIDTH; b++) begin
|
||||
if(biten[b]) mem[idx][b] <= data[b];
|
||||
end
|
||||
wr_ack <= '1;
|
||||
endtask
|
||||
|
||||
task do_read(int idx);
|
||||
automatic int delay;
|
||||
// Random delay
|
||||
delay = $urandom_range(3,0);
|
||||
repeat(delay) @(posedge clk)
|
||||
$info("Read delay: %d", delay);
|
||||
|
||||
rd_data <= mem[idx];
|
||||
rd_ack <= '1;
|
||||
endtask;
|
||||
|
||||
|
||||
initial begin
|
||||
rd_ack <= '0;
|
||||
rd_data <= '0;
|
||||
wr_ack <= '0;
|
||||
for(int i=0; i<N_ENTRIES; i++) mem[i] <= '0;
|
||||
|
||||
forever begin
|
||||
// Wait for next clock edge
|
||||
@(posedge clk);
|
||||
rd_ack <= '0;
|
||||
rd_data <= '0;
|
||||
wr_ack <= '0;
|
||||
|
||||
// wait slightly longer to "peek" at the current cycle's state
|
||||
#1ns;
|
||||
|
||||
if(!rst && req) begin
|
||||
if(req_is_wr) do_write(addr >> ADDR_SHIFT, wr_data, wr_biten);
|
||||
else do_read(addr >> ADDR_SHIFT);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
78
tests/lib/external_reg.sv
Normal file
78
tests/lib/external_reg.sv
Normal file
@@ -0,0 +1,78 @@
|
||||
module external_reg #(
|
||||
parameter WIDTH = 32,
|
||||
parameter SUBWORDS = 1
|
||||
)(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
input wire [SUBWORDS-1:0] req,
|
||||
input wire req_is_wr,
|
||||
input wire [WIDTH-1:0] wr_data,
|
||||
input wire [WIDTH-1:0] wr_biten,
|
||||
output logic rd_ack,
|
||||
output logic [WIDTH-1:0] rd_data,
|
||||
output logic wr_ack
|
||||
);
|
||||
timeunit 1ns;
|
||||
timeprecision 1ps;
|
||||
logic [SUBWORDS-1:0][WIDTH-1:0] value;
|
||||
|
||||
|
||||
task do_write(logic [SUBWORDS-1:0] strb, logic [WIDTH-1:0] data, logic [WIDTH-1:0] biten);
|
||||
automatic int delay;
|
||||
// Random delay
|
||||
delay = $urandom_range(3,0);
|
||||
repeat(delay) @(posedge clk)
|
||||
$info("Write delay: %d", delay);
|
||||
|
||||
for(int i=0; i<SUBWORDS; i++) begin
|
||||
if(strb[i]) begin
|
||||
for(int b=0; b<WIDTH; b++) begin
|
||||
if(biten[b]) value[i][b] <= data[b];
|
||||
end
|
||||
end
|
||||
end
|
||||
wr_ack <= '1;
|
||||
endtask
|
||||
|
||||
task do_read(logic [SUBWORDS-1:0] strb);
|
||||
automatic int delay;
|
||||
// Random delay
|
||||
delay = $urandom_range(3,0);
|
||||
repeat(delay) @(posedge clk)
|
||||
$info("Read delay: %d", delay);
|
||||
|
||||
|
||||
for(int i=0; i<SUBWORDS; i++) begin
|
||||
if(strb[i]) begin
|
||||
rd_data <= value[i];
|
||||
end
|
||||
end
|
||||
rd_ack <= '1;
|
||||
endtask;
|
||||
|
||||
|
||||
initial begin
|
||||
rd_ack <= '0;
|
||||
rd_data <= '0;
|
||||
wr_ack <= '0;
|
||||
value <= '0;
|
||||
|
||||
forever begin
|
||||
// Wait for next clock edge
|
||||
@(posedge clk);
|
||||
rd_ack <= '0;
|
||||
rd_data <= '0;
|
||||
wr_ack <= '0;
|
||||
|
||||
// wait slightly longer to "peek" at the current cycle's state
|
||||
#1ns;
|
||||
|
||||
if(!rst && req) begin
|
||||
if(req_is_wr) do_write(req, wr_data, wr_biten);
|
||||
else do_read(req);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -22,6 +22,25 @@ class SimTestCase(BaseTestCase):
|
||||
|
||||
tb_template_file = "tb_template.sv"
|
||||
|
||||
# Paths are relative to the testcase dir
|
||||
extra_tb_files = [] # type: List[str]
|
||||
|
||||
# Whether to initialize the hwif_in struct at test startup
|
||||
init_hwif_in = True
|
||||
|
||||
# Control whether to include in clocking block
|
||||
clocking_hwif_in = True
|
||||
clocking_hwif_out = True
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_extra_tb_files(cls) -> List[str]:
|
||||
paths = []
|
||||
for path in cls.extra_tb_files:
|
||||
path = os.path.join(cls.get_testcase_dir(), path)
|
||||
paths.append(path)
|
||||
return paths
|
||||
|
||||
@classmethod
|
||||
def _generate_tb(cls):
|
||||
"""
|
||||
|
||||
@@ -13,6 +13,7 @@ class Simulator:
|
||||
def tb_files(self) -> List[str]:
|
||||
files = []
|
||||
files.extend(self.testcase_cls.cpuif.get_sim_files())
|
||||
files.extend(self.testcase_cls.get_extra_tb_files())
|
||||
files.append("regblock_pkg.sv")
|
||||
files.append("regblock.sv")
|
||||
files.append("tb.sv")
|
||||
|
||||
@@ -30,11 +30,11 @@ module tb;
|
||||
default clocking cb @(posedge clk);
|
||||
default input #1step output #1;
|
||||
output rst;
|
||||
{%- if exporter.hwif.has_input_struct %}
|
||||
{%- if exporter.hwif.has_input_struct and cls.clocking_hwif_in %}
|
||||
output hwif_in;
|
||||
{%- endif %}
|
||||
|
||||
{%- if exporter.hwif.has_output_struct %}
|
||||
{%- if exporter.hwif.has_output_struct and cls.clocking_hwif_out %}
|
||||
input hwif_out;
|
||||
{%- endif %}
|
||||
|
||||
@@ -68,12 +68,15 @@ module tb;
|
||||
{%- endif %}
|
||||
{% sv_line_anchor %}
|
||||
|
||||
{%- block dut_support %}
|
||||
{%- endblock %}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Test Sequence
|
||||
//--------------------------------------------------------------------------
|
||||
initial begin
|
||||
cb.rst <= '1;
|
||||
{%- if exporter.hwif.has_input_struct %}
|
||||
{%- if exporter.hwif.has_input_struct and cls.init_hwif_in %}
|
||||
cb.hwif_in <= '{default: '0};
|
||||
{%- endif %}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user