QLF_TDP36K: parameterised sim test gen

Also limited to 16 tests per file to allow parallelism.
Previous tests are converted to new test format with no sim test steps.
This commit is contained in:
Krystine Sherwin 2023-12-01 12:55:59 +13:00 committed by Martin Povišer
parent ba3be3fd1c
commit 3d08ed216d
2 changed files with 227 additions and 20 deletions

View File

@ -1,3 +1,8 @@
from __future__ import annotations
from dataclasses import dataclass
blockram_template = """# ======================================
design -reset; read_verilog -defer ../../common/blockram.v
chparam{param_str} {top}
@ -97,23 +102,152 @@ blockram_tests: "list[tuple[list[tuple[str, int]], str, list[str]]]" = [
"-assert-count 1 t:TDP36K"]),
]
with open("t_mem.ys", mode="w") as f:
for (params, top, assertions) in blockram_tests:
sim_template = """\
cd
read_verilog +/quicklogic/qlf_k6n10f/brams_sim.v +/quicklogic/qlf_k6n10f/sram1024x18_mem.v +/quicklogic/qlf_k6n10f/ufifo_ctl.v +/quicklogic/qlf_k6n10f/TDP18K_FIFO.v
read_verilog <<EOF
`define MEM_TEST_VECTOR {mem_test_vector}
`define UUT_SUBMODULE \\
{uut_submodule}
EOF
read_verilog -defer -formal mem_tb.v
chparam{param_str} -set VECTORLEN {vectorlen} TB
hierarchy -top TB -check
proc
sim -clock clk -n {vectorlen} -assert
"""
sync_ram_sdp_submodule = """\
sync_ram_sdp #(\\
.ADDRESS_WIDTH(ADDRESS_WIDTH),\\
.DATA_WIDTH(DATA_WIDTH)\\
) uut (\\
.clk(clk),\\
.address_in_r(ra_a),\\
.data_out(rq_a),\\
.write_enable(wce_a),\\
.address_in_w(wa_a),\\
.data_in(wd_a)\\
);\
"""
@dataclass
class TestClass:
params: dict[str, int]
top: str
assertions: list[str]
test_steps: None | list[dict[str, int]]
test_val_map = {
"rce_a": "rce_a_testvector",
"ra_a": "ra_a_testvector",
"rq_a": "rq_a_expected",
"wce_a": "wce_a_testvector",
"wa_a": "wa_a_testvector",
"wd_a": "wd_a_testvector",
"rce_b": "rce_b_testvector",
"ra_b": "ra_b_testvector",
"rq_b": "rq_b_expected",
"wce_b": "wce_b_testvector",
"wa_b": "wa_b_testvector",
"wd_b": "wd_b_testvector",
}
sim_tests: list[TestClass] = [
TestClass(
params={"ADDRESS_WIDTH": 10, "DATA_WIDTH": 36},
top="sync_ram_sdp",
assertions=["-assert-count 1 t:TDP36K"],
test_steps=[
{"wce_a": 1, "wa_a": 0x0A, "wd_a": 0xdeadbeef},
{"wce_a": 1, "wa_a": 0xBA, "wd_a": 0x5a5a5a5a},
{"wce_a": 1, "wa_a": 0xFF, "wd_a": 0},
{"rce_a": 1, "ra_a": 0xA},
{"rq_a": 0xdeadbeef},
{"rce_a": 1, "ra_a": 0xFF},
{"rq_a": 0},
]
),
]
for (params, top, assertions) in blockram_tests:
sim_test = TestClass(
params=dict(params),
top=top,
assertions=assertions,
test_steps=None
)
sim_tests.append(sim_test)
i = 0
j = 0
max_j = 16
f = None
for sim_test in sim_tests:
# format params
param_str = ""
for (key, val) in params:
for (key, val) in sim_test.params.items():
param_str += f" -set {key} {val}"
dp_subs = [""]
if "*dp" in top:
dp_subs = ["sdp", "tdp"]
wr_subs = [""]
if "w*r" in top:
wr_subs = ["wwr", "wrr"]
for db_sub in dp_subs:
for wr_sub in wr_subs:
# resolve top module wildcards
top_list = [sim_test.top]
if "*dp" in sim_test.top:
top_list += [
sim_test.top.replace("*dp", dp_sub) for dp_sub in ["sdp", "tdp"]
]
if "w*r" in sim_test.top:
top_list += [
sim_test.top.replace("w*r", wr_sub) for wr_sub in ["wwr", "wrr"]
]
if len(top_list) > 1:
top_list.pop(0)
# iterate over string substitutions
for top in top_list:
# limit number of tests per file to allow parallel make
if not f:
fn = f"t_mem{i}.ys"
f = open(fn, mode="w")
j = 0
# output yosys script test file
print(
blockram_template.format(param_str=param_str, top=top.replace("*dp", db_sub).replace("w*r", wr_sub)),
blockram_template.format(param_str=param_str, top=top),
file=f
)
for assertion in assertions:
for assertion in sim_test.assertions:
print("select {}".format(assertion), file=f)
print("", file=f)
# prepare simulation tests
test_steps = sim_test.test_steps
if test_steps:
if top == "sync_ram_sdp":
uut_submodule = sync_ram_sdp_submodule
else:
raise NotImplementedError(f"missing submodule header for {top}")
mem_test_vector = ""
for step, test in enumerate(test_steps):
for key, val in test.items():
key = test_val_map[key]
mem_test_vector += f"\\\n{key}[{step}] = 'h{val:x};"
print(
sim_template.format(
mem_test_vector=mem_test_vector,
uut_submodule=uut_submodule,
param_str=param_str,
vectorlen=len(test_steps) + 2
), file=f
)
# simulation counts for 2 tests
j += 1
# increment test counter
j += 1
if j >= max_j:
f = f.close()
i += 1
if f:
f.close()

View File

@ -0,0 +1,73 @@
module TB(input clk);
parameter ADDRESS_WIDTH = 10;
parameter DATA_WIDTH = 36;
parameter VECTORLEN = 16;
reg rce_a_testvector [VECTORLEN-1:0];
reg [ADDRESS_WIDTH-1:0] ra_a_testvector [VECTORLEN-1:0];
reg [DATA_WIDTH-1:0] rq_a_expected [VECTORLEN-1:0];
reg wce_a_testvector [VECTORLEN-1:0];
reg [ADDRESS_WIDTH-1:0] wa_a_testvector [VECTORLEN-1:0];
reg [DATA_WIDTH-1:0] wd_a_testvector [VECTORLEN-1:0];
reg rce_b_testvector [VECTORLEN-1:0];
reg [ADDRESS_WIDTH-1:0] ra_b_testvector [VECTORLEN-1:0];
reg [DATA_WIDTH-1:0] rq_b_expected [VECTORLEN-1:0];
reg wce_b_testvector [VECTORLEN-1:0];
reg [ADDRESS_WIDTH-1:0] wa_b_testvector [VECTORLEN-1:0];
reg [DATA_WIDTH-1:0] wd_b_testvector [VECTORLEN-1:0];
reg [$clog2(VECTORLEN)-1:0] i = 0;
integer j;
initial begin
for (j = 0; j < VECTORLEN; j = j + 1) begin
rce_a_testvector[j] = 1'b0;
ra_a_testvector[j] = 10'h0;
wce_a_testvector[j] = 1'b0;
wa_a_testvector[j] = 10'h0;
rce_b_testvector[j] = 1'b0;
ra_b_testvector[j] = 10'h0;
wce_b_testvector[j] = 1'b0;
wa_b_testvector[j] = 10'h0;
end
`MEM_TEST_VECTOR
end
wire rce_a = rce_a_testvector[i];
wire [ADDRESS_WIDTH-1:0] ra_a = ra_a_testvector[i];
wire [DATA_WIDTH-1:0] rq_a;
wire wce_a = wce_a_testvector[i];
wire [ADDRESS_WIDTH-1:0] wa_a = wa_a_testvector[i];
wire [DATA_WIDTH-1:0] wd_a = wd_a_testvector[i];
wire rce_b = rce_b_testvector[i];
wire [ADDRESS_WIDTH-1:0] ra_b = ra_b_testvector[i];
wire [DATA_WIDTH-1:0] rq_b;
wire wce_b = wce_b_testvector[i];
wire [ADDRESS_WIDTH-1:0] wa_b = wa_b_testvector[i];
wire [DATA_WIDTH-1:0] wd_b = wd_b_testvector[i];
`UUT_SUBMODULE
always @(posedge clk) begin
if (i < VECTORLEN-1) begin
if (i > 0) begin
if($past(rce_a))
assert(rq_a == rq_a_expected[i]);
if($past(rce_b))
assert(rq_b == rq_b_expected[i]);
end
i <= i + 1;
end
end
endmodule