ql-qlf: qlf_k6n10f: bram: add post synthesis simulation tests Signed-off-by: Paweł Czarnecki <pczarnecki@antmicro.com>
diff --git a/ql-qlf-plugin/tests/Makefile b/ql-qlf-plugin/tests/Makefile index fef6c31..21b68b6 100644 --- a/ql-qlf-plugin/tests/Makefile +++ b/ql-qlf-plugin/tests/Makefile
@@ -24,7 +24,6 @@ qlf_k6n10f/dsp_mult \ qlf_k6n10f/dsp_simd \ qlf_k6n10f/dsp_macc \ - qlf_k6n10f/bram_tdp # qlf_k6n10_bram \ SIM_TESTS = \ @@ -32,6 +31,10 @@ qlf_k6n10f/sim_dsp_mult_r \ qlf_k6n10f/sim_dsp_fir +# Those tests perform synthesis and simulation of synthesis results +POST_SYNTH_SIM_TESTS = \ + qlf_k6n10f/bram_tdp + include $(shell pwd)/../../Makefile_test.common consts_verify = true @@ -50,5 +53,4 @@ qlf_k6n10f-dsp_mult_verify = true qlf_k6n10f-dsp_simd_verify = true qlf_k6n10f-dsp_macc_verify = true -qlf_k6n10f-bram_tdp_verify = true #qlf_k6n10_bram_verify = true
diff --git a/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/bram_tdp.tcl b/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/bram_tdp.tcl index d304fa5..f3a5349 100644 --- a/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/bram_tdp.tcl +++ b/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/bram_tdp.tcl
@@ -12,7 +12,7 @@ opt_expr -undriven opt_clean stat -write_verilog bram_tdp_32x512_synth.v +write_verilog sim/bram_tdp_32x512_post_synth.v select -assert-count 1 t:TDP_BRAM36 select -clear @@ -23,7 +23,7 @@ opt_expr -undriven opt_clean stat -write_verilog bram_tdp_16x1024_synth.v +write_verilog sim/bram_tdp_16x1024_post_synth.v select -assert-count 1 t:TDP_BRAM36 select -clear @@ -34,7 +34,7 @@ opt_expr -undriven opt_clean stat -write_verilog bram_tdp_8x2048_synth.v +write_verilog sim/bram_tdp_8x2048_post_synth.v select -assert-count 1 t:TDP_BRAM36 select -clear @@ -45,6 +45,6 @@ opt_expr -undriven opt_clean stat -write_verilog bram_tdp_4x4096_synth.v +write_verilog sim/bram_tdp_4x4096_post_synth.v select -assert-count 1 t:TDP_BRAM36
diff --git a/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/sim/Makefile b/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/sim/Makefile new file mode 100644 index 0000000..06b45cc --- /dev/null +++ b/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/sim/Makefile
@@ -0,0 +1,35 @@ +# Copyright (C) 2022 The SymbiFlow Authors. +# +# Use of this source code is governed by a ISC-style +# license that can be found in the LICENSE file or at +# https://opensource.org/licenses/ISC +# +# SPDX-License-Identifier:ISC + +TESTBENCH = bram_tdp_tb.v +POST_SYNTH = bram_tdp_32x512_post_synth bram_tdp_16x1024_post_synth bram_tdp_8x2048_post_synth bram_tdp_4x4096_post_synth +ADDR_WIDTH = 9 10 11 12 +DATA_WIDTH = 32 16 8 4 +TOP = BRAM_TDP_32x512 BRAM_TDP_16x1024 BRAM_TDP_8x2048 BRAM_TDP_4x4096 +TEST_CASES = $(seq 0 3) +ADDR_DEFINES = $(foreach awidth, $(ADDR_WIDTH),-DADDR_WIDTH="$(awidth)") +DATA_DEFINES = $(foreach dwidth, $(DATA_WIDTH),-DDATA_WIDTH="$(dwidth)") +TOP_DEFINES = $(foreach top, $(TOP),-DTOP="$(top)") +VCD_DEFINES = $(foreach vcd, $(POST_SYNTH),-DVCD="$(vcd).vcd") + +SIM_LIBS = $(shell find ../../../../qlf_k6n10f -name "*.v" -not -name "*_map.v") + +define simulate_post_synth + @iverilog -vvvv -g2005 $(word $(1),$(ADDR_DEFINES)) $(word $(1),$(DATA_DEFINES)) $(word $(1),$(TOP_DEFINES)) $(word $(1),$(VCD_DEFINES)) -o $(word $(1),$(POST_SYNTH)).vvp $(word $(1),$(POST_SYNTH)).v $(SIM_LIBS) $(TESTBENCH) > $(word $(1),$(POST_SYNTH)).vvp.log 2>&1 + @vvp -vvvv $(word $(1),$(POST_SYNTH)).vvp > $(word $(1),$(POST_SYNTH)).vcd.log 2>&1 +endef + +define clean_post_synth_sim + @rm -rf $(word $(1),$(POST_SYNTH)).vcd $(word $(1),$(POST_SYNTH)).vvp $(word $(1),$(POST_SYNTH)).vvp.log $(word $(1),$(POST_SYNTH)).vcd.log +endef + +sim: + $(call simulate_post_synth,1) + $(call simulate_post_synth,2) + $(call simulate_post_synth,3) + $(call simulate_post_synth,4)
diff --git a/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/sim/bram_tdp_tb.v b/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/sim/bram_tdp_tb.v new file mode 100644 index 0000000..90cbf4e --- /dev/null +++ b/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/sim/bram_tdp_tb.v
@@ -0,0 +1,227 @@ +// Copyright (C) 2022 The SymbiFlow Authors. +// +// Use of this source code is governed by a ISC-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/ISC +// +// SPDX-License-Identifier:ISC + +`timescale 1ns/1ps + +`define STRINGIFY(x) `"x`" + +module TB; + localparam PERIOD = 50; + localparam ADDR_INCR = 1; + + reg clk_a; + reg rce_a; + reg [`ADDR_WIDTH-1:0] ra_a; + wire [`DATA_WIDTH-1:0] rq_a; + reg wce_a; + reg [`ADDR_WIDTH-1:0] wa_a; + reg [`DATA_WIDTH-1:0] wd_a; + + reg clk_b; + reg rce_b; + reg [`ADDR_WIDTH-1:0] ra_b; + wire [`DATA_WIDTH-1:0] rq_b; + reg wce_b; + reg [`ADDR_WIDTH-1:0] wa_b; + reg [`DATA_WIDTH-1:0] wd_b; + + + initial clk_a = 0; + initial clk_b = 0; + initial ra_a = 0; + initial ra_b = 0; + initial rce_a = 0; + initial rce_b = 0; + initial forever #(PERIOD / 2.0) clk_a = ~clk_a; + initial begin + #(PERIOD / 4.0); + forever #(PERIOD / 2.0) clk_b = ~clk_b; + end + initial begin + $dumpfile(`STRINGIFY(`VCD)); + $dumpvars; + end + + integer a; + integer b; + + reg done_a; + reg done_b; + initial done_a = 1'b0; + initial done_b = 1'b0; + wire done_sim = done_a & done_b; + + reg [`DATA_WIDTH-1:0] expected_a; + reg [`DATA_WIDTH-1:0] expected_b; + + always @(posedge clk_a) begin + expected_a <= (a | (a << 20) | 20'h55000) & {`DATA_WIDTH{1'b1}}; + end + always @(posedge clk_b) begin + expected_b <= (b | (b << 20) | 20'h55000) & {`DATA_WIDTH{1'b1}}; + end + + wire error_a = a != 0 ? rq_a !== expected_a : 0; + wire error_b = b != (1<<`ADDR_WIDTH) / 2 ? rq_b !== expected_b : 0; + + integer error_a_cnt = 0; + integer error_b_cnt = 0; + + always @ (posedge clk_a) + begin + if (error_a) + error_a_cnt <= error_a_cnt + 1'b1; + end + always @ (posedge clk_b) + begin + if (error_b) + error_b_cnt <= error_b_cnt + 1'b1; + end + // PORT A + initial #(1) begin + // Write data + for (a = 0; a < (1<<`ADDR_WIDTH) / 2; a = a + ADDR_INCR) begin + @(negedge clk_a) begin + wa_a = a; + wd_a = a | (a << 20) | 20'h55000; + wce_a = 1; + end + @(posedge clk_a) begin + #(PERIOD/10) wce_a = 0; + end + end + // Read data + for (a = 0; a < (1<<`ADDR_WIDTH) / 2; a = a + ADDR_INCR) begin + @(negedge clk_a) begin + ra_a = a; + rce_a = 1; + end + @(posedge clk_a) begin + #(PERIOD/10) rce_a = 0; + if ( rq_a !== expected_a) begin + $display("%d: PORT A: FAIL: mismatch act=%x exp=%x at %x", $time, rq_a, expected_a, a); + end else begin + $display("%d: PORT A: OK: act=%x exp=%x at %x", $time, rq_a, expected_a, a); + end + end + end + done_a = 1'b1; + end + + // PORT B + initial #(1) begin + // Write data + for (b = (1<<`ADDR_WIDTH) / 2; b < (1<<`ADDR_WIDTH); b = b + ADDR_INCR) begin + @(negedge clk_b) begin + wa_b = b; + wd_b = b | (b << 20) | 20'h55000; + wce_b = 1; + end + @(posedge clk_b) begin + #(PERIOD/10) wce_b = 0; + end + end + // Read data + for (b = (1<<`ADDR_WIDTH) / 2; b < (1<<`ADDR_WIDTH); b = b + ADDR_INCR) begin + @(negedge clk_b) begin + ra_b = b; + rce_b = 1; + end + @(posedge clk_b) begin + #(PERIOD/10) rce_b = 0; + if ( rq_b !== expected_b) begin + $display("%d: PORT B: FAIL: mismatch act=%x exp=%x at %x", $time, rq_b, expected_b, b); + end else begin + $display("%d: PORT B: OK: act=%x exp=%x at %x", $time, rq_b, expected_b, b); + end + end + end + done_b = 1'b1; + end + + // Scan for simulation finish + always @(posedge clk_a, posedge clk_b) begin + if (done_sim) + $finish_and_return( (error_a_cnt == 0 & error_b_cnt == 0) ? 0 : -1 ); + end + + case (`STRINGIFY(`TOP)) + "BRAM_TDP_32x512": begin + BRAM_TDP_32x512 #() bram ( + .clk_a(clk_a), + .rce_a(rce_a), + .ra_a(ra_a), + .rq_a(rq_a), + .wce_a(wce_a), + .wa_a(wa_a), + .wd_a(wd_a), + .clk_b(clk_b), + .rce_b(rce_b), + .ra_b(ra_b), + .rq_b(rq_b), + .wce_b(wce_b), + .wa_b(wa_b), + .wd_b(wd_b) + ); + end + "BRAM_TDP_16x1024": begin + BRAM_TDP_16x1024 #() bram ( + .clk_a(clk_a), + .rce_a(rce_a), + .ra_a(ra_a), + .rq_a(rq_a), + .wce_a(wce_a), + .wa_a(wa_a), + .wd_a(wd_a), + .clk_b(clk_b), + .rce_b(rce_b), + .ra_b(ra_b), + .rq_b(rq_b), + .wce_b(wce_b), + .wa_b(wa_b), + .wd_b(wd_b) + ); + end + "BRAM_TDP_8x2048": begin + BRAM_TDP_8x2048 #() bram ( + .clk_a(clk_a), + .rce_a(rce_a), + .ra_a(ra_a), + .rq_a(rq_a), + .wce_a(wce_a), + .wa_a(wa_a), + .wd_a(wd_a), + .clk_b(clk_b), + .rce_b(rce_b), + .ra_b(ra_b), + .rq_b(rq_b), + .wce_b(wce_b), + .wa_b(wa_b), + .wd_b(wd_b) + ); + end + "BRAM_TDP_4x4096": begin + BRAM_TDP_4x4096 #() bram ( + .clk_a(clk_a), + .rce_a(rce_a), + .ra_a(ra_a), + .rq_a(rq_a), + .wce_a(wce_a), + .wa_a(wa_a), + .wd_a(wd_a), + .clk_b(clk_b), + .rce_b(rce_b), + .ra_b(ra_b), + .rq_b(rq_b), + .wce_b(wce_b), + .wa_b(wa_b), + .wd_b(wd_b) + ); + end + endcase +endmodule