mirror of https://github.com/YosysHQ/yosys.git
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:
parent
ba3be3fd1c
commit
3d08ed216d
|
@ -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()
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue