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