From 153ec0541c17ee8fad093c002a2724bc33dfe4b9 Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Tue, 20 Aug 2019 07:50:05 +0300 Subject: [PATCH 001/130] Add new tests for ice40 architecture --- Makefile | 1 + tests/ice40/.gitignore | 1 + tests/ice40/add_sub.ys | 7 +++ tests/ice40/add_sub_tb.v | 47 +++++++++++++++++ tests/ice40/add_sub_top.v | 13 +++++ tests/ice40/common.v | 47 +++++++++++++++++ tests/ice40/dffs.ys | 5 ++ tests/ice40/dffs_tb.v | 77 +++++++++++++++++++++++++++ tests/ice40/dffs_top.v | 108 ++++++++++++++++++++++++++++++++++++++ tests/ice40/div_mod.ys | 5 ++ tests/ice40/div_mod_tb.v | 48 +++++++++++++++++ tests/ice40/div_mod_top.v | 13 +++++ tests/ice40/latches.ys | 5 ++ tests/ice40/latches_tb.v | 59 +++++++++++++++++++++ tests/ice40/latches_top.v | 58 ++++++++++++++++++++ tests/ice40/memory.ys | 7 +++ tests/ice40/memory_tb.v | 81 ++++++++++++++++++++++++++++ tests/ice40/memory_top.v | 21 ++++++++ tests/ice40/mul_pow.ys | 6 +++ tests/ice40/mul_pow_tb.v | 47 +++++++++++++++++ tests/ice40/mul_pow_top.v | 13 +++++ tests/ice40/mux.ys | 5 ++ tests/ice40/mux_tb.v | 43 +++++++++++++++ tests/ice40/mux_top.v | 100 +++++++++++++++++++++++++++++++++++ tests/ice40/run-test.sh | 21 ++++++++ tests/ice40/tribuf.ys | 6 +++ tests/ice40/tribuf_tb.v | 34 ++++++++++++ tests/ice40/tribuf_top.v | 23 ++++++++ 28 files changed, 901 insertions(+) create mode 100644 tests/ice40/.gitignore create mode 100644 tests/ice40/add_sub.ys create mode 100644 tests/ice40/add_sub_tb.v create mode 100644 tests/ice40/add_sub_top.v create mode 100644 tests/ice40/common.v create mode 100644 tests/ice40/dffs.ys create mode 100644 tests/ice40/dffs_tb.v create mode 100644 tests/ice40/dffs_top.v create mode 100644 tests/ice40/div_mod.ys create mode 100644 tests/ice40/div_mod_tb.v create mode 100644 tests/ice40/div_mod_top.v create mode 100644 tests/ice40/latches.ys create mode 100644 tests/ice40/latches_tb.v create mode 100644 tests/ice40/latches_top.v create mode 100644 tests/ice40/memory.ys create mode 100644 tests/ice40/memory_tb.v create mode 100644 tests/ice40/memory_top.v create mode 100644 tests/ice40/mul_pow.ys create mode 100644 tests/ice40/mul_pow_tb.v create mode 100644 tests/ice40/mul_pow_top.v create mode 100644 tests/ice40/mux.ys create mode 100644 tests/ice40/mux_tb.v create mode 100644 tests/ice40/mux_top.v create mode 100755 tests/ice40/run-test.sh create mode 100644 tests/ice40/tribuf.ys create mode 100644 tests/ice40/tribuf_tb.v create mode 100644 tests/ice40/tribuf_top.v diff --git a/Makefile b/Makefile index 382f79546..9cfa6a0de 100644 --- a/Makefile +++ b/Makefile @@ -699,6 +699,7 @@ test: $(TARGETS) $(EXTRA_TARGETS) +cd tests/opt && bash run-test.sh +cd tests/aiger && bash run-test.sh $(ABCOPT) +cd tests/arch && bash run-test.sh + +cd tests/ice40 && bash run-test.sh $(SEEDOPT) @echo "" @echo " Passed \"make test\"." @echo "" diff --git a/tests/ice40/.gitignore b/tests/ice40/.gitignore new file mode 100644 index 000000000..397b4a762 --- /dev/null +++ b/tests/ice40/.gitignore @@ -0,0 +1 @@ +*.log diff --git a/tests/ice40/add_sub.ys b/tests/ice40/add_sub.ys new file mode 100644 index 000000000..58ad52a58 --- /dev/null +++ b/tests/ice40/add_sub.ys @@ -0,0 +1,7 @@ +equiv_opt -map ../../techlibs/ice40/cells_sim.v synth_ice40 +synth_ice40 +select -assert-count 12 t:SB_LUT4 +select -assert-count 7 t:SB_CARRY +select -assert-count 2 t:$logic_and +select -assert-count 2 t:$logic_or +write_verilog ./temp/add_sub_synth.v diff --git a/tests/ice40/add_sub_tb.v b/tests/ice40/add_sub_tb.v new file mode 100644 index 000000000..45e4f3154 --- /dev/null +++ b/tests/ice40/add_sub_tb.v @@ -0,0 +1,47 @@ +module testbench; + reg [7:0] in; + + wire [3:0] outA,outB; + wire [3:0] poutA,poutB; + + initial begin + // $dumpfile("testbench.vcd"); + // $dumpvars(0, testbench); + + #5 in = 0; + repeat (10000) begin + #5 in = in + 1; + end + + $display("OKAY"); + end + + top uut ( + .x(in[3:0]), + .y(in[7:4]), + .A(outA), + .B(outB) + ); + + + assign poutA = in[3:0] + in[7:4]; + assign poutB = in[3:0] - in[7:4]; + + check_comb add_test(outA, poutA); + check_comb sub_test(outB, poutB); + assert_comb sub0_test(outB[2], poutB[2]); + +endmodule + +module check_comb(input [3:0] test, input [3:0] pat); + always @* + begin + #1; + if (test != pat) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",test," ",pat); + $stop; + end + end +endmodule + diff --git a/tests/ice40/add_sub_top.v b/tests/ice40/add_sub_top.v new file mode 100644 index 000000000..177c32e30 --- /dev/null +++ b/tests/ice40/add_sub_top.v @@ -0,0 +1,13 @@ +module top +( + input [3:0] x, + input [3:0] y, + + output [3:0] A, + output [3:0] B + ); + +assign A = x + y; +assign B = x - y; + +endmodule diff --git a/tests/ice40/common.v b/tests/ice40/common.v new file mode 100644 index 000000000..5446f0817 --- /dev/null +++ b/tests/ice40/common.v @@ -0,0 +1,47 @@ +module assert_dff(input clk, input test, input pat); + always @(posedge clk) + begin + #1; + if (test != pat) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time); + $stop; + end + end +endmodule + +module assert_tri(input en, input A, input B); + always @(posedge en) + begin + #1; + if (A !== B) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); + $stop; + end + end +endmodule + +module assert_Z(input clk, input A); + always @(posedge clk) + begin + #1; + if (A === 1'bZ) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A); + $stop; + end + end +endmodule + +module assert_comb(input A, input B); + always @(*) + begin + #1; + if (A !== B) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); + $stop; + end + end +endmodule diff --git a/tests/ice40/dffs.ys b/tests/ice40/dffs.ys new file mode 100644 index 000000000..68410b4d8 --- /dev/null +++ b/tests/ice40/dffs.ys @@ -0,0 +1,5 @@ +equiv_opt -map ../../techlibs/ice40/cells_sim.v synth_ice40 +synth_ice40 +select -assert-count 2 t:SB_DFFR +select -assert-count 1 t:SB_DFFE +write_verilog ./temp/dffs_synth.v diff --git a/tests/ice40/dffs_tb.v b/tests/ice40/dffs_tb.v new file mode 100644 index 000000000..ed8f2eb2a --- /dev/null +++ b/tests/ice40/dffs_tb.v @@ -0,0 +1,77 @@ +module testbench; + reg clk; + + initial begin + // $dumpfile("testbench.vcd"); + // $dumpvars(0, testbench); + + #5 clk = 0; + repeat (10000) begin + #5 clk = 1; + #5 clk = 0; + end + + $display("OKAY"); + end + + + reg [2:0] dinA = 0; + wire doutB,doutB1,doutB2,doutB3,doutB4; + reg dff,ndff,adff,adffn,dffe = 0; + + top uut ( + .clk (clk ), + .a (dinA[0] ), + .pre (dinA[1] ), + .clr (dinA[2] ), + .b (doutB ), + .b1 (doutB1 ), + .b2 (doutB2 ), + .b3 (doutB3 ), + .b4 (doutB4 ) + ); + + always @(posedge clk) begin + #3; + dinA <= dinA + 1; + end + + always @( posedge clk, posedge dinA[1], posedge dinA[2] ) + if ( dinA[2] ) + dff <= 1'b0; + else if ( dinA[1] ) + dff <= 1'b1; + else + dff <= dinA[0]; + + always @( negedge clk, negedge dinA[1], negedge dinA[2] ) + if ( !dinA[2] ) + ndff <= 1'b0; + else if ( !dinA[1] ) + ndff <= 1'b1; + else + ndff <= dinA[0]; + + always @( posedge clk, posedge dinA[2] ) + if ( dinA[2] ) + adff <= 1'b0; + else + adff <= dinA[0]; + + always @( posedge clk, negedge dinA[2] ) + if ( !dinA[2] ) + adffn <= 1'b0; + else + adffn <= dinA[0]; + + always @( posedge clk ) + if ( dinA[2] ) + dffe <= dinA[0]; + + assert_dff dff_test(.clk(clk), .test(doutB), .pat(dff)); + assert_dff ndff_test(.clk(clk), .test(doutB1), .pat(ndff)); + assert_dff adff_test(.clk(clk), .test(doutB2), .pat(adff)); + assert_dff adffn_test(.clk(clk), .test(doutB3), .pat(adffn)); + assert_dff dffe_test(.clk(clk), .test(doutB4), .pat(dffe)); + +endmodule diff --git a/tests/ice40/dffs_top.v b/tests/ice40/dffs_top.v new file mode 100644 index 000000000..af7022c79 --- /dev/null +++ b/tests/ice40/dffs_top.v @@ -0,0 +1,108 @@ +module adff + ( input d, clk, clr, output reg q ); + initial begin + q = 0; + end + always @( posedge clk, posedge clr ) + if ( clr ) + q <= 1'b0; + else + q <= d; +endmodule + +module adffn + ( input d, clk, clr, output reg q ); + initial begin + q = 0; + end + always @( posedge clk, negedge clr ) + if ( !clr ) + q <= 1'b0; + else + q <= d; +endmodule + +module dffe + ( input d, clk, en, output reg q ); + initial begin + q = 0; + end + always @( posedge clk ) + if ( en ) + q <= d; +endmodule + +module dffsr + ( input d, clk, pre, clr, output reg q ); + initial begin + q = 0; + end + always @( posedge clk, posedge pre, posedge clr ) + if ( clr ) + q <= 1'b0; + else if ( pre ) + q <= 1'b1; + else + q <= d; +endmodule + +module ndffnsnr + ( input d, clk, pre, clr, output reg q ); + initial begin + q = 0; + end + always @( negedge clk, negedge pre, negedge clr ) + if ( !clr ) + q <= 1'b0; + else if ( !pre ) + q <= 1'b1; + else + q <= d; +endmodule + +module top ( +input clk, +input clr, +input pre, +input a, +output b,b1,b2,b3,b4 +); + +dffsr u_dffsr ( + .clk (clk ), + .clr (clr), + .pre (pre), + .d (a ), + .q (b ) + ); + +ndffnsnr u_ndffnsnr ( + .clk (clk ), + .clr (clr), + .pre (pre), + .d (a ), + .q (b1 ) + ); + +adff u_adff ( + .clk (clk ), + .clr (clr), + .d (a ), + .q (b2 ) + ); + +adffn u_adffn ( + .clk (clk ), + .clr (clr), + .d (a ), + .q (b3 ) + ); + +dffe u_dffe ( + .clk (clk ), + .en (clr), + .d (a ), + .q (b4 ) + ); + +endmodule diff --git a/tests/ice40/div_mod.ys b/tests/ice40/div_mod.ys new file mode 100644 index 000000000..28f31136b --- /dev/null +++ b/tests/ice40/div_mod.ys @@ -0,0 +1,5 @@ +synth_ice40 +equiv_opt -map ../../techlibs/ice40/cells_sim.v synth_ice40 +select -assert-count 89 t:SB_LUT4 +select -assert-count 66 t:SB_CARRY +write_verilog ./temp/div_mod_synth.v diff --git a/tests/ice40/div_mod_tb.v b/tests/ice40/div_mod_tb.v new file mode 100644 index 000000000..4296535c9 --- /dev/null +++ b/tests/ice40/div_mod_tb.v @@ -0,0 +1,48 @@ +module testbench; + reg [7:0] in; + + wire [3:0] outA,outB; + wire [3:0] poutA,poutB; + + initial begin + // $dumpfile("testbench.vcd"); + // $dumpvars(0, testbench); + + #5 in = 0; + repeat (10000) begin + #5 in = in + 1; + end + + $display("OKAY"); + end + + top uut ( + .x(in[3:0]), + .y(in[7:4]), + .A(outA), + .B(outB) + ); + + + assign poutA = in[3:0] % in[7:4]; + assign poutB = in[3:0] / in[7:4]; + + check_comb mod_test(in[7:4], outA, poutA); + check_comb div_test(in[7:4], outB, poutB); + //assert_comb div2_test(outB[2], poutB[2]); + +endmodule + +module check_comb(input [3:0] divisor, input [3:0] test, input [3:0] pat); + always @* + begin + #1; + if (divisor != 4'b0000) + if (test !== pat) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",test," ",pat); + $stop; + end + end +endmodule + diff --git a/tests/ice40/div_mod_top.v b/tests/ice40/div_mod_top.v new file mode 100644 index 000000000..64a36707d --- /dev/null +++ b/tests/ice40/div_mod_top.v @@ -0,0 +1,13 @@ +module top +( + input [3:0] x, + input [3:0] y, + + output [3:0] A, + output [3:0] B + ); + +assign A = x % y; +assign B = x / y; + +endmodule diff --git a/tests/ice40/latches.ys b/tests/ice40/latches.ys new file mode 100644 index 000000000..250ea0f84 --- /dev/null +++ b/tests/ice40/latches.ys @@ -0,0 +1,5 @@ +synth_ice40 +equiv_opt -map ../../techlibs/ice40/cells_sim.v synth_ice40 +proc +select -assert-count 5 t:SB_LUT4 +write_verilog ./temp/latches_synth.v diff --git a/tests/ice40/latches_tb.v b/tests/ice40/latches_tb.v new file mode 100644 index 000000000..47ae8670c --- /dev/null +++ b/tests/ice40/latches_tb.v @@ -0,0 +1,59 @@ +module testbench; + reg clk; + + initial begin + // $dumpfile("testbench.vcd"); + // $dumpvars(0, testbench); + + #5 clk = 0; + repeat (10000) begin + #5 clk = 1; + #5 clk = 0; + end + + $display("OKAY"); + end + + + reg [2:0] dinA = 0; + wire doutB,doutB1,doutB2; + reg lat,latn,latsr = 0; + + top uut ( + .clk (clk ), + .a (dinA[0] ), + .pre (dinA[1] ), + .clr (dinA[2] ), + .b (doutB ), + .b1 (doutB1 ), + .b2 (doutB2 ) + ); + + always @(posedge clk) begin + #3; + dinA <= dinA + 1; + end + + always @* + if ( clk ) + lat <= dinA[0]; + + + always @* + if ( !clk ) + latn <= dinA[0]; + + + always @* + if ( dinA[2] ) + latsr <= 1'b0; + else if ( dinA[1] ) + latsr <= 1'b1; + else if ( clk ) + latsr <= dinA[0]; + + assert_dff lat_test(.clk(clk), .test(doutB), .pat(lat)); + assert_dff latn_test(.clk(clk), .test(doutB1), .pat(latn)); + assert_dff latsr_test(.clk(clk), .test(doutB2), .pat(latsr)); + +endmodule diff --git a/tests/ice40/latches_top.v b/tests/ice40/latches_top.v new file mode 100644 index 000000000..9dc43e4c2 --- /dev/null +++ b/tests/ice40/latches_top.v @@ -0,0 +1,58 @@ +module latchp + ( input d, clk, en, output reg q ); + always @* + if ( en ) + q <= d; +endmodule + +module latchn + ( input d, clk, en, output reg q ); + always @* + if ( !en ) + q <= d; +endmodule + +module latchsr + ( input d, clk, en, clr, pre, output reg q ); + always @* + if ( clr ) + q <= 1'b0; + else if ( pre ) + q <= 1'b1; + else if ( en ) + q <= d; +endmodule + + +module top ( +input clk, +input clr, +input pre, +input a, +output b,b1,b2 +); + + +latchp u_latchp ( + .en (clk ), + .d (a ), + .q (b ) + ); + + +latchn u_latchn ( + .en (clk ), + .d (a ), + .q (b1 ) + ); + + +latchsr u_latchsr ( + .en (clk ), + .clr (clr), + .pre (pre), + .d (a ), + .q (b2 ) + ); + +endmodule diff --git a/tests/ice40/memory.ys b/tests/ice40/memory.ys new file mode 100644 index 000000000..0f030d77d --- /dev/null +++ b/tests/ice40/memory.ys @@ -0,0 +1,7 @@ +proc +memory +equiv_opt -map ../../techlibs/ice40/cells_sim.v synth_ice40 +synth_ice40 +select -assert-count 8 t:SB_DFF +select -assert-count 512 t:SB_DFFE +write_verilog ./temp/memory_synth.v diff --git a/tests/ice40/memory_tb.v b/tests/ice40/memory_tb.v new file mode 100644 index 000000000..5905f3ddd --- /dev/null +++ b/tests/ice40/memory_tb.v @@ -0,0 +1,81 @@ +module testbench; + reg clk; + + initial begin + // $dumpfile("testbench.vcd"); + // $dumpvars(0, testbench); + + #5 clk = 0; + repeat (10000) begin + #5 clk = 1; + #5 clk = 0; + end + + $display("OKAY"); + end + + + reg [7:0] data_a = 0; + reg [5:0] addr_a = 0; + reg we_a = 0; + reg re_a = 1; + wire [7:0] q_a; + reg mem_init = 0; + + reg [7:0] pq_a; + + top uut ( + .data_a(data_a), + .addr_a(addr_a), + .we_a(we_a), + .clk(clk), + .q_a(q_a) + ); + + always @(posedge clk) begin + #3; + data_a <= data_a + 17; + + addr_a <= addr_a + 1; + end + + always @(posedge addr_a) begin + #10; + if(addr_a > 6'h3E) + mem_init <= 1; + end + + always @(posedge clk) begin + //#3; + we_a <= !we_a; + end + + // Declare the RAM variable for check + reg [7:0] ram[63:0]; + + // Port A for check + always @ (posedge clk) + begin + if (we_a) + begin + ram[addr_a] <= data_a; + pq_a <= data_a; + end + pq_a <= ram[addr_a]; + end + + uut_mem_checker port_a_test(.clk(clk), .init(mem_init), .en(!we_a), .A(q_a), .B(pq_a)); + +endmodule + +module uut_mem_checker(input clk, input init, input en, input [7:0] A, input [7:0] B); + always @(posedge clk) + begin + #1; + if (en == 1 & init == 1 & A !== B) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); + $stop; + end + end +endmodule diff --git a/tests/ice40/memory_top.v b/tests/ice40/memory_top.v new file mode 100644 index 000000000..cb7753f7b --- /dev/null +++ b/tests/ice40/memory_top.v @@ -0,0 +1,21 @@ +module top +( + input [7:0] data_a, + input [6:1] addr_a, + input we_a, clk, + output reg [7:0] q_a +); + // Declare the RAM variable + reg [7:0] ram[63:0]; + + // Port A + always @ (posedge clk) + begin + if (we_a) + begin + ram[addr_a] <= data_a; + q_a <= data_a; + end + q_a <= ram[addr_a]; + end +endmodule diff --git a/tests/ice40/mul_pow.ys b/tests/ice40/mul_pow.ys new file mode 100644 index 000000000..486480506 --- /dev/null +++ b/tests/ice40/mul_pow.ys @@ -0,0 +1,6 @@ +equiv_opt -map ../../techlibs/ice40/cells_sim.v synth_ice40 +synth_ice40 +select -assert-count 15 t:SB_LUT4 +select -assert-count 4 t:SB_CARRY +select -assert-count 1 t:$pow +write_verilog ./temp/mul_pow_synth.v diff --git a/tests/ice40/mul_pow_tb.v b/tests/ice40/mul_pow_tb.v new file mode 100644 index 000000000..7e888474f --- /dev/null +++ b/tests/ice40/mul_pow_tb.v @@ -0,0 +1,47 @@ +module testbench; + reg [7:0] in; + + wire [3:0] outA,outB; + wire [3:0] poutA,poutB; + + initial begin + // $dumpfile("testbench.vcd"); + // $dumpvars(0, testbench); + + #5 in = 0; + repeat (10000) begin + #5 in = in + 1; + end + + $display("OKAY"); + end + + top uut ( + .x(in[3:0]), + .y(in[7:4]), + .A(outA), + .B(outB) + ); + + + assign poutA = in[3:0] * in[7:4]; + assign poutB = in[3:0] ** in[7:4]; + + check_comb mul_test(outA, poutA); + check_comb pow_test(outB, poutB); + assert_comb pow2_test(outB[2], poutB[2]); + +endmodule + +module check_comb(input [3:0] test, input [3:0] pat); + always @* + begin + #1; + if (test !== pat) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",test," ",pat); + $stop; + end + end +endmodule + diff --git a/tests/ice40/mul_pow_top.v b/tests/ice40/mul_pow_top.v new file mode 100644 index 000000000..6c256d96b --- /dev/null +++ b/tests/ice40/mul_pow_top.v @@ -0,0 +1,13 @@ +module top +( + input [3:0] x, + input [3:0] y, + + output [3:0] A, + output [3:0] B + ); + +assign A = x * y; +assign B = x ** y; + +endmodule diff --git a/tests/ice40/mux.ys b/tests/ice40/mux.ys new file mode 100644 index 000000000..5ae5a1f33 --- /dev/null +++ b/tests/ice40/mux.ys @@ -0,0 +1,5 @@ +equiv_opt -map ../../techlibs/ice40/cells_sim.v synth_ice40 +synth_ice40 +select -assert-count 20 t:SB_LUT4 +select -assert-count 1 t:SB_CARRY +write_verilog ./temp/mux_synth.v diff --git a/tests/ice40/mux_tb.v b/tests/ice40/mux_tb.v new file mode 100644 index 000000000..2b2da25e9 --- /dev/null +++ b/tests/ice40/mux_tb.v @@ -0,0 +1,43 @@ +module testbench; + reg clk; + + initial begin + // $dumpfile("testbench.vcd"); + // $dumpvars(0, testbench); + + #5 clk = 0; + repeat (10000) begin + #5 clk = 1; + #5 clk = 0; + end + + $display("OKAY"); + end + + + reg [15:0] D = 1; + reg [3:0] S = 0; + wire M2,M4,M8,M16; + + top uut ( + .S (S ), + .D (D ), + .M2 (M2 ), + .M4 (M4 ), + .M8 (M8 ), + .M16 (M16 ) + ); + + always @(posedge clk) begin + //#3; + D <= {D[14:0],D[15]}; + //D <= D <<< 1; + S <= S + 1; + end + + assert_tri m2_test(.en(clk), .A(D[0]|D[1]), .B(M2)); + assert_tri m4_test(.en(clk), .A(D[0]|D[1]|D[2]|D[3]), .B(M4)); + assert_tri m8_test(.en(clk), .A(!S[3]), .B(M8)); + assert_tri m16_test(.en(clk), .A(1'b1), .B(M16)); + +endmodule diff --git a/tests/ice40/mux_top.v b/tests/ice40/mux_top.v new file mode 100644 index 000000000..0814b733e --- /dev/null +++ b/tests/ice40/mux_top.v @@ -0,0 +1,100 @@ +module mux2 (S,A,B,Y); + input S; + input A,B; + output reg Y; + + always @(*) + Y = (S)? B : A; +endmodule + +module mux4 ( S, D, Y ); + +input[1:0] S; +input[3:0] D; +output Y; + +reg Y; +wire[1:0] S; +wire[3:0] D; + +always @* +begin + case( S ) + 0 : Y = D[0]; + 1 : Y = D[1]; + 2 : Y = D[2]; + 3 : Y = D[3]; + endcase +end + +endmodule + +module mux8 ( S, D, Y ); + +input[2:0] S; +input[7:0] D; +output Y; + +reg Y; +wire[2:0] S; +wire[7:0] D; + +always @* +begin + case( S ) + 0 : Y = D[0]; + 1 : Y = D[1]; + 2 : Y = D[2]; + 3 : Y = D[3]; + 4 : Y = D[4]; + 5 : Y = D[5]; + 6 : Y = D[6]; + 7 : Y = D[7]; + endcase +end + +endmodule + +module mux16 (D, S, Y); + input [15:0] D; + input [3:0] S; + output Y; + +assign Y = D[S]; + +endmodule + + +module top ( +input [3:0] S, +input [15:0] D, +output M2,M4,M8,M16 +); + +mux2 u_mux2 ( + .S (S[0]), + .A (D[0]), + .B (D[1]), + .Y (M2) + ); + + +mux4 u_mux4 ( + .S (S[1:0]), + .D (D[3:0]), + .Y (M4) + ); + +mux8 u_mux8 ( + .S (S[2:0]), + .D (D[7:0]), + .Y (M8) + ); + +mux16 u_mux16 ( + .S (S[3:0]), + .D (D[15:0]), + .Y (M16) + ); + +endmodule diff --git a/tests/ice40/run-test.sh b/tests/ice40/run-test.sh new file mode 100755 index 000000000..e839aa9f5 --- /dev/null +++ b/tests/ice40/run-test.sh @@ -0,0 +1,21 @@ +#!/bin/bash +set -e +if [ -f "../../../../../techlibs/common/simcells.v" ]; then + COMMON_PREFIX=../../../../../techlibs/common + TECHLIBS_PREFIX=../../../../../techlibs +else + COMMON_PREFIX=/usr/local/share/yosys + TECHLIBS_PREFIX=/usr/local/share/yosys +fi +for x in *_top.v; do + echo "Running $x.." + ../../yosys -q -s ${x%_top.v}.ys -l ./temp/${x%.v}.log $x + echo "Simulating $x.." + iverilog -o ./temp/${x%_top.v}_testbench ${x%_top.v}_tb.v ./temp/${x%_top.v}_synth.v common.v $COMMON_PREFIX/simcells.v $TECHLIBS_PREFIX/ice40/cells_sim.v + if ! vvp -N ./temp/${x%_top.v}_testbench > ./temp/${x%_top.v}_testbench.log 2>&1; then + grep 'ERROR' ./temp/${x%_top.v}_testbench.log + exit 0 + elif grep 'ERROR' ./temp/${x%_top.v}_testbench.log || ! grep 'OKAY' ./temp/${x%_top.v}_testbench.log; then + exit 0 + fi +done diff --git a/tests/ice40/tribuf.ys b/tests/ice40/tribuf.ys new file mode 100644 index 000000000..40ded734d --- /dev/null +++ b/tests/ice40/tribuf.ys @@ -0,0 +1,6 @@ +equiv_opt -map ../../techlibs/ice40/cells_sim.v synth_ice40 +synth_ice40 +select -assert-count 1 t:SB_LUT4 +select -assert-count 1 t:SB_CARRY +select -assert-count 1 t:$_TBUF_ +write_verilog ./temp/tribuf_synth.v diff --git a/tests/ice40/tribuf_tb.v b/tests/ice40/tribuf_tb.v new file mode 100644 index 000000000..16871b7b2 --- /dev/null +++ b/tests/ice40/tribuf_tb.v @@ -0,0 +1,34 @@ +module testbench; + reg en; + + initial begin + // $dumpfile("testbench.vcd"); + // $dumpvars(0, testbench); + + #5 en = 0; + repeat (10000) begin + #5 en = 1; + #5 en = 0; + end + + $display("OKAY"); + end + + + reg dinA = 0; + wire doutB; + + top uut ( + .en (en ), + .a (dinA ), + .b (doutB ) + ); + + always @(posedge en) begin + #3; + dinA <= !dinA; + end + + assert_tri b_test(.en(en), .A(dinA), .B(doutB)); + +endmodule diff --git a/tests/ice40/tribuf_top.v b/tests/ice40/tribuf_top.v new file mode 100644 index 000000000..b2b5e37d6 --- /dev/null +++ b/tests/ice40/tribuf_top.v @@ -0,0 +1,23 @@ +module tristate (en, i, o); + input en; + input i; + output reg o; + + always @(en or i) + o <= (en)? i : 1'bZ; +endmodule + + +module top ( +input en, +input a, +output b +); + +tristate u_tri ( + .en (en ), + .i (a ), + .o (b ) + ); + +endmodule From 71dd412ac55860cbf51d91d26088515978f70116 Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Tue, 20 Aug 2019 15:52:25 +0300 Subject: [PATCH 002/130] Fix tests; Remove simulation; - Add -map and -assert options for equiv_opt; !!! '-assert' option was commented for the next tests (unproven $equiv cells was found): - dffs; - div_mod; - latches; - mul_pow; - Add design -load; - Remove simulations; --- tests/ice40/{add_sub_top.v => add_sub.v} | 0 tests/ice40/add_sub.ys | 4 +- tests/ice40/add_sub_tb.v | 47 -------------- tests/ice40/common.v | 47 -------------- tests/ice40/{dffs_top.v => dffs.v} | 0 tests/ice40/dffs.ys | 11 +++- tests/ice40/dffs_tb.v | 77 ---------------------- tests/ice40/{div_mod_top.v => div_mod.v} | 0 tests/ice40/div_mod.ys | 9 +-- tests/ice40/div_mod_tb.v | 48 -------------- tests/ice40/{latches_top.v => latches.v} | 0 tests/ice40/latches.ys | 5 +- tests/ice40/latches_tb.v | 59 ----------------- tests/ice40/{memory_top.v => memory.v} | 0 tests/ice40/memory.ys | 5 +- tests/ice40/memory_tb.v | 81 ------------------------ tests/ice40/{mul_pow_top.v => mul_pow.v} | 0 tests/ice40/mul_pow.ys | 7 +- tests/ice40/mul_pow_tb.v | 47 -------------- tests/ice40/{mux_top.v => mux.v} | 0 tests/ice40/mux.ys | 5 +- tests/ice40/mux_tb.v | 43 ------------- tests/ice40/run-test.sh | 19 +----- tests/ice40/{tribuf_top.v => tribuf.v} | 0 tests/ice40/tribuf.ys | 4 +- tests/ice40/tribuf_tb.v | 34 ---------- 26 files changed, 33 insertions(+), 519 deletions(-) rename tests/ice40/{add_sub_top.v => add_sub.v} (100%) delete mode 100644 tests/ice40/add_sub_tb.v delete mode 100644 tests/ice40/common.v rename tests/ice40/{dffs_top.v => dffs.v} (100%) delete mode 100644 tests/ice40/dffs_tb.v rename tests/ice40/{div_mod_top.v => div_mod.v} (100%) delete mode 100644 tests/ice40/div_mod_tb.v rename tests/ice40/{latches_top.v => latches.v} (100%) delete mode 100644 tests/ice40/latches_tb.v rename tests/ice40/{memory_top.v => memory.v} (100%) delete mode 100644 tests/ice40/memory_tb.v rename tests/ice40/{mul_pow_top.v => mul_pow.v} (100%) delete mode 100644 tests/ice40/mul_pow_tb.v rename tests/ice40/{mux_top.v => mux.v} (100%) delete mode 100644 tests/ice40/mux_tb.v rename tests/ice40/{tribuf_top.v => tribuf.v} (100%) delete mode 100644 tests/ice40/tribuf_tb.v diff --git a/tests/ice40/add_sub_top.v b/tests/ice40/add_sub.v similarity index 100% rename from tests/ice40/add_sub_top.v rename to tests/ice40/add_sub.v diff --git a/tests/ice40/add_sub.ys b/tests/ice40/add_sub.ys index 58ad52a58..c2ee3a843 100644 --- a/tests/ice40/add_sub.ys +++ b/tests/ice40/add_sub.ys @@ -1,7 +1,7 @@ -equiv_opt -map ../../techlibs/ice40/cells_sim.v synth_ice40 synth_ice40 +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 +design -load postopt select -assert-count 12 t:SB_LUT4 select -assert-count 7 t:SB_CARRY select -assert-count 2 t:$logic_and select -assert-count 2 t:$logic_or -write_verilog ./temp/add_sub_synth.v diff --git a/tests/ice40/add_sub_tb.v b/tests/ice40/add_sub_tb.v deleted file mode 100644 index 45e4f3154..000000000 --- a/tests/ice40/add_sub_tb.v +++ /dev/null @@ -1,47 +0,0 @@ -module testbench; - reg [7:0] in; - - wire [3:0] outA,outB; - wire [3:0] poutA,poutB; - - initial begin - // $dumpfile("testbench.vcd"); - // $dumpvars(0, testbench); - - #5 in = 0; - repeat (10000) begin - #5 in = in + 1; - end - - $display("OKAY"); - end - - top uut ( - .x(in[3:0]), - .y(in[7:4]), - .A(outA), - .B(outB) - ); - - - assign poutA = in[3:0] + in[7:4]; - assign poutB = in[3:0] - in[7:4]; - - check_comb add_test(outA, poutA); - check_comb sub_test(outB, poutB); - assert_comb sub0_test(outB[2], poutB[2]); - -endmodule - -module check_comb(input [3:0] test, input [3:0] pat); - always @* - begin - #1; - if (test != pat) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",test," ",pat); - $stop; - end - end -endmodule - diff --git a/tests/ice40/common.v b/tests/ice40/common.v deleted file mode 100644 index 5446f0817..000000000 --- a/tests/ice40/common.v +++ /dev/null @@ -1,47 +0,0 @@ -module assert_dff(input clk, input test, input pat); - always @(posedge clk) - begin - #1; - if (test != pat) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time); - $stop; - end - end -endmodule - -module assert_tri(input en, input A, input B); - always @(posedge en) - begin - #1; - if (A !== B) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); - $stop; - end - end -endmodule - -module assert_Z(input clk, input A); - always @(posedge clk) - begin - #1; - if (A === 1'bZ) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A); - $stop; - end - end -endmodule - -module assert_comb(input A, input B); - always @(*) - begin - #1; - if (A !== B) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); - $stop; - end - end -endmodule diff --git a/tests/ice40/dffs_top.v b/tests/ice40/dffs.v similarity index 100% rename from tests/ice40/dffs_top.v rename to tests/ice40/dffs.v diff --git a/tests/ice40/dffs.ys b/tests/ice40/dffs.ys index 68410b4d8..09b7bc25a 100644 --- a/tests/ice40/dffs.ys +++ b/tests/ice40/dffs.ys @@ -1,5 +1,12 @@ -equiv_opt -map ../../techlibs/ice40/cells_sim.v synth_ice40 +proc +flatten +dff2dffe synth_ice40 +#equiv_opt -assert -map +/ice40/cells_sim.v -map +/simcells.v synth_ice40 +equiv_opt -map +/ice40/cells_sim.v -map +/simcells.v synth_ice40 +design -load postopt select -assert-count 2 t:SB_DFFR select -assert-count 1 t:SB_DFFE -write_verilog ./temp/dffs_synth.v +select -assert-count 4 t:SB_LUT4 +select -assert-count 1 t:$_DFFSR_PPP_ +select -assert-count 1 t:$_DFFSR_NPP_ diff --git a/tests/ice40/dffs_tb.v b/tests/ice40/dffs_tb.v deleted file mode 100644 index ed8f2eb2a..000000000 --- a/tests/ice40/dffs_tb.v +++ /dev/null @@ -1,77 +0,0 @@ -module testbench; - reg clk; - - initial begin - // $dumpfile("testbench.vcd"); - // $dumpvars(0, testbench); - - #5 clk = 0; - repeat (10000) begin - #5 clk = 1; - #5 clk = 0; - end - - $display("OKAY"); - end - - - reg [2:0] dinA = 0; - wire doutB,doutB1,doutB2,doutB3,doutB4; - reg dff,ndff,adff,adffn,dffe = 0; - - top uut ( - .clk (clk ), - .a (dinA[0] ), - .pre (dinA[1] ), - .clr (dinA[2] ), - .b (doutB ), - .b1 (doutB1 ), - .b2 (doutB2 ), - .b3 (doutB3 ), - .b4 (doutB4 ) - ); - - always @(posedge clk) begin - #3; - dinA <= dinA + 1; - end - - always @( posedge clk, posedge dinA[1], posedge dinA[2] ) - if ( dinA[2] ) - dff <= 1'b0; - else if ( dinA[1] ) - dff <= 1'b1; - else - dff <= dinA[0]; - - always @( negedge clk, negedge dinA[1], negedge dinA[2] ) - if ( !dinA[2] ) - ndff <= 1'b0; - else if ( !dinA[1] ) - ndff <= 1'b1; - else - ndff <= dinA[0]; - - always @( posedge clk, posedge dinA[2] ) - if ( dinA[2] ) - adff <= 1'b0; - else - adff <= dinA[0]; - - always @( posedge clk, negedge dinA[2] ) - if ( !dinA[2] ) - adffn <= 1'b0; - else - adffn <= dinA[0]; - - always @( posedge clk ) - if ( dinA[2] ) - dffe <= dinA[0]; - - assert_dff dff_test(.clk(clk), .test(doutB), .pat(dff)); - assert_dff ndff_test(.clk(clk), .test(doutB1), .pat(ndff)); - assert_dff adff_test(.clk(clk), .test(doutB2), .pat(adff)); - assert_dff adffn_test(.clk(clk), .test(doutB3), .pat(adffn)); - assert_dff dffe_test(.clk(clk), .test(doutB4), .pat(dffe)); - -endmodule diff --git a/tests/ice40/div_mod_top.v b/tests/ice40/div_mod.v similarity index 100% rename from tests/ice40/div_mod_top.v rename to tests/ice40/div_mod.v diff --git a/tests/ice40/div_mod.ys b/tests/ice40/div_mod.ys index 28f31136b..f66cb99dd 100644 --- a/tests/ice40/div_mod.ys +++ b/tests/ice40/div_mod.ys @@ -1,5 +1,6 @@ synth_ice40 -equiv_opt -map ../../techlibs/ice40/cells_sim.v synth_ice40 -select -assert-count 89 t:SB_LUT4 -select -assert-count 66 t:SB_CARRY -write_verilog ./temp/div_mod_synth.v +#equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 +equiv_opt -map +/ice40/cells_sim.v synth_ice40 +design -load postopt +select -assert-count 85 t:SB_LUT4 +select -assert-count 54 t:SB_CARRY diff --git a/tests/ice40/div_mod_tb.v b/tests/ice40/div_mod_tb.v deleted file mode 100644 index 4296535c9..000000000 --- a/tests/ice40/div_mod_tb.v +++ /dev/null @@ -1,48 +0,0 @@ -module testbench; - reg [7:0] in; - - wire [3:0] outA,outB; - wire [3:0] poutA,poutB; - - initial begin - // $dumpfile("testbench.vcd"); - // $dumpvars(0, testbench); - - #5 in = 0; - repeat (10000) begin - #5 in = in + 1; - end - - $display("OKAY"); - end - - top uut ( - .x(in[3:0]), - .y(in[7:4]), - .A(outA), - .B(outB) - ); - - - assign poutA = in[3:0] % in[7:4]; - assign poutB = in[3:0] / in[7:4]; - - check_comb mod_test(in[7:4], outA, poutA); - check_comb div_test(in[7:4], outB, poutB); - //assert_comb div2_test(outB[2], poutB[2]); - -endmodule - -module check_comb(input [3:0] divisor, input [3:0] test, input [3:0] pat); - always @* - begin - #1; - if (divisor != 4'b0000) - if (test !== pat) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",test," ",pat); - $stop; - end - end -endmodule - diff --git a/tests/ice40/latches_top.v b/tests/ice40/latches.v similarity index 100% rename from tests/ice40/latches_top.v rename to tests/ice40/latches.v diff --git a/tests/ice40/latches.ys b/tests/ice40/latches.ys index 250ea0f84..77037b1d5 100644 --- a/tests/ice40/latches.ys +++ b/tests/ice40/latches.ys @@ -1,5 +1,6 @@ synth_ice40 -equiv_opt -map ../../techlibs/ice40/cells_sim.v synth_ice40 +#equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 +equiv_opt -map +/ice40/cells_sim.v synth_ice40 +design -load postopt proc select -assert-count 5 t:SB_LUT4 -write_verilog ./temp/latches_synth.v diff --git a/tests/ice40/latches_tb.v b/tests/ice40/latches_tb.v deleted file mode 100644 index 47ae8670c..000000000 --- a/tests/ice40/latches_tb.v +++ /dev/null @@ -1,59 +0,0 @@ -module testbench; - reg clk; - - initial begin - // $dumpfile("testbench.vcd"); - // $dumpvars(0, testbench); - - #5 clk = 0; - repeat (10000) begin - #5 clk = 1; - #5 clk = 0; - end - - $display("OKAY"); - end - - - reg [2:0] dinA = 0; - wire doutB,doutB1,doutB2; - reg lat,latn,latsr = 0; - - top uut ( - .clk (clk ), - .a (dinA[0] ), - .pre (dinA[1] ), - .clr (dinA[2] ), - .b (doutB ), - .b1 (doutB1 ), - .b2 (doutB2 ) - ); - - always @(posedge clk) begin - #3; - dinA <= dinA + 1; - end - - always @* - if ( clk ) - lat <= dinA[0]; - - - always @* - if ( !clk ) - latn <= dinA[0]; - - - always @* - if ( dinA[2] ) - latsr <= 1'b0; - else if ( dinA[1] ) - latsr <= 1'b1; - else if ( clk ) - latsr <= dinA[0]; - - assert_dff lat_test(.clk(clk), .test(doutB), .pat(lat)); - assert_dff latn_test(.clk(clk), .test(doutB1), .pat(latn)); - assert_dff latsr_test(.clk(clk), .test(doutB2), .pat(latsr)); - -endmodule diff --git a/tests/ice40/memory_top.v b/tests/ice40/memory.v similarity index 100% rename from tests/ice40/memory_top.v rename to tests/ice40/memory.v diff --git a/tests/ice40/memory.ys b/tests/ice40/memory.ys index 0f030d77d..47d5526c1 100644 --- a/tests/ice40/memory.ys +++ b/tests/ice40/memory.ys @@ -1,7 +1,8 @@ proc memory -equiv_opt -map ../../techlibs/ice40/cells_sim.v synth_ice40 synth_ice40 +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 +design -load postopt + select -assert-count 8 t:SB_DFF select -assert-count 512 t:SB_DFFE -write_verilog ./temp/memory_synth.v diff --git a/tests/ice40/memory_tb.v b/tests/ice40/memory_tb.v deleted file mode 100644 index 5905f3ddd..000000000 --- a/tests/ice40/memory_tb.v +++ /dev/null @@ -1,81 +0,0 @@ -module testbench; - reg clk; - - initial begin - // $dumpfile("testbench.vcd"); - // $dumpvars(0, testbench); - - #5 clk = 0; - repeat (10000) begin - #5 clk = 1; - #5 clk = 0; - end - - $display("OKAY"); - end - - - reg [7:0] data_a = 0; - reg [5:0] addr_a = 0; - reg we_a = 0; - reg re_a = 1; - wire [7:0] q_a; - reg mem_init = 0; - - reg [7:0] pq_a; - - top uut ( - .data_a(data_a), - .addr_a(addr_a), - .we_a(we_a), - .clk(clk), - .q_a(q_a) - ); - - always @(posedge clk) begin - #3; - data_a <= data_a + 17; - - addr_a <= addr_a + 1; - end - - always @(posedge addr_a) begin - #10; - if(addr_a > 6'h3E) - mem_init <= 1; - end - - always @(posedge clk) begin - //#3; - we_a <= !we_a; - end - - // Declare the RAM variable for check - reg [7:0] ram[63:0]; - - // Port A for check - always @ (posedge clk) - begin - if (we_a) - begin - ram[addr_a] <= data_a; - pq_a <= data_a; - end - pq_a <= ram[addr_a]; - end - - uut_mem_checker port_a_test(.clk(clk), .init(mem_init), .en(!we_a), .A(q_a), .B(pq_a)); - -endmodule - -module uut_mem_checker(input clk, input init, input en, input [7:0] A, input [7:0] B); - always @(posedge clk) - begin - #1; - if (en == 1 & init == 1 & A !== B) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); - $stop; - end - end -endmodule diff --git a/tests/ice40/mul_pow_top.v b/tests/ice40/mul_pow.v similarity index 100% rename from tests/ice40/mul_pow_top.v rename to tests/ice40/mul_pow.v diff --git a/tests/ice40/mul_pow.ys b/tests/ice40/mul_pow.ys index 486480506..2a6baa738 100644 --- a/tests/ice40/mul_pow.ys +++ b/tests/ice40/mul_pow.ys @@ -1,6 +1,7 @@ -equiv_opt -map ../../techlibs/ice40/cells_sim.v synth_ice40 synth_ice40 -select -assert-count 15 t:SB_LUT4 +#equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 +equiv_opt -map +/ice40/cells_sim.v synth_ice40 +design -load postopt +select -assert-count 16 t:SB_LUT4 select -assert-count 4 t:SB_CARRY select -assert-count 1 t:$pow -write_verilog ./temp/mul_pow_synth.v diff --git a/tests/ice40/mul_pow_tb.v b/tests/ice40/mul_pow_tb.v deleted file mode 100644 index 7e888474f..000000000 --- a/tests/ice40/mul_pow_tb.v +++ /dev/null @@ -1,47 +0,0 @@ -module testbench; - reg [7:0] in; - - wire [3:0] outA,outB; - wire [3:0] poutA,poutB; - - initial begin - // $dumpfile("testbench.vcd"); - // $dumpvars(0, testbench); - - #5 in = 0; - repeat (10000) begin - #5 in = in + 1; - end - - $display("OKAY"); - end - - top uut ( - .x(in[3:0]), - .y(in[7:4]), - .A(outA), - .B(outB) - ); - - - assign poutA = in[3:0] * in[7:4]; - assign poutB = in[3:0] ** in[7:4]; - - check_comb mul_test(outA, poutA); - check_comb pow_test(outB, poutB); - assert_comb pow2_test(outB[2], poutB[2]); - -endmodule - -module check_comb(input [3:0] test, input [3:0] pat); - always @* - begin - #1; - if (test !== pat) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",test," ",pat); - $stop; - end - end -endmodule - diff --git a/tests/ice40/mux_top.v b/tests/ice40/mux.v similarity index 100% rename from tests/ice40/mux_top.v rename to tests/ice40/mux.v diff --git a/tests/ice40/mux.ys b/tests/ice40/mux.ys index 5ae5a1f33..3da9ef433 100644 --- a/tests/ice40/mux.ys +++ b/tests/ice40/mux.ys @@ -1,5 +1,6 @@ -equiv_opt -map ../../techlibs/ice40/cells_sim.v synth_ice40 + synth_ice40 +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 +design -load postopt select -assert-count 20 t:SB_LUT4 select -assert-count 1 t:SB_CARRY -write_verilog ./temp/mux_synth.v diff --git a/tests/ice40/mux_tb.v b/tests/ice40/mux_tb.v deleted file mode 100644 index 2b2da25e9..000000000 --- a/tests/ice40/mux_tb.v +++ /dev/null @@ -1,43 +0,0 @@ -module testbench; - reg clk; - - initial begin - // $dumpfile("testbench.vcd"); - // $dumpvars(0, testbench); - - #5 clk = 0; - repeat (10000) begin - #5 clk = 1; - #5 clk = 0; - end - - $display("OKAY"); - end - - - reg [15:0] D = 1; - reg [3:0] S = 0; - wire M2,M4,M8,M16; - - top uut ( - .S (S ), - .D (D ), - .M2 (M2 ), - .M4 (M4 ), - .M8 (M8 ), - .M16 (M16 ) - ); - - always @(posedge clk) begin - //#3; - D <= {D[14:0],D[15]}; - //D <= D <<< 1; - S <= S + 1; - end - - assert_tri m2_test(.en(clk), .A(D[0]|D[1]), .B(M2)); - assert_tri m4_test(.en(clk), .A(D[0]|D[1]|D[2]|D[3]), .B(M4)); - assert_tri m8_test(.en(clk), .A(!S[3]), .B(M8)); - assert_tri m16_test(.en(clk), .A(1'b1), .B(M16)); - -endmodule diff --git a/tests/ice40/run-test.sh b/tests/ice40/run-test.sh index e839aa9f5..75e5f0609 100755 --- a/tests/ice40/run-test.sh +++ b/tests/ice40/run-test.sh @@ -1,21 +1,6 @@ #!/bin/bash set -e -if [ -f "../../../../../techlibs/common/simcells.v" ]; then - COMMON_PREFIX=../../../../../techlibs/common - TECHLIBS_PREFIX=../../../../../techlibs -else - COMMON_PREFIX=/usr/local/share/yosys - TECHLIBS_PREFIX=/usr/local/share/yosys -fi -for x in *_top.v; do +for x in *.v; do echo "Running $x.." - ../../yosys -q -s ${x%_top.v}.ys -l ./temp/${x%.v}.log $x - echo "Simulating $x.." - iverilog -o ./temp/${x%_top.v}_testbench ${x%_top.v}_tb.v ./temp/${x%_top.v}_synth.v common.v $COMMON_PREFIX/simcells.v $TECHLIBS_PREFIX/ice40/cells_sim.v - if ! vvp -N ./temp/${x%_top.v}_testbench > ./temp/${x%_top.v}_testbench.log 2>&1; then - grep 'ERROR' ./temp/${x%_top.v}_testbench.log - exit 0 - elif grep 'ERROR' ./temp/${x%_top.v}_testbench.log || ! grep 'OKAY' ./temp/${x%_top.v}_testbench.log; then - exit 0 - fi + ../../yosys -q -s ${x%.v}.ys -l ./temp/${x%.v}.log $x done diff --git a/tests/ice40/tribuf_top.v b/tests/ice40/tribuf.v similarity index 100% rename from tests/ice40/tribuf_top.v rename to tests/ice40/tribuf.v diff --git a/tests/ice40/tribuf.ys b/tests/ice40/tribuf.ys index 40ded734d..b319e6622 100644 --- a/tests/ice40/tribuf.ys +++ b/tests/ice40/tribuf.ys @@ -1,6 +1,6 @@ -equiv_opt -map ../../techlibs/ice40/cells_sim.v synth_ice40 synth_ice40 +equiv_opt -assert -map +/ice40/cells_sim.v -map +/simcells.v synth_ice40 +design -load postopt select -assert-count 1 t:SB_LUT4 select -assert-count 1 t:SB_CARRY select -assert-count 1 t:$_TBUF_ -write_verilog ./temp/tribuf_synth.v diff --git a/tests/ice40/tribuf_tb.v b/tests/ice40/tribuf_tb.v deleted file mode 100644 index 16871b7b2..000000000 --- a/tests/ice40/tribuf_tb.v +++ /dev/null @@ -1,34 +0,0 @@ -module testbench; - reg en; - - initial begin - // $dumpfile("testbench.vcd"); - // $dumpvars(0, testbench); - - #5 en = 0; - repeat (10000) begin - #5 en = 1; - #5 en = 0; - end - - $display("OKAY"); - end - - - reg dinA = 0; - wire doutB; - - top uut ( - .en (en ), - .a (dinA ), - .b (doutB ) - ); - - always @(posedge en) begin - #3; - dinA <= !dinA; - end - - assert_tri b_test(.en(en), .A(dinA), .B(doutB)); - -endmodule From b835ec37cbb56bc3b55fe53eb85375ad5ac98f27 Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Wed, 21 Aug 2019 07:53:34 +0300 Subject: [PATCH 003/130] Add temp directory --- tests/ice40/temp/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/ice40/temp/.gitignore diff --git a/tests/ice40/temp/.gitignore b/tests/ice40/temp/.gitignore new file mode 100644 index 000000000..397b4a762 --- /dev/null +++ b/tests/ice40/temp/.gitignore @@ -0,0 +1 @@ +*.log From d945b8a357c567f5f3565983da09f24c0f295461 Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Wed, 21 Aug 2019 21:52:07 +0300 Subject: [PATCH 004/130] Fix all comments from PR --- tests/ice40/add_sub.ys | 17 +++-- tests/ice40/adffs.v | 108 +++++++++++++++++++++++++++++++ tests/ice40/adffs.ys | 9 +++ tests/ice40/adffs_tb.v | 75 +++++++++++++++++++++ tests/ice40/common.v | 47 ++++++++++++++ tests/ice40/dffs.v | 107 +----------------------------- tests/ice40/dffs.ys | 17 +++-- tests/ice40/div_mod.ys | 15 +++-- tests/ice40/latches.ys | 7 +- tests/ice40/latches_tb.v | 59 +++++++++++++++++ tests/ice40/memory.ys | 10 +-- tests/ice40/memory_tb.v | 81 +++++++++++++++++++++++ tests/ice40/{mul_pow.v => mul.v} | 1 - tests/ice40/mul.ys | 9 +++ tests/ice40/mul_pow.ys | 7 -- tests/ice40/mux.ys | 2 +- tests/ice40/run-test.sh | 35 ++++++++-- tests/ice40/temp/.gitignore | 1 - tests/ice40/tribuf.v | 6 +- tests/ice40/tribuf.ys | 12 ++-- 20 files changed, 465 insertions(+), 160 deletions(-) create mode 100644 tests/ice40/adffs.v create mode 100644 tests/ice40/adffs.ys create mode 100644 tests/ice40/adffs_tb.v create mode 100644 tests/ice40/common.v create mode 100644 tests/ice40/latches_tb.v create mode 100644 tests/ice40/memory_tb.v rename tests/ice40/{mul_pow.v => mul.v} (85%) create mode 100644 tests/ice40/mul.ys delete mode 100644 tests/ice40/mul_pow.ys delete mode 100644 tests/ice40/temp/.gitignore diff --git a/tests/ice40/add_sub.ys b/tests/ice40/add_sub.ys index c2ee3a843..84f31ec53 100644 --- a/tests/ice40/add_sub.ys +++ b/tests/ice40/add_sub.ys @@ -1,7 +1,10 @@ -synth_ice40 -equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -design -load postopt -select -assert-count 12 t:SB_LUT4 -select -assert-count 7 t:SB_CARRY -select -assert-count 2 t:$logic_and -select -assert-count 2 t:$logic_or +read_verilog add_sub.v +hierarchy -top top +synth -flatten -run coarse # technology-independent coarse grained synthesis +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check same as technology-dependent fine-grained synthesis +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 11 t:SB_LUT4 +select -assert-count 6 t:SB_CARRY +select -assert-none t:SB_LUT4 t:SB_CARRY %% t:* %D + diff --git a/tests/ice40/adffs.v b/tests/ice40/adffs.v new file mode 100644 index 000000000..af7022c79 --- /dev/null +++ b/tests/ice40/adffs.v @@ -0,0 +1,108 @@ +module adff + ( input d, clk, clr, output reg q ); + initial begin + q = 0; + end + always @( posedge clk, posedge clr ) + if ( clr ) + q <= 1'b0; + else + q <= d; +endmodule + +module adffn + ( input d, clk, clr, output reg q ); + initial begin + q = 0; + end + always @( posedge clk, negedge clr ) + if ( !clr ) + q <= 1'b0; + else + q <= d; +endmodule + +module dffe + ( input d, clk, en, output reg q ); + initial begin + q = 0; + end + always @( posedge clk ) + if ( en ) + q <= d; +endmodule + +module dffsr + ( input d, clk, pre, clr, output reg q ); + initial begin + q = 0; + end + always @( posedge clk, posedge pre, posedge clr ) + if ( clr ) + q <= 1'b0; + else if ( pre ) + q <= 1'b1; + else + q <= d; +endmodule + +module ndffnsnr + ( input d, clk, pre, clr, output reg q ); + initial begin + q = 0; + end + always @( negedge clk, negedge pre, negedge clr ) + if ( !clr ) + q <= 1'b0; + else if ( !pre ) + q <= 1'b1; + else + q <= d; +endmodule + +module top ( +input clk, +input clr, +input pre, +input a, +output b,b1,b2,b3,b4 +); + +dffsr u_dffsr ( + .clk (clk ), + .clr (clr), + .pre (pre), + .d (a ), + .q (b ) + ); + +ndffnsnr u_ndffnsnr ( + .clk (clk ), + .clr (clr), + .pre (pre), + .d (a ), + .q (b1 ) + ); + +adff u_adff ( + .clk (clk ), + .clr (clr), + .d (a ), + .q (b2 ) + ); + +adffn u_adffn ( + .clk (clk ), + .clr (clr), + .d (a ), + .q (b3 ) + ); + +dffe u_dffe ( + .clk (clk ), + .en (clr), + .d (a ), + .q (b4 ) + ); + +endmodule diff --git a/tests/ice40/adffs.ys b/tests/ice40/adffs.ys new file mode 100644 index 000000000..aee8cd6b4 --- /dev/null +++ b/tests/ice40/adffs.ys @@ -0,0 +1,9 @@ +read_verilog adffs.v +proc +dff2dffe +synth_ice40 +select -assert-count 2 t:SB_DFFR +select -assert-count 1 t:SB_DFFE +select -assert-count 4 t:SB_LUT4 +#select -assert-none t:SB_LUT4 t:SB_DFFR t:SB_DFFE t:$_DFFSR_NPP_ t:$_DFFSR_PPP_ %% t:* %D +write_verilog adffs_synth.v diff --git a/tests/ice40/adffs_tb.v b/tests/ice40/adffs_tb.v new file mode 100644 index 000000000..e049edabc --- /dev/null +++ b/tests/ice40/adffs_tb.v @@ -0,0 +1,75 @@ +module testbench; + reg clk; + + initial begin + // $dumpfile("testbench.vcd"); + // $dumpvars(0, testbench); + + #5 clk = 0; + repeat (10000) begin + #5 clk = 1; + #5 clk = 0; + end + + $display("OKAY"); + end + + + reg [2:0] dinA = 0; + wire doutB,doutB1,doutB2,doutB3,doutB4; + reg dff,ndff,adff,adffn,dffe = 0; + + top uut ( + .clk (clk ), + .a (dinA[0] ), + .pre (dinA[1] ), + .clr (dinA[2] ), + .b (doutB ), + .b1 (doutB1 ), + .b2 (doutB2 ) + ); + + always @(posedge clk) begin + #3; + dinA <= dinA + 1; + end + + always @( posedge clk, posedge dinA[1], posedge dinA[2] ) + if ( dinA[2] ) + dff <= 1'b0; + else if ( dinA[1] ) + dff <= 1'b1; + else + dff <= dinA[0]; + + always @( negedge clk, negedge dinA[1], negedge dinA[2] ) + if ( !dinA[2] ) + ndff <= 1'b0; + else if ( !dinA[1] ) + ndff <= 1'b1; + else + ndff <= dinA[0]; + + always @( posedge clk, posedge dinA[2] ) + if ( dinA[2] ) + adff <= 1'b0; + else + adff <= dinA[0]; + + always @( posedge clk, negedge dinA[2] ) + if ( !dinA[2] ) + adffn <= 1'b0; + else + adffn <= dinA[0]; + + always @( posedge clk ) + if ( dinA[2] ) + dffe <= dinA[0]; + + assert_dff dff_test(.clk(clk), .test(doutB), .pat(dff)); + assert_dff ndff_test(.clk(clk), .test(doutB1), .pat(ndff)); + assert_dff adff_test(.clk(clk), .test(doutB2), .pat(adff)); + //assert_dff adffn_test(.clk(clk), .test(doutB3), .pat(adffn)); + //assert_dff dffe_test(.clk(clk), .test(doutB4), .pat(dffe)); + +endmodule diff --git a/tests/ice40/common.v b/tests/ice40/common.v new file mode 100644 index 000000000..5446f0817 --- /dev/null +++ b/tests/ice40/common.v @@ -0,0 +1,47 @@ +module assert_dff(input clk, input test, input pat); + always @(posedge clk) + begin + #1; + if (test != pat) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time); + $stop; + end + end +endmodule + +module assert_tri(input en, input A, input B); + always @(posedge en) + begin + #1; + if (A !== B) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); + $stop; + end + end +endmodule + +module assert_Z(input clk, input A); + always @(posedge clk) + begin + #1; + if (A === 1'bZ) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A); + $stop; + end + end +endmodule + +module assert_comb(input A, input B); + always @(*) + begin + #1; + if (A !== B) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); + $stop; + end + end +endmodule diff --git a/tests/ice40/dffs.v b/tests/ice40/dffs.v index af7022c79..d57c8c97c 100644 --- a/tests/ice40/dffs.v +++ b/tests/ice40/dffs.v @@ -1,108 +1,5 @@ -module adff - ( input d, clk, clr, output reg q ); - initial begin - q = 0; - end - always @( posedge clk, posedge clr ) - if ( clr ) - q <= 1'b0; - else - q <= d; -endmodule - -module adffn - ( input d, clk, clr, output reg q ); - initial begin - q = 0; - end - always @( posedge clk, negedge clr ) - if ( !clr ) - q <= 1'b0; - else - q <= d; -endmodule - -module dffe - ( input d, clk, en, output reg q ); - initial begin - q = 0; - end +module top + ( input d, clk, output reg q ); always @( posedge clk ) - if ( en ) - q <= d; -endmodule - -module dffsr - ( input d, clk, pre, clr, output reg q ); - initial begin - q = 0; - end - always @( posedge clk, posedge pre, posedge clr ) - if ( clr ) - q <= 1'b0; - else if ( pre ) - q <= 1'b1; - else q <= d; endmodule - -module ndffnsnr - ( input d, clk, pre, clr, output reg q ); - initial begin - q = 0; - end - always @( negedge clk, negedge pre, negedge clr ) - if ( !clr ) - q <= 1'b0; - else if ( !pre ) - q <= 1'b1; - else - q <= d; -endmodule - -module top ( -input clk, -input clr, -input pre, -input a, -output b,b1,b2,b3,b4 -); - -dffsr u_dffsr ( - .clk (clk ), - .clr (clr), - .pre (pre), - .d (a ), - .q (b ) - ); - -ndffnsnr u_ndffnsnr ( - .clk (clk ), - .clr (clr), - .pre (pre), - .d (a ), - .q (b1 ) - ); - -adff u_adff ( - .clk (clk ), - .clr (clr), - .d (a ), - .q (b2 ) - ); - -adffn u_adffn ( - .clk (clk ), - .clr (clr), - .d (a ), - .q (b3 ) - ); - -dffe u_dffe ( - .clk (clk ), - .en (clr), - .d (a ), - .q (b4 ) - ); - -endmodule diff --git a/tests/ice40/dffs.ys b/tests/ice40/dffs.ys index 09b7bc25a..0fa0bc3eb 100644 --- a/tests/ice40/dffs.ys +++ b/tests/ice40/dffs.ys @@ -1,12 +1,11 @@ +read_verilog dffs.v proc flatten dff2dffe -synth_ice40 -#equiv_opt -assert -map +/ice40/cells_sim.v -map +/simcells.v synth_ice40 -equiv_opt -map +/ice40/cells_sim.v -map +/simcells.v synth_ice40 -design -load postopt -select -assert-count 2 t:SB_DFFR -select -assert-count 1 t:SB_DFFE -select -assert-count 4 t:SB_LUT4 -select -assert-count 1 t:$_DFFSR_PPP_ -select -assert-count 1 t:$_DFFSR_NPP_ +hierarchy -top top +synth -flatten -run coarse # technology-independent coarse grained synthesis +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check same as technology-dependent fine-grained synthesis +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 1 t:SB_DFF +select -assert-none t:SB_DFF %% t:* %D diff --git a/tests/ice40/div_mod.ys b/tests/ice40/div_mod.ys index f66cb99dd..93285cede 100644 --- a/tests/ice40/div_mod.ys +++ b/tests/ice40/div_mod.ys @@ -1,6 +1,9 @@ -synth_ice40 -#equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -equiv_opt -map +/ice40/cells_sim.v synth_ice40 -design -load postopt -select -assert-count 85 t:SB_LUT4 -select -assert-count 54 t:SB_CARRY +read_verilog div_mod.v +hierarchy -top top +synth -flatten -run coarse # technology-independent coarse grained synthesis +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check same as technology-dependent fine-grained synthesis +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 88 t:SB_LUT4 +select -assert-count 65 t:SB_CARRY +select -assert-none t:SB_LUT4 t:SB_CARRY %% t:* %D diff --git a/tests/ice40/latches.ys b/tests/ice40/latches.ys index 77037b1d5..0abd7f195 100644 --- a/tests/ice40/latches.ys +++ b/tests/ice40/latches.ys @@ -1,6 +1,5 @@ +read_verilog latches.v synth_ice40 -#equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -equiv_opt -map +/ice40/cells_sim.v synth_ice40 -design -load postopt -proc select -assert-count 5 t:SB_LUT4 +#select -assert-none t:SB_LUT4 %% t:* %D +write_verilog latches_synth.v diff --git a/tests/ice40/latches_tb.v b/tests/ice40/latches_tb.v new file mode 100644 index 000000000..47ae8670c --- /dev/null +++ b/tests/ice40/latches_tb.v @@ -0,0 +1,59 @@ +module testbench; + reg clk; + + initial begin + // $dumpfile("testbench.vcd"); + // $dumpvars(0, testbench); + + #5 clk = 0; + repeat (10000) begin + #5 clk = 1; + #5 clk = 0; + end + + $display("OKAY"); + end + + + reg [2:0] dinA = 0; + wire doutB,doutB1,doutB2; + reg lat,latn,latsr = 0; + + top uut ( + .clk (clk ), + .a (dinA[0] ), + .pre (dinA[1] ), + .clr (dinA[2] ), + .b (doutB ), + .b1 (doutB1 ), + .b2 (doutB2 ) + ); + + always @(posedge clk) begin + #3; + dinA <= dinA + 1; + end + + always @* + if ( clk ) + lat <= dinA[0]; + + + always @* + if ( !clk ) + latn <= dinA[0]; + + + always @* + if ( dinA[2] ) + latsr <= 1'b0; + else if ( dinA[1] ) + latsr <= 1'b1; + else if ( clk ) + latsr <= dinA[0]; + + assert_dff lat_test(.clk(clk), .test(doutB), .pat(lat)); + assert_dff latn_test(.clk(clk), .test(doutB1), .pat(latn)); + assert_dff latsr_test(.clk(clk), .test(doutB2), .pat(latsr)); + +endmodule diff --git a/tests/ice40/memory.ys b/tests/ice40/memory.ys index 47d5526c1..a0391e93d 100644 --- a/tests/ice40/memory.ys +++ b/tests/ice40/memory.ys @@ -1,8 +1,4 @@ -proc -memory +read_verilog memory.v synth_ice40 -equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -design -load postopt - -select -assert-count 8 t:SB_DFF -select -assert-count 512 t:SB_DFFE +select -assert-count 1 t:SB_RAM40_4K +write_verilog memory_synth.v diff --git a/tests/ice40/memory_tb.v b/tests/ice40/memory_tb.v new file mode 100644 index 000000000..5905f3ddd --- /dev/null +++ b/tests/ice40/memory_tb.v @@ -0,0 +1,81 @@ +module testbench; + reg clk; + + initial begin + // $dumpfile("testbench.vcd"); + // $dumpvars(0, testbench); + + #5 clk = 0; + repeat (10000) begin + #5 clk = 1; + #5 clk = 0; + end + + $display("OKAY"); + end + + + reg [7:0] data_a = 0; + reg [5:0] addr_a = 0; + reg we_a = 0; + reg re_a = 1; + wire [7:0] q_a; + reg mem_init = 0; + + reg [7:0] pq_a; + + top uut ( + .data_a(data_a), + .addr_a(addr_a), + .we_a(we_a), + .clk(clk), + .q_a(q_a) + ); + + always @(posedge clk) begin + #3; + data_a <= data_a + 17; + + addr_a <= addr_a + 1; + end + + always @(posedge addr_a) begin + #10; + if(addr_a > 6'h3E) + mem_init <= 1; + end + + always @(posedge clk) begin + //#3; + we_a <= !we_a; + end + + // Declare the RAM variable for check + reg [7:0] ram[63:0]; + + // Port A for check + always @ (posedge clk) + begin + if (we_a) + begin + ram[addr_a] <= data_a; + pq_a <= data_a; + end + pq_a <= ram[addr_a]; + end + + uut_mem_checker port_a_test(.clk(clk), .init(mem_init), .en(!we_a), .A(q_a), .B(pq_a)); + +endmodule + +module uut_mem_checker(input clk, input init, input en, input [7:0] A, input [7:0] B); + always @(posedge clk) + begin + #1; + if (en == 1 & init == 1 & A !== B) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); + $stop; + end + end +endmodule diff --git a/tests/ice40/mul_pow.v b/tests/ice40/mul.v similarity index 85% rename from tests/ice40/mul_pow.v rename to tests/ice40/mul.v index 6c256d96b..c099db0d9 100644 --- a/tests/ice40/mul_pow.v +++ b/tests/ice40/mul.v @@ -8,6 +8,5 @@ module top ); assign A = x * y; -assign B = x ** y; endmodule diff --git a/tests/ice40/mul.ys b/tests/ice40/mul.ys new file mode 100644 index 000000000..35048d14a --- /dev/null +++ b/tests/ice40/mul.ys @@ -0,0 +1,9 @@ +read_verilog mul.v +hierarchy -top top +synth -flatten -run coarse # technology-independent coarse grained synthesis +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -dsp # equivalency check same as technology-dependent fine-grained synthesis +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 15 t:SB_LUT4 +select -assert-count 3 t:SB_CARRY +select -assert-none t:SB_LUT4 t:SB_CARRY %% t:* %D diff --git a/tests/ice40/mul_pow.ys b/tests/ice40/mul_pow.ys deleted file mode 100644 index 2a6baa738..000000000 --- a/tests/ice40/mul_pow.ys +++ /dev/null @@ -1,7 +0,0 @@ -synth_ice40 -#equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -equiv_opt -map +/ice40/cells_sim.v synth_ice40 -design -load postopt -select -assert-count 16 t:SB_LUT4 -select -assert-count 4 t:SB_CARRY -select -assert-count 1 t:$pow diff --git a/tests/ice40/mux.ys b/tests/ice40/mux.ys index 3da9ef433..9e3d87b7f 100644 --- a/tests/ice40/mux.ys +++ b/tests/ice40/mux.ys @@ -1,4 +1,4 @@ - +read_verilog mux.v synth_ice40 equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 design -load postopt diff --git a/tests/ice40/run-test.sh b/tests/ice40/run-test.sh index 75e5f0609..5bd9fb173 100755 --- a/tests/ice40/run-test.sh +++ b/tests/ice40/run-test.sh @@ -1,6 +1,33 @@ -#!/bin/bash set -e -for x in *.v; do - echo "Running $x.." - ../../yosys -q -s ${x%.v}.ys -l ./temp/${x%.v}.log $x +if [ -f "../../../../../techlibs/common/simcells.v" ]; then + COMMON_PREFIX=../../../../../techlibs/common + TECHLIBS_PREFIX=../../../../../techlibs +else + COMMON_PREFIX=/usr/local/share/yosys + TECHLIBS_PREFIX=/usr/local/share/yosys +fi +{ +echo "all::" +for x in *.ys; do + echo "all:: run-$x" + echo "run-$x:" + echo " @echo 'Running $x..'" + echo " @../../yosys -ql ${x%.ys}.log $x" done +for t in *_tb.v; do + echo "all:: run-$t" + echo "run-$t:" + echo " @echo 'Running $t..'" + echo " @iverilog -o ${t%_tb.v}_testbench $t ${t%_tb.v}_synth.v common.v $COMMON_PREFIX/simcells.v $TECHLIBS_PREFIX/ice40/cells_sim.v" + echo " @if ! vvp -N ${t%_tb.v}_testbench > ${t%_tb.v}_testbench.log 2>&1; then grep 'ERROR' ${t%_tb.v}_testbench.log; exit 0; elif grep 'ERROR' ${t%_tb.v}_testbench.log || ! grep 'OKAY' ${t%_tb.v}_testbench.log; then echo "FAIL"; exit 0; fi" +done +for s in *.sh; do + if [ "$s" != "run-test.sh" ]; then + echo "all:: run-$s" + echo "run-$s:" + echo " @echo 'Running $s..'" + echo " @bash $s" + fi +done +} > run-test.mk +exec ${MAKE:-make} -f run-test.mk diff --git a/tests/ice40/temp/.gitignore b/tests/ice40/temp/.gitignore deleted file mode 100644 index 397b4a762..000000000 --- a/tests/ice40/temp/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.log diff --git a/tests/ice40/tribuf.v b/tests/ice40/tribuf.v index b2b5e37d6..870a02584 100644 --- a/tests/ice40/tribuf.v +++ b/tests/ice40/tribuf.v @@ -1,10 +1,10 @@ module tristate (en, i, o); input en; input i; - output reg o; + output o; + + assign o = en ? i : 1'bz; - always @(en or i) - o <= (en)? i : 1'bZ; endmodule diff --git a/tests/ice40/tribuf.ys b/tests/ice40/tribuf.ys index b319e6622..9b7ea1eab 100644 --- a/tests/ice40/tribuf.ys +++ b/tests/ice40/tribuf.ys @@ -1,6 +1,8 @@ -synth_ice40 -equiv_opt -assert -map +/ice40/cells_sim.v -map +/simcells.v synth_ice40 -design -load postopt -select -assert-count 1 t:SB_LUT4 -select -assert-count 1 t:SB_CARRY +read_verilog tribuf.v +hierarchy -top top +synth -flatten -run coarse # technology-independent coarse grained synthesis +equiv_opt -map +/ice40/cells_sim.v synth_ice40 # equivalency check same as technology-dependent fine-grained synthesis +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module select -assert-count 1 t:$_TBUF_ +select -assert-none t:$_TBUF_ %% t:* %D From 02507124868144145526a39b0718319bf9db12a7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 12:50:49 -0700 Subject: [PATCH 005/130] Initial progress on xilinx_srl --- passes/pmgen/Makefile.inc | 6 ++ passes/pmgen/xilinx_srl.cc | 115 ++++++++++++++++++++++++++++++++++++ passes/pmgen/xilinx_srl.pmg | 92 +++++++++++++++++++++++++++++ 3 files changed, 213 insertions(+) create mode 100644 passes/pmgen/xilinx_srl.cc create mode 100644 passes/pmgen/xilinx_srl.pmg diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index 382a1b4ad..479e03a56 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -30,3 +30,9 @@ PEEPOPT_PATTERN += passes/pmgen/peepopt_muldiv.pmg passes/pmgen/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN) $(P) mkdir -p passes/pmgen && python3 $< -o $@ -p peepopt $(filter-out $<,$^) + +# -------------------------------------- + +OBJS += passes/pmgen/xilinx_srl.o +passes/pmgen/xilinx_srl.o: passes/pmgen/xilinx_srl_pm.h +$(eval $(call add_extra_objs,passes/pmgen/xilinx_srl_pm.h)) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc new file mode 100644 index 000000000..2d052534d --- /dev/null +++ b/passes/pmgen/xilinx_srl.cc @@ -0,0 +1,115 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +// for peepopt_pm +bool did_something; + +#include "passes/pmgen/xilinx_srl_pm.h" +#include "passes/pmgen/ice40_dsp_pm.h" +#include "passes/pmgen/peepopt_pm.h" + +void reduce_chain(xilinx_srl_pm &pm, int minlen) +{ + auto &st = pm.st_reduce; + auto &ud = pm.ud_reduce; + + if (GetSize(ud.longest_chain) < minlen) + return; + + log("Found chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type)); + + auto last_cell = ud.longest_chain.back(); + + for (auto cell : ud.longest_chain) { + log_debug(" %s\n", log_id(cell)); + if (cell != last_cell) + pm.autoremove(cell); + } + + Cell *c = last_cell; + SigSpec Q = st.first->getPort(ID(Q)); + c->setPort(ID(Q), Q); + + if (c->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID(FDRE), ID(FDRE_1))) { + c->parameters.clear(); + c->setParam(ID(DEPTH), GetSize(ud.longest_chain)); + // TODO c->setParam(ID(INIT), init); + if (c->type.in(ID($_DFF_P_), ID($_DFFE_PN_), ID($_DFFE_PP_))) + c->setParam(ID(CLKPOL), 1); + else + log_abort(); + if (c->type.in(ID($_DFFE_NN_), ID($_DFFE_PN_))) + c->setParam(ID(ENPOL), 1); + else if (c->type.in(ID($_DFFE_NP_), ID($_DFFE_PN_))) + c->setParam(ID(ENPOL), 0); + else + c->setParam(ID(ENPOL), 2); + if (c->type.in(ID($_DFF_N_), ID($_DFF_P_))) + c->setPort(ID(E), State::S1); + c->setPort(ID(L), GetSize(ud.longest_chain)-1); + c->type = ID($__XILINX_SHREG_); + } + else + log_abort(); + + log(" -> %s (%s)\n", log_id(c), log_id(c->type)); +} + +struct XilinxSrlPass : public Pass { + XilinxSrlPass() : Pass("xilinx_srl", "Xilinx shift register extraction") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" xilinx_srl [options] [selection]\n"); + log("\n"); + log("TODO.\n"); + log("\n"); + } + + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing XILINX_SRL pass (Xilinx shift register extraction).\n"); + + int minlen = 3; + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-minlen" && argidx+1 < args.size()) { + minlen = atoi(args[++argidx].c_str()); + continue; + } + break; + } + extra_args(args, argidx, design); + + auto f = std::bind(reduce_chain, std::placeholders::_1, minlen); + for (auto module : design->selected_modules()) + while (xilinx_srl_pm(module, module->selected_cells()).run_reduce(f)) {} + } +} XilinxSrlPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg new file mode 100644 index 000000000..ae29ac6c9 --- /dev/null +++ b/passes/pmgen/xilinx_srl.pmg @@ -0,0 +1,92 @@ +pattern reduce + +udata > chain longest_chain +udata > non_first_cells + +code + non_first_cells.clear(); + subpattern(setup); +endcode + +match first + select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) + filter !non_first_cells.count(first) +//generate +// SigSpec A = module->addWire(NEW_ID); +// SigSpec B = module->addWire(NEW_ID); +// SigSpec Y = module->addWire(NEW_ID); +// switch (rng(3)) +// { +// case 0: +// module->addAndGate(NEW_ID, A, B, Y); +// break; +// case 1: +// module->addOrGate(NEW_ID, A, B, Y); +// break; +// case 2: +// module->addXorGate(NEW_ID, A, B, Y); +// break; +// } +endmatch + +code + longest_chain.clear(); + chain.push_back(first); + subpattern(tail); +finally + chain.pop_back(); + log_assert(chain.empty()); + if (GetSize(longest_chain) > 1) + accept; +endcode + +// ------------------------------------------------------------------ + +subpattern setup + +match first + select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) +endmatch + +match next + select nusers(port(next, \Q)) == 2 + select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) + index next->type === first->type + index port(next, \Q) === port(first, \D) +endmatch + +code + non_first_cells.insert(next); +endcode + +// ------------------------------------------------------------------ + +subpattern tail +arg first + +match next + semioptional + select nusers(port(next, \Q)) == 2 + select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) + index next->type === chain.back()->type + index port(next, \Q) === port(chain.back(), \D) +//generate 10 +// SigSpec A = module->addWire(NEW_ID); +// SigSpec B = module->addWire(NEW_ID); +// SigSpec Y = port(chain.back().first, chain.back().second); +// Cell *c = module->addAndGate(NEW_ID, A, B, Y); +// c->type = chain.back().first->type; +endmatch + +code + if (next) { + chain.push_back(next); + subpattern(tail); + } else { + if (GetSize(chain) > GetSize(longest_chain)) + longest_chain = chain; + } +finally + if (next) + chain.pop_back(); +endcode From df53fe12e7ed667d36d3829681cfc43a3355b834 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 12:54:11 -0700 Subject: [PATCH 006/130] Fix spacing --- passes/pmgen/xilinx_srl.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index 2d052534d..bfda55af0 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -93,7 +93,7 @@ struct XilinxSrlPass : public Pass { { log_header(design, "Executing XILINX_SRL pass (Xilinx shift register extraction).\n"); - int minlen = 3; + int minlen = 3; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -106,7 +106,7 @@ struct XilinxSrlPass : public Pass { } extra_args(args, argidx, design); - auto f = std::bind(reduce_chain, std::placeholders::_1, minlen); + auto f = std::bind(reduce_chain, std::placeholders::_1, minlen); for (auto module : design->selected_modules()) while (xilinx_srl_pm(module, module->selected_cells()).run_reduce(f)) {} } From 5ce0c31d0e01603264b23cff8f6d431902f08b63 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 13:05:10 -0700 Subject: [PATCH 007/130] Add init support --- passes/pmgen/xilinx_srl.cc | 13 +++++++++++-- techlibs/xilinx/synth_xilinx.cc | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index bfda55af0..7240c2fa3 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -42,20 +42,29 @@ void reduce_chain(xilinx_srl_pm &pm, int minlen) auto last_cell = ud.longest_chain.back(); + SigSpec initval; for (auto cell : ud.longest_chain) { log_debug(" %s\n", log_id(cell)); + SigBit Q = cell->getPort(ID(Q)); + log_assert(Q.wire); + auto it = Q.wire->attributes.find(ID(init)); + if (it != Q.wire->attributes.end()) { + initval.append(it->second[Q.offset]); + } + else + initval.append(State::Sx); if (cell != last_cell) pm.autoremove(cell); } Cell *c = last_cell; - SigSpec Q = st.first->getPort(ID(Q)); + SigBit Q = st.first->getPort(ID(Q)); c->setPort(ID(Q), Q); if (c->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID(FDRE), ID(FDRE_1))) { c->parameters.clear(); c->setParam(ID(DEPTH), GetSize(ud.longest_chain)); - // TODO c->setParam(ID(INIT), init); + c->setParam(ID(INIT), initval.as_const()); if (c->type.in(ID($_DFF_P_), ID($_DFFE_PN_), ID($_DFFE_PP_))) c->setParam(ID(CLKPOL), 1); else diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 7ba67409b..49f32002c 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -406,7 +406,7 @@ struct SynthXilinxPass : public ScriptPass // This shregmap call infers fixed length shift registers after abc // has performed any necessary retiming if (!nosrl || help_mode) - run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')"); + run("xilinx_srl -minlen 3", "(skip if '-nosrl')"); run("techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v"); run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); From 52fea5b65829745988de00a5e15975026060e76c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 13:42:03 -0700 Subject: [PATCH 008/130] Respect \keep on cells or wires --- passes/pmgen/xilinx_srl.pmg | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index ae29ac6c9..cd7461052 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -10,6 +10,8 @@ endcode match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) + select !first->get_bool_attribute(\keep) + select !port(first, \Q).as_wire()->get_bool_attribute(\keep) filter !non_first_cells.count(first) //generate // SigSpec A = module->addWire(NEW_ID); @@ -46,11 +48,15 @@ subpattern setup match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) + select !first->get_bool_attribute(\keep) + select !port(first, \Q).as_wire()->get_bool_attribute(\keep) endmatch match next - select nusers(port(next, \Q)) == 2 select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) + select !next->get_bool_attribute(\keep) + select !port(next, \Q).as_wire()->get_bool_attribute(\keep) + select nusers(port(next, \Q)) == 2 index next->type === first->type index port(next, \Q) === port(first, \D) endmatch @@ -66,8 +72,10 @@ arg first match next semioptional - select nusers(port(next, \Q)) == 2 select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) + select !next->get_bool_attribute(\keep) + select !port(next, \Q).as_wire()->get_bool_attribute(\keep) + select nusers(port(next, \Q)) == 2 index next->type === chain.back()->type index port(next, \Q) === port(chain.back(), \D) //generate 10 From cab2bd083ed25ebe1113d5fd054df5983e5086e7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 13:47:47 -0700 Subject: [PATCH 009/130] Get wire via SigBit --- passes/pmgen/xilinx_srl.pmg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index cd7461052..69a9c7af2 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -11,7 +11,7 @@ endcode match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !first->get_bool_attribute(\keep) - select !port(first, \Q).as_wire()->get_bool_attribute(\keep) + select !port(first, \Q)[0].wire->get_bool_attribute(\keep) filter !non_first_cells.count(first) //generate // SigSpec A = module->addWire(NEW_ID); @@ -49,13 +49,13 @@ subpattern setup match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !first->get_bool_attribute(\keep) - select !port(first, \Q).as_wire()->get_bool_attribute(\keep) + select !port(first, \Q)[0].wire->get_bool_attribute(\keep) endmatch match next select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !next->get_bool_attribute(\keep) - select !port(next, \Q).as_wire()->get_bool_attribute(\keep) + select !port(next, \Q)[0].wire->get_bool_attribute(\keep) select nusers(port(next, \Q)) == 2 index next->type === first->type index port(next, \Q) === port(first, \D) @@ -74,7 +74,7 @@ match next semioptional select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !next->get_bool_attribute(\keep) - select !port(next, \Q).as_wire()->get_bool_attribute(\keep) + select !port(next, \Q)[0].wire->get_bool_attribute(\keep) select nusers(port(next, \Q)) == 2 index next->type === chain.back()->type index port(next, \Q) === port(chain.back(), \D) From 1c7d721558737292a6e1c5492ac8032fcdd8e31e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 14:26:24 -0700 Subject: [PATCH 010/130] Reject if not minlen from inside pattern matcher --- passes/pmgen/xilinx_srl.cc | 16 +++++++++------- passes/pmgen/xilinx_srl.pmg | 3 ++- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index 7240c2fa3..a4a893307 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -30,14 +30,11 @@ bool did_something; #include "passes/pmgen/ice40_dsp_pm.h" #include "passes/pmgen/peepopt_pm.h" -void reduce_chain(xilinx_srl_pm &pm, int minlen) +void reduce_chain(xilinx_srl_pm &pm) { auto &st = pm.st_reduce; auto &ud = pm.ud_reduce; - if (GetSize(ud.longest_chain) < minlen) - return; - log("Found chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type)); auto last_cell = ud.longest_chain.back(); @@ -115,9 +112,14 @@ struct XilinxSrlPass : public Pass { } extra_args(args, argidx, design); - auto f = std::bind(reduce_chain, std::placeholders::_1, minlen); - for (auto module : design->selected_modules()) - while (xilinx_srl_pm(module, module->selected_cells()).run_reduce(f)) {} + for (auto module : design->selected_modules()) { + bool did_something = false; + do { + auto pm = xilinx_srl_pm(module, module->selected_cells()); + pm.ud_reduce.minlen = minlen; + did_something = pm.run_reduce(reduce_chain); + } while (did_something); + } } } XilinxSrlPass; diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 69a9c7af2..3a2096653 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -2,6 +2,7 @@ pattern reduce udata > chain longest_chain udata > non_first_cells +udata minlen code non_first_cells.clear(); @@ -38,7 +39,7 @@ code finally chain.pop_back(); log_assert(chain.empty()); - if (GetSize(longest_chain) > 1) + if (GetSize(longest_chain) >= minlen) accept; endcode From a980f0d4be218040ee2ecf42186583e416f82d91 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 14:35:40 -0700 Subject: [PATCH 011/130] Add CLKPOL == 0 --- passes/pmgen/xilinx_srl.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index a4a893307..4a3a30f83 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -64,6 +64,8 @@ void reduce_chain(xilinx_srl_pm &pm) c->setParam(ID(INIT), initval.as_const()); if (c->type.in(ID($_DFF_P_), ID($_DFFE_PN_), ID($_DFFE_PP_))) c->setParam(ID(CLKPOL), 1); + else if (c->type.in(ID($_DFF_N_), ID($DFFE_NN_), ID($_DFFE_NP_), ID(FDRE_1))) + c->setParam(ID(CLKPOL), 0); else log_abort(); if (c->type.in(ID($_DFFE_NN_), ID($_DFFE_PN_))) From 3c8e8521a6c5431c9350038abcb50dff5dfe8469 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 14:42:11 -0700 Subject: [PATCH 012/130] Fix polarity of EN_POL --- passes/pmgen/xilinx_srl.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index 4a3a30f83..bd4dc59ab 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -68,9 +68,9 @@ void reduce_chain(xilinx_srl_pm &pm) c->setParam(ID(CLKPOL), 0); else log_abort(); - if (c->type.in(ID($_DFFE_NN_), ID($_DFFE_PN_))) + if (c->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_))) c->setParam(ID(ENPOL), 1); - else if (c->type.in(ID($_DFFE_NP_), ID($_DFFE_PN_))) + else if (c->type.in(ID($_DFFE_NN_), ID($_DFFE_PN_))) c->setParam(ID(ENPOL), 0); else c->setParam(ID(ENPOL), 2); From 6fa9e03e4cdb981fa829469a94d8c7c6d4c7a22e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 15:35:29 -0700 Subject: [PATCH 013/130] xilinx_srl to support FDRE and FDRE_1 --- passes/pmgen/xilinx_srl.cc | 29 +++++++++++++++----- passes/pmgen/xilinx_srl.pmg | 54 ++++++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 10 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index bd4dc59ab..862b44bb0 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -34,6 +34,10 @@ void reduce_chain(xilinx_srl_pm &pm) { auto &st = pm.st_reduce; auto &ud = pm.ud_reduce; + auto param_def = [&ud](Cell *cell, IdString param) { + auto def = ud.default_params.at(std::make_pair(cell->type,param)); + return cell->parameters.at(param, def); + }; log("Found chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type)); @@ -42,14 +46,20 @@ void reduce_chain(xilinx_srl_pm &pm) SigSpec initval; for (auto cell : ud.longest_chain) { log_debug(" %s\n", log_id(cell)); - SigBit Q = cell->getPort(ID(Q)); - log_assert(Q.wire); - auto it = Q.wire->attributes.find(ID(init)); - if (it != Q.wire->attributes.end()) { - initval.append(it->second[Q.offset]); + if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) { + SigBit Q = cell->getPort(ID(Q)); + log_assert(Q.wire); + auto it = Q.wire->attributes.find(ID(init)); + if (it != Q.wire->attributes.end()) { + initval.append(it->second[Q.offset]); + } + else + initval.append(State::Sx); } + else if (cell->type.in(ID(FDRE), ID(FDRE_1))) + initval.append(param_def(cell, ID(INIT))); else - initval.append(State::Sx); + log_abort(); if (cell != last_cell) pm.autoremove(cell); } @@ -66,6 +76,8 @@ void reduce_chain(xilinx_srl_pm &pm) c->setParam(ID(CLKPOL), 1); else if (c->type.in(ID($_DFF_N_), ID($DFFE_NN_), ID($_DFFE_NP_), ID(FDRE_1))) c->setParam(ID(CLKPOL), 0); + else if (c->type.in(ID(FDRE))) + c->setParam(ID(CLKPOL), param_def(c, ID(IS_C_INVERTED)).as_bool() ? 0 : 1); else log_abort(); if (c->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_))) @@ -119,6 +131,11 @@ struct XilinxSrlPass : public Pass { do { auto pm = xilinx_srl_pm(module, module->selected_cells()); pm.ud_reduce.minlen = minlen; + // TODO: How to get these automatically? + pm.ud_reduce.default_params[std::make_pair(ID(FDRE),ID(INIT))] = State::S0; + pm.ud_reduce.default_params[std::make_pair(ID(FDRE),ID(IS_C_INVERTED))] = State::S0; + pm.ud_reduce.default_params[std::make_pair(ID(FDRE),ID(IS_D_INVERTED))] = State::S0; + pm.ud_reduce.default_params[std::make_pair(ID(FDRE),ID(IS_R_INVERTED))] = State::S0; did_something = pm.run_reduce(reduce_chain); } while (did_something); } diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 3a2096653..5ae7690c8 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -3,6 +3,7 @@ pattern reduce udata > chain longest_chain udata > non_first_cells udata minlen +udata ,Const>> default_params code non_first_cells.clear(); @@ -12,7 +13,6 @@ endcode match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !first->get_bool_attribute(\keep) - select !port(first, \Q)[0].wire->get_bool_attribute(\keep) filter !non_first_cells.count(first) //generate // SigSpec A = module->addWire(NEW_ID); @@ -50,19 +50,50 @@ subpattern setup match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !first->get_bool_attribute(\keep) - select !port(first, \Q)[0].wire->get_bool_attribute(\keep) endmatch +code + if (first->type.in(\FDRE, \FDRE_1)) { + SigBit R = port(first, \R); + if (first->type == \FDRE) { + auto inverted = first->parameters.at(\IS_R_INVERTED, default_params.at(std::make_pair(first->type,\IS_R_INVERTED))).as_bool(); + if (!inverted && R != State::S0) + reject; + if (inverted && R != State::S1) + reject; + } + else if (first->type == \FDRE_1) { + if (R == State::S0) + reject; + } + else log_abort(); + } +endcode + match next select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !next->get_bool_attribute(\keep) - select !port(next, \Q)[0].wire->get_bool_attribute(\keep) + select !port(next, \D)[0].wire->get_bool_attribute(\keep) select nusers(port(next, \Q)) == 2 index next->type === first->type index port(next, \Q) === port(first, \D) endmatch code + if (next->type.in(\FDRE, \FDRE_1)) { + for (auto p : { \R }) + if (port(next, p) != port(first, p)) + reject; + + if (next->type == \FDRE) { + for (auto p : { \IS_C_INVERTED, \IS_D_INVERTED, \IS_R_INVERTED }) { + auto n = next->parameters.at(p, default_params.at(std::make_pair(next->type,p))); + auto f = first->parameters.at(p, default_params.at(std::make_pair(first->type,p))); + if (n != f) + reject; + } + } + } non_first_cells.insert(next); endcode @@ -75,7 +106,7 @@ match next semioptional select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !next->get_bool_attribute(\keep) - select !port(next, \Q)[0].wire->get_bool_attribute(\keep) + select !port(next, \D)[0].wire->get_bool_attribute(\keep) select nusers(port(next, \Q)) == 2 index next->type === chain.back()->type index port(next, \Q) === port(chain.back(), \D) @@ -89,6 +120,21 @@ endmatch code if (next) { + if (next->type.in(\FDRE, \FDRE_1)) { + for (auto p : { \R }) + if (port(next, p) != port(first, p)) + reject; + + if (next->type == \FDRE) { + for (auto p : { \IS_C_INVERTED, \IS_D_INVERTED, \IS_R_INVERTED }) { + auto n = next->parameters.at(p, default_params.at(std::make_pair(next->type,p))); + auto f = first->parameters.at(p, default_params.at(std::make_pair(first->type,p))); + if (n != f) + reject; + } + } + } + chain.push_back(next); subpattern(tail); } else { From edec73fec1973e5d2491e577127ff8932f67cb88 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 15:37:55 -0700 Subject: [PATCH 014/130] abc9 to perform new 'map_ffs' before 'map_luts' --- techlibs/xilinx/synth_xilinx.cc | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 49f32002c..2c5f2ec57 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -383,6 +383,14 @@ struct SynthXilinxPass : public ScriptPass run("clean"); } + if (check_label("map_ffs")) { + if (abc9 || help_mode) { + run("techmap -map +/xilinx/ff_map.v", "('-abc9' only)"); + run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " + "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT", "('-abc9' only)"); + } + } + if (check_label("map_luts")) { run("opt_expr -mux_undef"); if (help_mode) @@ -407,9 +415,16 @@ struct SynthXilinxPass : public ScriptPass // has performed any necessary retiming if (!nosrl || help_mode) run("xilinx_srl -minlen 3", "(skip if '-nosrl')"); - run("techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v"); - run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " - "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); + + std::string techmap_args = "-map +/xilinx/lut_map.v -map +/xilinx/cells_map.v"; + if (help_mode) + techmap_args += " [-map +/xilinx/ff_map.v]"; + else if (!abc9) + techmap_args += " -map +/xilinx/ff_map.v"; + run("techmap " + techmap_args); + if (!abc9) + run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " + "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT", "(without '-abc9' only)"); run("clean"); } From 61b4d7ae13c9bdb3c8aca10eb5540eca4c6d6007 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 15:41:46 -0700 Subject: [PATCH 015/130] Use Cell::has_keep_attribute() --- passes/pmgen/xilinx_srl.pmg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 5ae7690c8..e90bac68d 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -12,7 +12,7 @@ endcode match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) - select !first->get_bool_attribute(\keep) + select !first->has_keep_attribute() filter !non_first_cells.count(first) //generate // SigSpec A = module->addWire(NEW_ID); @@ -49,7 +49,7 @@ subpattern setup match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) - select !first->get_bool_attribute(\keep) + select !first->has_keep_attribute() endmatch code @@ -72,7 +72,7 @@ endcode match next select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) - select !next->get_bool_attribute(\keep) + select !next->has_keep_attribute() select !port(next, \D)[0].wire->get_bool_attribute(\keep) select nusers(port(next, \Q)) == 2 index next->type === first->type @@ -105,7 +105,7 @@ arg first match next semioptional select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) - select !next->get_bool_attribute(\keep) + select !next->has_keep_attribute() select !port(next, \D)[0].wire->get_bool_attribute(\keep) select nusers(port(next, \Q)) == 2 index next->type === chain.back()->type From b0a3b430bf1a54b00daf9a33818598057f67cf7c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 15:44:07 -0700 Subject: [PATCH 016/130] attribute -> attr --- passes/pmgen/xilinx_srl.pmg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index e90bac68d..6c740b7a7 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -12,7 +12,7 @@ endcode match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) - select !first->has_keep_attribute() + select !first->has_keep_attr() filter !non_first_cells.count(first) //generate // SigSpec A = module->addWire(NEW_ID); @@ -49,7 +49,7 @@ subpattern setup match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) - select !first->has_keep_attribute() + select !first->has_keep_attr() endmatch code @@ -72,7 +72,7 @@ endcode match next select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) - select !next->has_keep_attribute() + select !next->has_keep_attr() select !port(next, \D)[0].wire->get_bool_attribute(\keep) select nusers(port(next, \Q)) == 2 index next->type === first->type @@ -105,7 +105,7 @@ arg first match next semioptional select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) - select !next->has_keep_attribute() + select !next->has_keep_attr() select !port(next, \D)[0].wire->get_bool_attribute(\keep) select nusers(port(next, \Q)) == 2 index next->type === chain.back()->type From 6d76ae4c65d3a7b403888219900a3c0f85ee737d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 15:46:58 -0700 Subject: [PATCH 017/130] Rename pattern to fixed --- passes/pmgen/xilinx_srl.cc | 18 +++++++++--------- passes/pmgen/xilinx_srl.pmg | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index 862b44bb0..029cb3235 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -30,10 +30,10 @@ bool did_something; #include "passes/pmgen/ice40_dsp_pm.h" #include "passes/pmgen/peepopt_pm.h" -void reduce_chain(xilinx_srl_pm &pm) +void fixed(xilinx_srl_pm &pm) { - auto &st = pm.st_reduce; - auto &ud = pm.ud_reduce; + auto &st = pm.st_fixed; + auto &ud = pm.ud_fixed; auto param_def = [&ud](Cell *cell, IdString param) { auto def = ud.default_params.at(std::make_pair(cell->type,param)); return cell->parameters.at(param, def); @@ -130,13 +130,13 @@ struct XilinxSrlPass : public Pass { bool did_something = false; do { auto pm = xilinx_srl_pm(module, module->selected_cells()); - pm.ud_reduce.minlen = minlen; + pm.ud_fixed.minlen = minlen; // TODO: How to get these automatically? - pm.ud_reduce.default_params[std::make_pair(ID(FDRE),ID(INIT))] = State::S0; - pm.ud_reduce.default_params[std::make_pair(ID(FDRE),ID(IS_C_INVERTED))] = State::S0; - pm.ud_reduce.default_params[std::make_pair(ID(FDRE),ID(IS_D_INVERTED))] = State::S0; - pm.ud_reduce.default_params[std::make_pair(ID(FDRE),ID(IS_R_INVERTED))] = State::S0; - did_something = pm.run_reduce(reduce_chain); + pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(INIT))] = State::S0; + pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_C_INVERTED))] = State::S0; + pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_D_INVERTED))] = State::S0; + pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_R_INVERTED))] = State::S0; + did_something = pm.run_fixed(fixed); } while (did_something); } } diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 6c740b7a7..e7086c424 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -1,4 +1,4 @@ -pattern reduce +pattern fixed udata > chain longest_chain udata > non_first_cells From 15188033da68c89c409af0839f22e6acc573abb7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 17:34:40 -0700 Subject: [PATCH 018/130] Add variable length support to xilinx_srl --- passes/pmgen/xilinx_srl.cc | 112 ++++++++++++++++++++++++++++---- passes/pmgen/xilinx_srl.pmg | 66 ++++++++++++++++++- techlibs/xilinx/synth_xilinx.cc | 7 +- 3 files changed, 167 insertions(+), 18 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index 029cb3235..ce77a3308 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -30,7 +30,7 @@ bool did_something; #include "passes/pmgen/ice40_dsp_pm.h" #include "passes/pmgen/peepopt_pm.h" -void fixed(xilinx_srl_pm &pm) +void run_fixed(xilinx_srl_pm &pm) { auto &st = pm.st_fixed; auto &ud = pm.ud_fixed; @@ -39,7 +39,7 @@ void fixed(xilinx_srl_pm &pm) return cell->parameters.at(param, def); }; - log("Found chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type)); + log("Found fixed chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type)); auto last_cell = ud.longest_chain.back(); @@ -97,6 +97,68 @@ void fixed(xilinx_srl_pm &pm) log(" -> %s (%s)\n", log_id(c), log_id(c->type)); } +void run_variable(xilinx_srl_pm &pm) +{ + auto &st = pm.st_variable; + auto &ud = pm.ud_variable; + + log("Found variable chain of length %d (%s):\n", GetSize(ud.chain), log_id(st.first->type)); + + auto last_cell = ud.chain.back(); + + SigSpec initval; + for (auto cell : ud.chain) { + log_debug(" %s\n", log_id(cell)); + if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) { + SigBit Q = cell->getPort(ID(Q)); + log_assert(Q.wire); + auto it = Q.wire->attributes.find(ID(init)); + if (it != Q.wire->attributes.end()) { + initval.append(it->second[Q.offset]); + } + else + initval.append(State::Sx); + } + else + log_abort(); + if (cell != last_cell) + pm.autoremove(cell); + } + pm.autoremove(st.shiftx); + + Cell *c = last_cell; + SigBit Q = st.first->getPort(ID(Q)); + c->setPort(ID(Q), Q); + + if (c->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) { + c->parameters.clear(); + c->setParam(ID(DEPTH), GetSize(ud.chain)); + c->setParam(ID(INIT), initval.as_const()); + if (c->type.in(ID($_DFF_P_), ID($_DFFE_PN_), ID($_DFFE_PP_))) + c->setParam(ID(CLKPOL), 1); + else if (c->type.in(ID($_DFF_N_), ID($DFFE_NN_), ID($_DFFE_NP_), ID(FDRE_1))) + c->setParam(ID(CLKPOL), 0); + else + log_abort(); + if (c->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_))) + c->setParam(ID(ENPOL), 1); + else if (c->type.in(ID($_DFFE_NN_), ID($_DFFE_PN_))) + c->setParam(ID(ENPOL), 0); + else + c->setParam(ID(ENPOL), 2); + if (c->type.in(ID($_DFF_N_), ID($_DFF_P_))) + c->setPort(ID(E), State::S1); + c->setPort(ID(L), st.shiftx->getPort(ID(B))); + c->setPort(ID(Q), st.shiftx->getPort(ID(Y))); + c->type = ID($__XILINX_SHREG_); + } + else + log_abort(); + + log(" -> %s (%s)\n", log_id(c), log_id(c->type)); + +} + struct XilinxSrlPass : public Pass { XilinxSrlPass() : Pass("xilinx_srl", "Xilinx shift register extraction") { } void help() YS_OVERRIDE @@ -113,6 +175,8 @@ struct XilinxSrlPass : public Pass { { log_header(design, "Executing XILINX_SRL pass (Xilinx shift register extraction).\n"); + bool fixed = false; + bool variable = false; int minlen = 3; size_t argidx; @@ -122,22 +186,46 @@ struct XilinxSrlPass : public Pass { minlen = atoi(args[++argidx].c_str()); continue; } + if (args[argidx] == "-fixed") { + fixed = true; + continue; + } + if (args[argidx] == "-variable") { + variable = true; + continue; + } break; } extra_args(args, argidx, design); + if (!fixed && !variable) + log_cmd_error("'-fixed' and/or '-variable' must be specified.\n"); + for (auto module : design->selected_modules()) { bool did_something = false; - do { - auto pm = xilinx_srl_pm(module, module->selected_cells()); - pm.ud_fixed.minlen = minlen; - // TODO: How to get these automatically? - pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(INIT))] = State::S0; - pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_C_INVERTED))] = State::S0; - pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_D_INVERTED))] = State::S0; - pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_R_INVERTED))] = State::S0; - did_something = pm.run_fixed(fixed); - } while (did_something); + if (fixed) + do { + auto pm = xilinx_srl_pm(module, module->selected_cells()); + pm.ud_fixed.minlen = minlen; + // TODO: How to get these automatically? + pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(INIT))] = State::S0; + pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_C_INVERTED))] = State::S0; + pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_D_INVERTED))] = State::S0; + pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_R_INVERTED))] = State::S0; + did_something = pm.run_fixed(run_fixed); + } while (did_something); + if (variable) + do { + auto pm = xilinx_srl_pm(module, module->selected_cells()); + pm.ud_variable.minlen = minlen; + for (auto p : module->ports) { + auto w = module->wire(p); + if (w->port_output) + for (auto b : pm.sigmap(w)) + pm.ud_variable.output_bits.insert(b); + } + did_something = pm.run_variable(run_variable); + } while (did_something); } } } XilinxSrlPass; diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index e7086c424..3f4efebe9 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -76,7 +76,7 @@ match next select !port(next, \D)[0].wire->get_bool_attribute(\keep) select nusers(port(next, \Q)) == 2 index next->type === first->type - index port(next, \Q) === port(first, \D) + index port(next, \Q) === port(first, \D) endmatch code @@ -109,7 +109,7 @@ match next select !port(next, \D)[0].wire->get_bool_attribute(\keep) select nusers(port(next, \Q)) == 2 index next->type === chain.back()->type - index port(next, \Q) === port(chain.back(), \D) + index port(next, \Q) === port(chain.back(), \D) //generate 10 // SigSpec A = module->addWire(NEW_ID); // SigSpec B = module->addWire(NEW_ID); @@ -145,3 +145,65 @@ finally if (next) chain.pop_back(); endcode + +// ----------- + +pattern variable + +state shiftx_width +udata minlen +udata > output_bits +udata > chain + +match shiftx + select shiftx->type.in($shiftx) + select !shiftx->has_keep_attr() + select param(shiftx, \Y_WIDTH) == 1 + filter param(shiftx, \A_WIDTH).as_int() >= minlen +endmatch + +code shiftx_width + shiftx_width = param(shiftx, \A_WIDTH).as_int(); +endcode + +match first + select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_) + select nusers(port(first, \Q)) == 2 + index port(first, \Q) === port(shiftx, \A)[shiftx_width-1] + filter !output_bits.count(port(first, \Q)) +endmatch + +code + chain.push_back(first); + subpattern(tail); +finally + if (GetSize(chain) == param(shiftx, \A_WIDTH).as_int()) + accept; + chain.clear(); +endcode + +// ------------------------------------------------------------------ + +subpattern tail +arg shiftx +arg shiftx_width + +match next + semioptional + select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_) + select !next->has_keep_attr() + select !port(next, \D)[0].wire->get_bool_attribute(\keep) + select nusers(port(next, \Q)) == 3 + filter !output_bits.count(port(next, \Q)) + index next->type === chain.back()->type + index port(next, \Q) === port(chain.back(), \D) + index port(next, \Q) === port(shiftx, \A)[shiftx_width-1-GetSize(chain)] +endmatch + +code + if (next) { + chain.push_back(next); + if (GetSize(chain) < shiftx_width) + subpattern(tail); + } +endcode diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 2c5f2ec57..8bf43bf97 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -352,9 +352,8 @@ struct SynthXilinxPass : public ScriptPass if (!nosrl || help_mode) { // shregmap operates on bit-level flops, not word-level, // so break those down here - run("simplemap t:$dff t:$dffe", " (skip if '-nosrl')"); - // shregmap with '-tech xilinx' infers variable length shift regs - run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')"); + run("simplemap t:$dff t:$dffe", " (skip if '-nosrl')"); + run("xilinx_srl -variable -minlen 3", "(skip if '-nosrl')"); } std::string techmap_args = " -map +/techmap.v"; @@ -414,7 +413,7 @@ struct SynthXilinxPass : public ScriptPass // This shregmap call infers fixed length shift registers after abc // has performed any necessary retiming if (!nosrl || help_mode) - run("xilinx_srl -minlen 3", "(skip if '-nosrl')"); + run("xilinx_srl -fixed -minlen 3", "(skip if '-nosrl')"); std::string techmap_args = "-map +/xilinx/lut_map.v -map +/xilinx/cells_map.v"; if (help_mode) From ed7be3e6b68521b2f147034f811a19bd7af86d1a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 17:36:38 -0700 Subject: [PATCH 019/130] Add comment --- passes/pmgen/xilinx_srl.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index ce77a3308..71112e3bc 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -218,6 +218,10 @@ struct XilinxSrlPass : public Pass { do { auto pm = xilinx_srl_pm(module, module->selected_cells()); pm.ud_variable.minlen = minlen; + // Since `nusers` does not count module ports as a user, + // and since `sigmap` does not always make such ports + // the canonical signal.. need to maintain a pool these + // ourselves for (auto p : module->ports) { auto w = module->wire(p); if (w->port_output) From 7e7965ca7b3bbeb79cb70014da7bc48c08a74adb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 18:43:17 -0700 Subject: [PATCH 020/130] Trim shiftx_width when upper bits are 1'bx --- passes/pmgen/xilinx_srl.pmg | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 3f4efebe9..d3ba0109f 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -164,6 +164,11 @@ endmatch code shiftx_width shiftx_width = param(shiftx, \A_WIDTH).as_int(); + while (shiftx_width > 1) { + if (port(shiftx, \A)[shiftx_width-1] != State::Sx) + break; + --shiftx_width; + } endcode match first @@ -177,7 +182,7 @@ code chain.push_back(first); subpattern(tail); finally - if (GetSize(chain) == param(shiftx, \A_WIDTH).as_int()) + if (GetSize(chain) == shiftx_width) accept; chain.clear(); endcode From c7859531c2cf56df67a0767a6333ecf9acab7251 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 19:18:05 -0700 Subject: [PATCH 021/130] opt_expr to trim A port of $shiftx if Y_WIDTH == 1 --- passes/opt/opt_expr.cc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 858b3560c..b56ce252f 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -745,6 +745,23 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } + if (cell->type == ID($shiftx) && cell->getPort(ID::Y).size() == 1) { + SigSpec sig_a = assign_map(cell->getPort(ID::A)); + int width; + for (width = GetSize(sig_a); width > 1; width--) { + if (sig_a[width-1] != State::Sx) + break; + } + + if (width < GetSize(sig_a)) { + sig_a.remove(width, GetSize(sig_a)-width); + cell->setPort(ID::A, sig_a); + cell->setParam(ID(A_WIDTH), width); + did_something = true; + goto next_cell; + } + } + if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && cell->getPort(ID::Y).size() == 1 && invert_map.count(assign_map(cell->getPort(ID::A))) != 0) { cover_list("opt.opt_expr.invert.double", "$_NOT_", "$not", "$logic_not", cell->type.str()); From 5c8344363f6405d1d6e21868b10b6dc9e02148a4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 19:18:27 -0700 Subject: [PATCH 022/130] Revert "Trim shiftx_width when upper bits are 1'bx" This reverts commit 7e7965ca7b3bbeb79cb70014da7bc48c08a74adb. --- passes/pmgen/xilinx_srl.pmg | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index d3ba0109f..3f4efebe9 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -164,11 +164,6 @@ endmatch code shiftx_width shiftx_width = param(shiftx, \A_WIDTH).as_int(); - while (shiftx_width > 1) { - if (port(shiftx, \A)[shiftx_width-1] != State::Sx) - break; - --shiftx_width; - } endcode match first @@ -182,7 +177,7 @@ code chain.push_back(first); subpattern(tail); finally - if (GetSize(chain) == shiftx_width) + if (GetSize(chain) == param(shiftx, \A_WIDTH).as_int()) accept; chain.clear(); endcode From 7d02d17b16d1f120697a5513f29d4eba8deae2a5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 19:18:40 -0700 Subject: [PATCH 023/130] Reuse var --- passes/pmgen/xilinx_srl.pmg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 3f4efebe9..4558234de 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -177,7 +177,7 @@ code chain.push_back(first); subpattern(tail); finally - if (GetSize(chain) == param(shiftx, \A_WIDTH).as_int()) + if (GetSize(chain) == shiftx_width) accept; chain.clear(); endcode From 61639d5387cceec6f6c50b851c4c44d6b4f93dad Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 10:51:04 -0700 Subject: [PATCH 024/130] Do not run xilinx_srl_pm in fixed loop --- passes/pmgen/xilinx_srl.cc | 52 ++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index 71112e3bc..36833839b 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -202,34 +202,30 @@ struct XilinxSrlPass : public Pass { log_cmd_error("'-fixed' and/or '-variable' must be specified.\n"); for (auto module : design->selected_modules()) { - bool did_something = false; - if (fixed) - do { - auto pm = xilinx_srl_pm(module, module->selected_cells()); - pm.ud_fixed.minlen = minlen; - // TODO: How to get these automatically? - pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(INIT))] = State::S0; - pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_C_INVERTED))] = State::S0; - pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_D_INVERTED))] = State::S0; - pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_R_INVERTED))] = State::S0; - did_something = pm.run_fixed(run_fixed); - } while (did_something); - if (variable) - do { - auto pm = xilinx_srl_pm(module, module->selected_cells()); - pm.ud_variable.minlen = minlen; - // Since `nusers` does not count module ports as a user, - // and since `sigmap` does not always make such ports - // the canonical signal.. need to maintain a pool these - // ourselves - for (auto p : module->ports) { - auto w = module->wire(p); - if (w->port_output) - for (auto b : pm.sigmap(w)) - pm.ud_variable.output_bits.insert(b); - } - did_something = pm.run_variable(run_variable); - } while (did_something); + auto pm = xilinx_srl_pm(module, module->selected_cells()); + pm.ud_fixed.minlen = minlen; + + if (fixed) { + // TODO: How to get these automatically? + pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(INIT))] = State::S0; + pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_C_INVERTED))] = State::S0; + pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_D_INVERTED))] = State::S0; + pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_R_INVERTED))] = State::S0; + pm.run_fixed(run_fixed); + } + if (variable) { + // Since `nusers` does not count module ports as a user, + // and since `sigmap` does not always make such ports + // the canonical signal.. need to maintain a pool these + // ourselves + for (auto p : module->ports) { + auto w = module->wire(p); + if (w->port_output) + for (auto b : pm.sigmap(w)) + pm.ud_variable.output_bits.insert(b); + } + pm.run_variable(run_variable); + } } } } XilinxSrlPass; From 231ddbf95cb2541eb73622e7dcb2744b2308f584 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 11:02:17 -0700 Subject: [PATCH 025/130] Forgot to set ud_variable.minlen --- passes/pmgen/xilinx_srl.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index 36833839b..d1dbd77ae 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -204,6 +204,7 @@ struct XilinxSrlPass : public Pass { for (auto module : design->selected_modules()) { auto pm = xilinx_srl_pm(module, module->selected_cells()); pm.ud_fixed.minlen = minlen; + pm.ud_variable.minlen = minlen; if (fixed) { // TODO: How to get these automatically? From 74bd190d3bb3d606f95e9c565ca8ccec70fca290 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 11:14:59 -0700 Subject: [PATCH 026/130] Remove output_bits --- passes/pmgen/xilinx_srl.cc | 13 +------------ passes/pmgen/xilinx_srl.pmg | 10 ++++++---- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index d1dbd77ae..0120a6c2c 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -214,19 +214,8 @@ struct XilinxSrlPass : public Pass { pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_R_INVERTED))] = State::S0; pm.run_fixed(run_fixed); } - if (variable) { - // Since `nusers` does not count module ports as a user, - // and since `sigmap` does not always make such ports - // the canonical signal.. need to maintain a pool these - // ourselves - for (auto p : module->ports) { - auto w = module->wire(p); - if (w->port_output) - for (auto b : pm.sigmap(w)) - pm.ud_variable.output_bits.insert(b); - } + if (variable) pm.run_variable(run_variable); - } } } } XilinxSrlPass; diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 4558234de..0cc551e92 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -152,13 +152,12 @@ pattern variable state shiftx_width udata minlen -udata > output_bits udata > chain match shiftx select shiftx->type.in($shiftx) select !shiftx->has_keep_attr() - select param(shiftx, \Y_WIDTH) == 1 + select param(shiftx, \Y_WIDTH).as_int() == 1 filter param(shiftx, \A_WIDTH).as_int() >= minlen endmatch @@ -170,7 +169,6 @@ match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_) select nusers(port(first, \Q)) == 2 index port(first, \Q) === port(shiftx, \A)[shiftx_width-1] - filter !output_bits.count(port(first, \Q)) endmatch code @@ -194,7 +192,6 @@ match next select !next->has_keep_attr() select !port(next, \D)[0].wire->get_bool_attribute(\keep) select nusers(port(next, \Q)) == 3 - filter !output_bits.count(port(next, \Q)) index next->type === chain.back()->type index port(next, \Q) === port(chain.back(), \D) index port(next, \Q) === port(shiftx, \A)[shiftx_width-1-GetSize(chain)] @@ -202,6 +199,11 @@ endmatch code if (next) { + auto sig = port(next, \Q); + log_warning("nusers of '%s'\n", log_signal(sig)); + for (auto bit : sigmap(sig)) + for (auto user : sigusers[bit]) + log_warning("\t%s\n", log_id(user)); chain.push_back(next); if (GetSize(chain) < shiftx_width) subpattern(tail); From 9f3ed1726ea82d18b5f3410fd60d3a96c652f447 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 11:15:16 -0700 Subject: [PATCH 027/130] pmgen to also iterate over all module ports --- passes/pmgen/pmgen.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py index 18c3bf5a5..8944ac2bf 100644 --- a/passes/pmgen/pmgen.py +++ b/passes/pmgen/pmgen.py @@ -390,8 +390,6 @@ with open(outfile, "w") as f: print(" void add_siguser(const SigSpec &sig, Cell *cell) {", file=f) print(" for (auto bit : sigmap(sig)) {", file=f) print(" if (bit.wire == nullptr) continue;", file=f) - print(" if (sigusers.count(bit) == 0 && bit.wire->port_id)", file=f) - print(" sigusers[bit].insert(nullptr);", file=f) print(" sigusers[bit].insert(cell);", file=f) print(" }", file=f) print(" }", file=f) @@ -450,6 +448,10 @@ with open(outfile, "w") as f: print(" for (auto &conn : cell->connections())", file=f) print(" add_siguser(conn.second, cell);", file=f) print(" }", file=f) + print(" for (auto port : module->ports)", file=f) + print(" add_siguser(module->wire(port), nullptr);", file=f) + print(" ", file=f) + print(" for (auto cell : cells) {", file=f) for index in range(len(blocks)): From 36d94caec169d232e8bf1a668ef9062ab38395ea Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 11:22:09 -0700 Subject: [PATCH 028/130] Remove `shregmap -tech xilinx` additions --- passes/techmap/shregmap.cc | 197 ++----------------------------------- 1 file changed, 8 insertions(+), 189 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 5e298d8dd..d472d1275 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -26,9 +26,7 @@ PRIVATE_NAMESPACE_BEGIN struct ShregmapTech { virtual ~ShregmapTech() { } - virtual void init(const Module * /*module*/, const SigMap &/*sigmap*/) {} - virtual void non_chain_user(const SigBit &/*bit*/, const Cell* /*cell*/, IdString /*port*/) {} - virtual bool analyze(vector &taps, const vector &qbits) = 0; + virtual bool analyze(vector &taps) = 0; virtual bool fixup(Cell *cell, dict &taps) = 0; }; @@ -56,7 +54,7 @@ struct ShregmapOptions struct ShregmapTechGreenpak4 : ShregmapTech { - bool analyze(vector &taps, const vector &/*qbits*/) + bool analyze(vector &taps) { if (GetSize(taps) > 2 && taps[0] == 0 && taps[2] < 17) { taps.clear(); @@ -93,155 +91,6 @@ struct ShregmapTechGreenpak4 : ShregmapTech } }; -struct ShregmapTechXilinx7 : ShregmapTech -{ - dict> sigbit_to_shiftx_offset; - const ShregmapOptions &opts; - - ShregmapTechXilinx7(const ShregmapOptions &opts) : opts(opts) {} - - virtual void init(const Module* module, const SigMap &sigmap) override - { - for (const auto &i : module->cells_) { - auto cell = i.second; - if (cell->type == ID($shiftx)) { - if (cell->getParam(ID(Y_WIDTH)) != 1) continue; - int j = 0; - for (auto bit : sigmap(cell->getPort(ID::A))) - sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j++, 0); - log_assert(j == cell->getParam(ID(A_WIDTH)).as_int()); - } - else if (cell->type == ID($mux)) { - int j = 0; - for (auto bit : sigmap(cell->getPort(ID::A))) - sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 0, j++); - j = 0; - for (auto bit : sigmap(cell->getPort(ID::B))) - sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 1, j++); - } - } - } - - virtual void non_chain_user(const SigBit &bit, const Cell *cell, IdString port) override - { - auto it = sigbit_to_shiftx_offset.find(bit); - if (it == sigbit_to_shiftx_offset.end()) - return; - if (cell) { - if (cell->type == ID($shiftx) && port == ID::A) - return; - if (cell->type == ID($mux) && port.in(ID::A, ID::B)) - return; - } - sigbit_to_shiftx_offset.erase(it); - } - - virtual bool analyze(vector &taps, const vector &qbits) override - { - if (GetSize(taps) == 1) - return taps[0] >= opts.minlen-1 && sigbit_to_shiftx_offset.count(qbits[0]); - - if (taps.back() < opts.minlen-1) - return false; - - Cell *shiftx = nullptr; - int group = 0; - for (int i = 0; i < GetSize(taps); ++i) { - auto it = sigbit_to_shiftx_offset.find(qbits[i]); - if (it == sigbit_to_shiftx_offset.end()) - return false; - - // Check taps are sequential - if (i != taps[i]) - return false; - // Check taps are not connected to a shift register, - // or sequential to the same shift register - if (i == 0) { - int offset; - std::tie(shiftx,offset,group) = it->second; - if (offset != i) - return false; - } - else { - Cell *shiftx_ = std::get<0>(it->second); - if (shiftx_ != shiftx) - return false; - int offset = std::get<1>(it->second); - if (offset != i) - return false; - int group_ = std::get<2>(it->second); - if (group_ != group) - return false; - } - } - log_assert(shiftx); - - // Only map if $shiftx exclusively covers the shift register - if (shiftx->type == ID($shiftx)) { - if (GetSize(taps) > shiftx->getParam(ID(A_WIDTH)).as_int()) - return false; - // Due to padding the most significant bits of A may be 1'bx, - // and if so, discount them - if (GetSize(taps) < shiftx->getParam(ID(A_WIDTH)).as_int()) { - const SigSpec A = shiftx->getPort(ID::A); - const int A_width = shiftx->getParam(ID(A_WIDTH)).as_int(); - for (int i = GetSize(taps); i < A_width; ++i) - if (A[i] != RTLIL::Sx) return false; - } - else if (GetSize(taps) != shiftx->getParam(ID(A_WIDTH)).as_int()) - return false; - } - else if (shiftx->type == ID($mux)) { - if (GetSize(taps) != 2) - return false; - } - else log_abort(); - - return true; - } - - virtual bool fixup(Cell *cell, dict &taps) override - { - const auto &tap = *taps.begin(); - auto bit = tap.second; - - auto it = sigbit_to_shiftx_offset.find(bit); - log_assert(it != sigbit_to_shiftx_offset.end()); - - auto newcell = cell->module->addCell(NEW_ID, ID($__XILINX_SHREG_)); - newcell->set_src_attribute(cell->get_src_attribute()); - newcell->setParam(ID(DEPTH), cell->getParam(ID(DEPTH))); - newcell->setParam(ID(INIT), cell->getParam(ID(INIT))); - newcell->setParam(ID(CLKPOL), cell->getParam(ID(CLKPOL))); - newcell->setParam(ID(ENPOL), cell->getParam(ID(ENPOL))); - - newcell->setPort(ID(C), cell->getPort(ID(C))); - newcell->setPort(ID(D), cell->getPort(ID(D))); - if (cell->hasPort(ID(E))) - newcell->setPort(ID(E), cell->getPort(ID(E))); - - Cell* shiftx = std::get<0>(it->second); - RTLIL::SigSpec l_wire, q_wire; - if (shiftx->type == ID($shiftx)) { - l_wire = shiftx->getPort(ID::B); - q_wire = shiftx->getPort(ID::Y); - shiftx->setPort(ID::Y, cell->module->addWire(NEW_ID)); - } - else if (shiftx->type == ID($mux)) { - l_wire = shiftx->getPort(ID(S)); - q_wire = shiftx->getPort(ID::Y); - shiftx->setPort(ID::Y, cell->module->addWire(NEW_ID)); - } - else log_abort(); - - newcell->setPort(ID(Q), q_wire); - newcell->setPort(ID(L), l_wire); - - return false; - } -}; - - struct ShregmapWorker { Module *module; @@ -264,10 +113,8 @@ struct ShregmapWorker for (auto wire : module->wires()) { if (wire->port_output || wire->get_bool_attribute(ID::keep)) { - for (auto bit : sigmap(wire)) { + for (auto bit : sigmap(wire)) sigbit_with_non_chain_users.insert(bit); - if (opts.tech) opts.tech->non_chain_user(bit, nullptr, {}); - } } if (wire->attributes.count(ID(init))) { @@ -293,22 +140,10 @@ struct ShregmapWorker if (opts.init || sigbit_init.count(q_bit) == 0) { - auto r = sigbit_chain_next.insert(std::make_pair(d_bit, cell)); - if (!r.second) { - // Insertion not successful means that d_bit is already - // connected to another register, thus mark it as a - // non chain user ... + if (sigbit_chain_next.count(d_bit)) { sigbit_with_non_chain_users.insert(d_bit); - // ... and clone d_bit into another wire, and use that - // wire as a different key in the d_bit-to-cell dictionary - // so that it can be identified as another chain - // (omitting this common flop) - // Link: https://github.com/YosysHQ/yosys/pull/1085 - Wire *wire = module->addWire(NEW_ID); - module->connect(wire, d_bit); - sigmap.add(wire, d_bit); - sigbit_chain_next.insert(std::make_pair(wire, cell)); - } + } else + sigbit_chain_next[d_bit] = cell; sigbit_chain_prev[q_bit] = cell; continue; @@ -317,10 +152,8 @@ struct ShregmapWorker for (auto conn : cell->connections()) if (cell->input(conn.first)) - for (auto bit : sigmap(conn.second)) { + for (auto bit : sigmap(conn.second)) sigbit_with_non_chain_users.insert(bit); - if (opts.tech) opts.tech->non_chain_user(bit, cell, conn.first); - } } } @@ -425,7 +258,7 @@ struct ShregmapWorker if (taps.empty() || taps.back() < depth-1) taps.push_back(depth-1); - if (opts.tech->analyze(taps, qbits)) + if (opts.tech->analyze(taps)) break; taps.pop_back(); @@ -544,9 +377,6 @@ struct ShregmapWorker ShregmapWorker(Module *module, const ShregmapOptions &opts) : module(module), sigmap(module), opts(opts), dff_count(0), shreg_count(0) { - if (opts.tech) - opts.tech->init(module, sigmap); - make_sigbit_chain_next_prev(); find_chain_start_cells(); @@ -617,11 +447,6 @@ struct ShregmapPass : public Pass { log("\n"); log(" -tech greenpak4\n"); log(" map to greenpak4 shift registers.\n"); - log(" this option also implies -clkpol pos -zinit\n"); - log("\n"); - log(" -tech xilinx\n"); - log(" map to xilinx dynamic-length shift registers.\n"); - log(" this option also implies -params -init\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -676,12 +501,6 @@ struct ShregmapPass : public Pass { clkpol = "pos"; opts.zinit = true; opts.tech = new ShregmapTechGreenpak4; - } - else if (tech == "xilinx") { - opts.init = true; - opts.params = true; - enpol = "any_or_none"; - opts.tech = new ShregmapTechXilinx7(opts); } else { argidx--; break; From 7a9031c48ed91de674f4ad1507b1148153930d0d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 11:22:53 -0700 Subject: [PATCH 029/130] Add CHANGELOG entry --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index ca42df71e..92456df99 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -27,6 +27,8 @@ Yosys 0.9 .. Yosys 0.9-dev - Added "opt_share" pass, run as part of "opt -full" - Added "ice40_wrapcarry" to encapsulate SB_LUT+SB_CARRY pairs for techmapping - Removed "ice40_unlut" + - Added "xilinx_srl" for Xilinx shift register extraction + - Removed "shregmap -tech xilinx" Yosys 0.8 .. Yosys 0.8-dev -------------------------- From cabadb85e2520bd07fa5071d553235da3614b462 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 11:25:19 -0700 Subject: [PATCH 030/130] Add copyright --- passes/pmgen/xilinx_srl.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index 0120a6c2c..45a78a320 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -2,6 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf + * (C) 2019 Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above From 6e8fda8bf074ca14c5bd58c0dbafc3a5c8ec8e7f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 11:52:24 -0700 Subject: [PATCH 031/130] Add doc --- passes/pmgen/xilinx_srl.cc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index 45a78a320..22fb93e18 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -168,7 +168,20 @@ struct XilinxSrlPass : public Pass { log("\n"); log(" xilinx_srl [options] [selection]\n"); log("\n"); - log("TODO.\n"); + log("This pass converts chains of built-in flops ($_DFF_[NP]_, $_DFFE_*) as well as\n"); + log("Xilinx flops (FDRE, FDRE_1) into a $__XILINX_SHREG cell. Chains must be of the\n"); + log("same type, clock, clock polarity, enable, enable polarity (when relevant).\n"); + log("Flops with resets cannot be mapped to Xilinx devices and will not be inferred."); + log("\n"); + log(" -minlen N\n"); + log(" min length of shift register (default = 3)\n"); + log("\n"); + log(" -fixed\n"); + log(" infer fixed-length shift registers.\n"); + log("\n"); + log(" -variable\n"); + log(" infer variable-length shift registers (i.e. fixed-length shifts where\n"); + log(" each element also fans-out to a $shiftx cell.\n"); log("\n"); } From c5754d9e8bed8d9238a462712f39a8d818401ad3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 12:17:25 -0700 Subject: [PATCH 032/130] Make multiplier wider, do not do tech independent synth --- tests/ice40/mul.v | 7 +++---- tests/ice40/mul.ys | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/ice40/mul.v b/tests/ice40/mul.v index c099db0d9..d5b48b1d7 100644 --- a/tests/ice40/mul.v +++ b/tests/ice40/mul.v @@ -1,10 +1,9 @@ module top ( - input [3:0] x, - input [3:0] y, + input [5:0] x, + input [5:0] y, - output [3:0] A, - output [3:0] B + output [11:0] A, ); assign A = x * y; diff --git a/tests/ice40/mul.ys b/tests/ice40/mul.ys index 35048d14a..adf1b3211 100644 --- a/tests/ice40/mul.ys +++ b/tests/ice40/mul.ys @@ -1,9 +1,8 @@ read_verilog mul.v hierarchy -top top -synth -flatten -run coarse # technology-independent coarse grained synthesis +#synth -flatten -run coarse # technology-independent coarse grained synthesis equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -dsp # equivalency check same as technology-dependent fine-grained synthesis design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module -select -assert-count 15 t:SB_LUT4 -select -assert-count 3 t:SB_CARRY -select -assert-none t:SB_LUT4 t:SB_CARRY %% t:* %D +select -assert-count 1 t:SB_MAC16 +select -assert-none t:SB_MAC16 %% t:* %D From 9e537a76b5a0487e0788054091132d2fd7f1a0dd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 12:20:18 -0700 Subject: [PATCH 033/130] Move $dffe to dffs.{v,ys} --- tests/ice40/adffs.v | 10 ---------- tests/ice40/adffs.ys | 9 ++++++--- tests/ice40/dffs.v | 34 +++++++++++++++++++++++++++++++++- tests/ice40/dffs.ys | 6 ++---- 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/tests/ice40/adffs.v b/tests/ice40/adffs.v index af7022c79..972184cfa 100644 --- a/tests/ice40/adffs.v +++ b/tests/ice40/adffs.v @@ -22,16 +22,6 @@ module adffn q <= d; endmodule -module dffe - ( input d, clk, en, output reg q ); - initial begin - q = 0; - end - always @( posedge clk ) - if ( en ) - q <= d; -endmodule - module dffsr ( input d, clk, pre, clr, output reg q ); initial begin diff --git a/tests/ice40/adffs.ys b/tests/ice40/adffs.ys index aee8cd6b4..d58ce1a82 100644 --- a/tests/ice40/adffs.ys +++ b/tests/ice40/adffs.ys @@ -1,8 +1,11 @@ read_verilog adffs.v proc -dff2dffe -synth_ice40 -select -assert-count 2 t:SB_DFFR +async2sync +synth -flatten -run coarse # technology-independent coarse grained synthesis +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check same as technology-dependent fine-grained synthesis +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 1 t:SB_DFF select -assert-count 1 t:SB_DFFE select -assert-count 4 t:SB_LUT4 #select -assert-none t:SB_LUT4 t:SB_DFFR t:SB_DFFE t:$_DFFSR_NPP_ t:$_DFFSR_PPP_ %% t:* %D diff --git a/tests/ice40/dffs.v b/tests/ice40/dffs.v index d57c8c97c..d97840c43 100644 --- a/tests/ice40/dffs.v +++ b/tests/ice40/dffs.v @@ -1,5 +1,37 @@ -module top +module dff ( input d, clk, output reg q ); always @( posedge clk ) q <= d; endmodule + +module dffe + ( input d, clk, en, output reg q ); + initial begin + q = 0; + end + always @( posedge clk ) + if ( en ) + q <= d; +endmodule + +module top ( +input clk, +input en, +input a, +output b,b1, +); + +dff u_dff ( + .clk (clk ), + .d (a ), + .q (b ) + ); + +dffe u_ndffe ( + .clk (clk ), + .en (en), + .d (a ), + .q (b1 ) + ); + +endmodule diff --git a/tests/ice40/dffs.ys b/tests/ice40/dffs.ys index 0fa0bc3eb..ddd8e5734 100644 --- a/tests/ice40/dffs.ys +++ b/tests/ice40/dffs.ys @@ -1,11 +1,9 @@ read_verilog dffs.v -proc -flatten -dff2dffe hierarchy -top top synth -flatten -run coarse # technology-independent coarse grained synthesis equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check same as technology-dependent fine-grained synthesis design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 1 t:SB_DFF -select -assert-none t:SB_DFF %% t:* %D +select -assert-count 1 t:SB_DFFE +select -assert-none t:SB_DFF t:SB_DFFE %% t:* %D From 388eb3288c907dbc8b2763ffc20b0b5fccba81ed Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 12:21:54 -0700 Subject: [PATCH 034/130] Remove dffe instantation --- tests/ice40/adffs.v | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/ice40/adffs.v b/tests/ice40/adffs.v index 972184cfa..e09ef52e1 100644 --- a/tests/ice40/adffs.v +++ b/tests/ice40/adffs.v @@ -88,11 +88,4 @@ adffn u_adffn ( .q (b3 ) ); -dffe u_dffe ( - .clk (clk ), - .en (clr), - .d (a ), - .q (b4 ) - ); - endmodule From 9224b3bc1721ae45abf11594b3ab9a58e50aa86f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 12:30:49 -0700 Subject: [PATCH 035/130] Remove tech independent synthesis --- tests/ice40/add_sub.ys | 1 - tests/ice40/adffs.ys | 10 +++++----- tests/ice40/dffs.ys | 3 ++- tests/ice40/div_mod.ys | 2 +- tests/ice40/latches.ys | 5 +++-- tests/ice40/memory.ys | 1 + tests/ice40/mul.ys | 1 - tests/ice40/mux.ys | 8 +++++--- tests/ice40/tribuf.ys | 5 +++-- 9 files changed, 20 insertions(+), 16 deletions(-) diff --git a/tests/ice40/add_sub.ys b/tests/ice40/add_sub.ys index 84f31ec53..8eeb221db 100644 --- a/tests/ice40/add_sub.ys +++ b/tests/ice40/add_sub.ys @@ -1,6 +1,5 @@ read_verilog add_sub.v hierarchy -top top -synth -flatten -run coarse # technology-independent coarse grained synthesis equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check same as technology-dependent fine-grained synthesis design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module diff --git a/tests/ice40/adffs.ys b/tests/ice40/adffs.ys index d58ce1a82..3c676e590 100644 --- a/tests/ice40/adffs.ys +++ b/tests/ice40/adffs.ys @@ -1,12 +1,12 @@ read_verilog adffs.v proc async2sync -synth -flatten -run coarse # technology-independent coarse grained synthesis +flatten equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check same as technology-dependent fine-grained synthesis design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 1 t:SB_DFF -select -assert-count 1 t:SB_DFFE -select -assert-count 4 t:SB_LUT4 -#select -assert-none t:SB_LUT4 t:SB_DFFR t:SB_DFFE t:$_DFFSR_NPP_ t:$_DFFSR_PPP_ %% t:* %D -write_verilog adffs_synth.v +select -assert-count 1 t:SB_DFFN +select -assert-count 2 t:SB_DFFSR +select -assert-count 7 t:SB_LUT4 +select -assert-none t:SB_DFF t:SB_DFFN t:SB_DFFSR t:SB_LUT4 %% t:* %D diff --git a/tests/ice40/dffs.ys b/tests/ice40/dffs.ys index ddd8e5734..b14346f5a 100644 --- a/tests/ice40/dffs.ys +++ b/tests/ice40/dffs.ys @@ -1,6 +1,7 @@ read_verilog dffs.v hierarchy -top top -synth -flatten -run coarse # technology-independent coarse grained synthesis +proc +flatten equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check same as technology-dependent fine-grained synthesis design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module diff --git a/tests/ice40/div_mod.ys b/tests/ice40/div_mod.ys index 93285cede..613cad760 100644 --- a/tests/ice40/div_mod.ys +++ b/tests/ice40/div_mod.ys @@ -1,6 +1,6 @@ read_verilog div_mod.v hierarchy -top top -synth -flatten -run coarse # technology-independent coarse grained synthesis +flatten equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check same as technology-dependent fine-grained synthesis design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module diff --git a/tests/ice40/latches.ys b/tests/ice40/latches.ys index 0abd7f195..fe0d1f70e 100644 --- a/tests/ice40/latches.ys +++ b/tests/ice40/latches.ys @@ -1,5 +1,6 @@ read_verilog latches.v synth_ice40 -select -assert-count 5 t:SB_LUT4 -#select -assert-none t:SB_LUT4 %% t:* %D +cd top +select -assert-count 4 t:SB_LUT4 +select -assert-none t:SB_LUT4 %% t:* %D write_verilog latches_synth.v diff --git a/tests/ice40/memory.ys b/tests/ice40/memory.ys index a0391e93d..0a8c48dca 100644 --- a/tests/ice40/memory.ys +++ b/tests/ice40/memory.ys @@ -1,4 +1,5 @@ read_verilog memory.v synth_ice40 +cd top select -assert-count 1 t:SB_RAM40_4K write_verilog memory_synth.v diff --git a/tests/ice40/mul.ys b/tests/ice40/mul.ys index adf1b3211..aec7d0b1f 100644 --- a/tests/ice40/mul.ys +++ b/tests/ice40/mul.ys @@ -1,6 +1,5 @@ read_verilog mul.v hierarchy -top top -#synth -flatten -run coarse # technology-independent coarse grained synthesis equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -dsp # equivalency check same as technology-dependent fine-grained synthesis design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module diff --git a/tests/ice40/mux.ys b/tests/ice40/mux.ys index 9e3d87b7f..63d22001f 100644 --- a/tests/ice40/mux.ys +++ b/tests/ice40/mux.ys @@ -1,6 +1,8 @@ read_verilog mux.v -synth_ice40 +proc +flatten equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 design -load postopt -select -assert-count 20 t:SB_LUT4 -select -assert-count 1 t:SB_CARRY +cd top +select -assert-count 19 t:SB_LUT4 +select -assert-none t:SB_LUT4 %% t:* %D diff --git a/tests/ice40/tribuf.ys b/tests/ice40/tribuf.ys index 9b7ea1eab..8049a37ab 100644 --- a/tests/ice40/tribuf.ys +++ b/tests/ice40/tribuf.ys @@ -1,7 +1,8 @@ read_verilog tribuf.v hierarchy -top top -synth -flatten -run coarse # technology-independent coarse grained synthesis -equiv_opt -map +/ice40/cells_sim.v synth_ice40 # equivalency check same as technology-dependent fine-grained synthesis +proc +flatten +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check same as technology-dependent fine-grained synthesis design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 1 t:$_TBUF_ From f9906eed68beab359ed83beee2bcf42ffac908c3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 12:35:35 -0700 Subject: [PATCH 036/130] Fix comments --- tests/ice40/add_sub.ys | 2 +- tests/ice40/adffs.ys | 4 ++-- tests/ice40/dffs.ys | 2 +- tests/ice40/div_mod.ys | 2 +- tests/ice40/memory.ys | 1 + tests/ice40/mul.ys | 2 +- tests/ice40/mux.ys | 6 +++--- tests/ice40/tribuf.ys | 2 +- 8 files changed, 11 insertions(+), 10 deletions(-) diff --git a/tests/ice40/add_sub.ys b/tests/ice40/add_sub.ys index 8eeb221db..4a998d98d 100644 --- a/tests/ice40/add_sub.ys +++ b/tests/ice40/add_sub.ys @@ -1,6 +1,6 @@ read_verilog add_sub.v hierarchy -top top -equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check same as technology-dependent fine-grained synthesis +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 11 t:SB_LUT4 diff --git a/tests/ice40/adffs.ys b/tests/ice40/adffs.ys index 3c676e590..14b251c5c 100644 --- a/tests/ice40/adffs.ys +++ b/tests/ice40/adffs.ys @@ -1,8 +1,8 @@ read_verilog adffs.v proc -async2sync +async2sync # converts async flops to a 'sync' variant clocked by a 'super'-clock flatten -equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check same as technology-dependent fine-grained synthesis +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 1 t:SB_DFF diff --git a/tests/ice40/dffs.ys b/tests/ice40/dffs.ys index b14346f5a..ee7f884b1 100644 --- a/tests/ice40/dffs.ys +++ b/tests/ice40/dffs.ys @@ -2,7 +2,7 @@ read_verilog dffs.v hierarchy -top top proc flatten -equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check same as technology-dependent fine-grained synthesis +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 1 t:SB_DFF diff --git a/tests/ice40/div_mod.ys b/tests/ice40/div_mod.ys index 613cad760..96753b4ef 100644 --- a/tests/ice40/div_mod.ys +++ b/tests/ice40/div_mod.ys @@ -1,7 +1,7 @@ read_verilog div_mod.v hierarchy -top top flatten -equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check same as technology-dependent fine-grained synthesis +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 88 t:SB_LUT4 diff --git a/tests/ice40/memory.ys b/tests/ice40/memory.ys index 0a8c48dca..fa5d004b0 100644 --- a/tests/ice40/memory.ys +++ b/tests/ice40/memory.ys @@ -2,4 +2,5 @@ read_verilog memory.v synth_ice40 cd top select -assert-count 1 t:SB_RAM40_4K +select -assert-none t:SB_RAM40_4K %% t:* %D write_verilog memory_synth.v diff --git a/tests/ice40/mul.ys b/tests/ice40/mul.ys index aec7d0b1f..8a0822a84 100644 --- a/tests/ice40/mul.ys +++ b/tests/ice40/mul.ys @@ -1,6 +1,6 @@ read_verilog mul.v hierarchy -top top -equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -dsp # equivalency check same as technology-dependent fine-grained synthesis +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -dsp # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 1 t:SB_MAC16 diff --git a/tests/ice40/mux.ys b/tests/ice40/mux.ys index 63d22001f..182b49499 100644 --- a/tests/ice40/mux.ys +++ b/tests/ice40/mux.ys @@ -1,8 +1,8 @@ read_verilog mux.v proc flatten -equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -design -load postopt -cd top +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module select -assert-count 19 t:SB_LUT4 select -assert-none t:SB_LUT4 %% t:* %D diff --git a/tests/ice40/tribuf.ys b/tests/ice40/tribuf.ys index 8049a37ab..ef4266959 100644 --- a/tests/ice40/tribuf.ys +++ b/tests/ice40/tribuf.ys @@ -2,7 +2,7 @@ read_verilog tribuf.v hierarchy -top top proc flatten -equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check same as technology-dependent fine-grained synthesis +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 1 t:$_TBUF_ From 61087329efcfac45de6b69ded33f38c8f8817eef Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 12:36:27 -0700 Subject: [PATCH 037/130] Fix tribuf test --- tests/ice40/tribuf.ys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ice40/tribuf.ys b/tests/ice40/tribuf.ys index ef4266959..d1e1b3108 100644 --- a/tests/ice40/tribuf.ys +++ b/tests/ice40/tribuf.ys @@ -2,7 +2,7 @@ read_verilog tribuf.v hierarchy -top top proc flatten -equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check +equiv_opt -assert -map +/ice40/cells_sim.v -map +/simcells.v synth_ice40 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 1 t:$_TBUF_ From 659a481482b59efd672034bff9e034fa6d47336c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 13:57:11 -0700 Subject: [PATCH 038/130] Remove unused output --- tests/ice40/adffs.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ice40/adffs.v b/tests/ice40/adffs.v index e09ef52e1..93c8bf52c 100644 --- a/tests/ice40/adffs.v +++ b/tests/ice40/adffs.v @@ -55,7 +55,7 @@ input clk, input clr, input pre, input a, -output b,b1,b2,b3,b4 +output b,b1,b2,b3 ); dffsr u_dffsr ( From 8e3754bdb468842a784ef5eac8427a59055673c3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 13:57:19 -0700 Subject: [PATCH 039/130] Hide tri-state warning message for now --- tests/ice40/.gitignore | 1 + tests/ice40/run-test.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/ice40/.gitignore b/tests/ice40/.gitignore index 397b4a762..1d329c933 100644 --- a/tests/ice40/.gitignore +++ b/tests/ice40/.gitignore @@ -1 +1,2 @@ *.log +/run-test.mk diff --git a/tests/ice40/run-test.sh b/tests/ice40/run-test.sh index 5bd9fb173..184d8f09b 100755 --- a/tests/ice40/run-test.sh +++ b/tests/ice40/run-test.sh @@ -12,7 +12,7 @@ for x in *.ys; do echo "all:: run-$x" echo "run-$x:" echo " @echo 'Running $x..'" - echo " @../../yosys -ql ${x%.ys}.log $x" + echo " @../../yosys -ql ${x%.ys}.log $x -w 'Yosys has only limited support for tri-state logic at the moment.'" done for t in *_tb.v; do echo "all:: run-$t" From 5061d239ae2d6881b898662f838a0f4cfc24ca88 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 14:03:02 -0700 Subject: [PATCH 040/130] Fail if iverilog fails --- tests/ice40/run-test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ice40/run-test.sh b/tests/ice40/run-test.sh index 184d8f09b..90a8a3c83 100755 --- a/tests/ice40/run-test.sh +++ b/tests/ice40/run-test.sh @@ -18,8 +18,8 @@ for t in *_tb.v; do echo "all:: run-$t" echo "run-$t:" echo " @echo 'Running $t..'" - echo " @iverilog -o ${t%_tb.v}_testbench $t ${t%_tb.v}_synth.v common.v $COMMON_PREFIX/simcells.v $TECHLIBS_PREFIX/ice40/cells_sim.v" - echo " @if ! vvp -N ${t%_tb.v}_testbench > ${t%_tb.v}_testbench.log 2>&1; then grep 'ERROR' ${t%_tb.v}_testbench.log; exit 0; elif grep 'ERROR' ${t%_tb.v}_testbench.log || ! grep 'OKAY' ${t%_tb.v}_testbench.log; then echo "FAIL"; exit 0; fi" + echo " @iverilog -o ${t%_tb.v}_testbench $t ${t%_tb.v}_synth.v common.v $TECHLIBS_PREFIX/ice40/cells_sim.v" + echo " @vvp -N ${t%_tb.v}_testbench" done for s in *.sh; do if [ "$s" != "run-test.sh" ]; then From 65e6c23abd9add59b95a024c91d4fff6d15ba135 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 14:20:03 -0700 Subject: [PATCH 041/130] Spelling --- passes/equiv/equiv_make.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/equiv/equiv_make.cc b/passes/equiv/equiv_make.cc index dbd8682e6..4855ce29e 100644 --- a/passes/equiv/equiv_make.cc +++ b/passes/equiv/equiv_make.cc @@ -532,10 +532,10 @@ struct EquivMakePass : public Pass { log_cmd_error("Equiv module %s already exists.\n", args[argidx+2].c_str()); if (worker.gold_mod->has_memories() || worker.gold_mod->has_processes()) - log_cmd_error("Gold module contains memories or procresses. Run 'memory' or 'proc' respectively.\n"); + log_cmd_error("Gold module contains memories or processes. Run 'memory' or 'proc' respectively.\n"); if (worker.gate_mod->has_memories() || worker.gate_mod->has_processes()) - log_cmd_error("Gate module contains memories or procresses. Run 'memory' or 'proc' respectively.\n"); + log_cmd_error("Gate module contains memories or processes. Run 'memory' or 'proc' respectively.\n"); worker.read_blacklists(); worker.read_encfiles(); From 43e7c4917ad42b01d34b496c35798416a050aa61 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 15:50:38 -0700 Subject: [PATCH 042/130] Do not print OKAY --- tests/ice40/latches_tb.v | 2 -- tests/ice40/memory_tb.v | 2 -- 2 files changed, 4 deletions(-) diff --git a/tests/ice40/latches_tb.v b/tests/ice40/latches_tb.v index 47ae8670c..b0585264b 100644 --- a/tests/ice40/latches_tb.v +++ b/tests/ice40/latches_tb.v @@ -10,8 +10,6 @@ module testbench; #5 clk = 1; #5 clk = 0; end - - $display("OKAY"); end diff --git a/tests/ice40/memory_tb.v b/tests/ice40/memory_tb.v index 5905f3ddd..be69374eb 100644 --- a/tests/ice40/memory_tb.v +++ b/tests/ice40/memory_tb.v @@ -10,8 +10,6 @@ module testbench; #5 clk = 1; #5 clk = 0; end - - $display("OKAY"); end From 698a0e3aafcae48535c68996fccf002c0e0e3aea Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 15:50:45 -0700 Subject: [PATCH 043/130] WIP for equivalency checking memories --- tests/ice40/memory.ys | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/ice40/memory.ys b/tests/ice40/memory.ys index fa5d004b0..9b7490cd8 100644 --- a/tests/ice40/memory.ys +++ b/tests/ice40/memory.ys @@ -1,5 +1,17 @@ read_verilog memory.v -synth_ice40 +hierarchy -top top +proc +memory -nomap +equiv_opt -run :prove -map +/ice40/cells_sim.v synth_ice40 +memory +opt -full + +# TODO +#equiv_opt -run prove: -assert null +miter -equiv -flatten -make_assert -make_outputs gold gate miter +#sat -verify -prove-asserts -tempinduct -show-inputs -show-outputs miter + +design -load postopt cd top select -assert-count 1 t:SB_RAM40_4K select -assert-none t:SB_RAM40_4K %% t:* %D From e1fff34dde994f6d175311c61c5a63b5a21b549b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 10 Jun 2019 16:16:40 -0700 Subject: [PATCH 044/130] If d_bit already in sigbit_chain_next, create extra wire --- passes/techmap/shregmap.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index d472d1275..6c00d4d53 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -140,10 +140,13 @@ struct ShregmapWorker if (opts.init || sigbit_init.count(q_bit) == 0) { - if (sigbit_chain_next.count(d_bit)) { + auto r = sigbit_chain_next.insert(std::make_pair(d_bit, cell)); + if (!r.second) { sigbit_with_non_chain_users.insert(d_bit); - } else - sigbit_chain_next[d_bit] = cell; + Wire *wire = module->addWire(NEW_ID); + module->connect(wire, d_bit); + sigbit_chain_next.insert(std::make_pair(wire, cell)); + } sigbit_chain_prev[q_bit] = cell; continue; From 5ff75b1cdce45fdc8422dbe2ac327217a5d2a2e6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 11 Jun 2019 15:48:20 -0700 Subject: [PATCH 045/130] Try way that doesn't involve creating a new wire --- passes/techmap/shregmap.cc | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 6c00d4d53..811b40eac 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -141,12 +141,8 @@ struct ShregmapWorker if (opts.init || sigbit_init.count(q_bit) == 0) { auto r = sigbit_chain_next.insert(std::make_pair(d_bit, cell)); - if (!r.second) { + if (!r.second) sigbit_with_non_chain_users.insert(d_bit); - Wire *wire = module->addWire(NEW_ID); - module->connect(wire, d_bit); - sigbit_chain_next.insert(std::make_pair(wire, cell)); - } sigbit_chain_prev[q_bit] = cell; continue; @@ -164,14 +160,14 @@ struct ShregmapWorker { for (auto it : sigbit_chain_next) { + Cell *c1, *c2 = it.second; + if (opts.tech == nullptr && sigbit_with_non_chain_users.count(it.first)) goto start_cell; - if (sigbit_chain_prev.count(it.first) != 0) + c1 = sigbit_chain_prev.at(it.first, nullptr); + if (c1 != nullptr) { - Cell *c1 = sigbit_chain_prev.at(it.first); - Cell *c2 = it.second; - if (c1->type != c2->type) goto start_cell; @@ -181,6 +177,15 @@ struct ShregmapWorker IdString d_port = opts.ffcells.at(c1->type).first; IdString q_port = opts.ffcells.at(c1->type).second; + // If the previous cell's D has other non chain users, + // then it is possible that this previous cell could + // be a start of the chain + SigBit d_bit = sigmap(c1->getPort(d_port).as_bit()); + if (sigbit_with_non_chain_users.count(d_bit)) { + c2 = c1; + goto start_cell; + } + auto c1_conn = c1->connections(); auto c2_conn = c1->connections(); @@ -197,7 +202,7 @@ struct ShregmapWorker } start_cell: - chain_start_cells.insert(it.second); + chain_start_cells.insert(c2); } } From 8691596d19e2384ccf946f2b391bf5c17db0d60e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 11 Jun 2019 16:05:42 -0700 Subject: [PATCH 046/130] Revert "Try way that doesn't involve creating a new wire" This reverts commit 2f427acc9ed23c77e89386f4fbf53ac580bf0f0b. --- passes/techmap/shregmap.cc | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 811b40eac..6c00d4d53 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -141,8 +141,12 @@ struct ShregmapWorker if (opts.init || sigbit_init.count(q_bit) == 0) { auto r = sigbit_chain_next.insert(std::make_pair(d_bit, cell)); - if (!r.second) + if (!r.second) { sigbit_with_non_chain_users.insert(d_bit); + Wire *wire = module->addWire(NEW_ID); + module->connect(wire, d_bit); + sigbit_chain_next.insert(std::make_pair(wire, cell)); + } sigbit_chain_prev[q_bit] = cell; continue; @@ -160,14 +164,14 @@ struct ShregmapWorker { for (auto it : sigbit_chain_next) { - Cell *c1, *c2 = it.second; - if (opts.tech == nullptr && sigbit_with_non_chain_users.count(it.first)) goto start_cell; - c1 = sigbit_chain_prev.at(it.first, nullptr); - if (c1 != nullptr) + if (sigbit_chain_prev.count(it.first) != 0) { + Cell *c1 = sigbit_chain_prev.at(it.first); + Cell *c2 = it.second; + if (c1->type != c2->type) goto start_cell; @@ -177,15 +181,6 @@ struct ShregmapWorker IdString d_port = opts.ffcells.at(c1->type).first; IdString q_port = opts.ffcells.at(c1->type).second; - // If the previous cell's D has other non chain users, - // then it is possible that this previous cell could - // be a start of the chain - SigBit d_bit = sigmap(c1->getPort(d_port).as_bit()); - if (sigbit_with_non_chain_users.count(d_bit)) { - c2 = c1; - goto start_cell; - } - auto c1_conn = c1->connections(); auto c2_conn = c1->connections(); @@ -202,7 +197,7 @@ struct ShregmapWorker } start_cell: - chain_start_cells.insert(c2); + chain_start_cells.insert(it.second); } } From e7a8cdbccfa6f619f2e25c540b5af6d8e34ff431 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 08:34:06 -0700 Subject: [PATCH 047/130] Add shregmap -tech xilinx test --- tests/various/shregmap.ys | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/various/shregmap.ys b/tests/various/shregmap.ys index 0e5fe882b..a717c54f1 100644 --- a/tests/various/shregmap.ys +++ b/tests/various/shregmap.ys @@ -64,3 +64,4 @@ sat -verify -prove-asserts -show-ports -seq 5 miter # design -load gate # stat + From cfafd360d52795c9c76c69d008f765d171e2b0ed Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 16:57:54 -0700 Subject: [PATCH 048/130] Add comment as per @cliffordwolf --- passes/techmap/shregmap.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 6c00d4d53..f308292fa 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -142,7 +142,18 @@ struct ShregmapWorker { auto r = sigbit_chain_next.insert(std::make_pair(d_bit, cell)); if (!r.second) { + // Insertion not successful means that d_bit is already + // connected to another register, thus mark it as a + // non chain user ... sigbit_with_non_chain_users.insert(d_bit); + // ... and clone d_bit into another wire, and use that + // wire as a different key in the d_bit-to-cell dictionary + // so that it can be identified as another chain + // (omitting this common flop) + // Link: https://github.com/YosysHQ/yosys/pull/1085 + // NB: This relies on us not updating sigmap with this + // alias otherwise it would think they are the same + // wire Wire *wire = module->addWire(NEW_ID); module->connect(wire, d_bit); sigbit_chain_next.insert(std::make_pair(wire, cell)); From 53fed4f7e9cd6512762cf93c74464d8e40efb414 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 17:03:05 -0700 Subject: [PATCH 049/130] Actually, there might not be any harm in updating sigmap... --- passes/techmap/shregmap.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index f308292fa..9da69e8ba 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -151,11 +151,9 @@ struct ShregmapWorker // so that it can be identified as another chain // (omitting this common flop) // Link: https://github.com/YosysHQ/yosys/pull/1085 - // NB: This relies on us not updating sigmap with this - // alias otherwise it would think they are the same - // wire Wire *wire = module->addWire(NEW_ID); module->connect(wire, d_bit); + sigmap.add(wire, d_bit); sigbit_chain_next.insert(std::make_pair(wire, cell)); } From 66607845eccb2e3bc17b017c4f6b109aeaecdf77 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 16:18:07 -0700 Subject: [PATCH 050/130] Remove Xilinx test --- tests/various/shregmap.ys | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/tests/various/shregmap.ys b/tests/various/shregmap.ys index a717c54f1..16e5f40e1 100644 --- a/tests/various/shregmap.ys +++ b/tests/various/shregmap.ys @@ -31,37 +31,3 @@ sat -verify -prove-asserts -show-ports -seq 5 miter #design -load gate #stat - -########## - -design -load read -design -copy-to model $__XILINX_SHREG_ -hierarchy -top shregmap_variable_test -prep -design -save gold - -simplemap t:$dff t:$dffe -shregmap -tech xilinx - -#stat -# show -width -# write_verilog -noexpr -norename -select -assert-count 1 t:$_DFF_P_ -select -assert-count 2 t:$__XILINX_SHREG_ - -design -stash gate - -design -import gold -as gold -design -import gate -as gate -design -copy-from model -as $__XILINX_SHREG_ \$__XILINX_SHREG_ -prep - -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports -seq 5 miter - -# design -load gold -# stat - -# design -load gate -# stat - From 2b37a093e95036b267481b2dae2046278eef4040 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 16:42:19 -0700 Subject: [PATCH 051/130] In sat: 'x' in init attr should not override constant --- passes/sat/sat.cc | 2 ++ tests/sat/initval.v | 4 ++++ tests/sat/initval.ys | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index dd56d8c71..bcc690fa3 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -268,6 +268,8 @@ struct SatHelper RTLIL::SigSpec removed_bits; for (int i = 0; i < lhs.size(); i++) { RTLIL::SigSpec bit = lhs.extract(i, 1); + if (bit.is_fully_const() && rhs[i] == State::Sx) + rhs[i] = bit; if (!satgen.initial_state.check_all(bit)) { removed_bits.append(bit); lhs.remove(i, 1); diff --git a/tests/sat/initval.v b/tests/sat/initval.v index 5b661f8d6..d46ccae48 100644 --- a/tests/sat/initval.v +++ b/tests/sat/initval.v @@ -1,6 +1,7 @@ module test(input clk, input [3:0] bar, output [3:0] foo); reg [3:0] foo = 0; reg [3:0] last_bar = 0; + reg [3:0] asdf = 4'b1xxx; always @* foo[1:0] <= bar[1:0]; @@ -11,5 +12,8 @@ module test(input clk, input [3:0] bar, output [3:0] foo); always @(posedge clk) last_bar <= bar; + always @* + asdf[2:0] <= 3'b111; + assert property (foo == {last_bar[3:2], bar[1:0]}); endmodule diff --git a/tests/sat/initval.ys b/tests/sat/initval.ys index 2079d2f34..3d88aa971 100644 --- a/tests/sat/initval.ys +++ b/tests/sat/initval.ys @@ -1,4 +1,4 @@ read_verilog -sv initval.v -proc;; +proc; sat -seq 10 -prove-asserts From 36cf0a3dd5a9599b60eb449a2401454e7a7af6fd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 16:50:14 -0700 Subject: [PATCH 052/130] Remove adffs_tb.v --- tests/ice40/adffs_tb.v | 75 ------------------------------------------ 1 file changed, 75 deletions(-) delete mode 100644 tests/ice40/adffs_tb.v diff --git a/tests/ice40/adffs_tb.v b/tests/ice40/adffs_tb.v deleted file mode 100644 index e049edabc..000000000 --- a/tests/ice40/adffs_tb.v +++ /dev/null @@ -1,75 +0,0 @@ -module testbench; - reg clk; - - initial begin - // $dumpfile("testbench.vcd"); - // $dumpvars(0, testbench); - - #5 clk = 0; - repeat (10000) begin - #5 clk = 1; - #5 clk = 0; - end - - $display("OKAY"); - end - - - reg [2:0] dinA = 0; - wire doutB,doutB1,doutB2,doutB3,doutB4; - reg dff,ndff,adff,adffn,dffe = 0; - - top uut ( - .clk (clk ), - .a (dinA[0] ), - .pre (dinA[1] ), - .clr (dinA[2] ), - .b (doutB ), - .b1 (doutB1 ), - .b2 (doutB2 ) - ); - - always @(posedge clk) begin - #3; - dinA <= dinA + 1; - end - - always @( posedge clk, posedge dinA[1], posedge dinA[2] ) - if ( dinA[2] ) - dff <= 1'b0; - else if ( dinA[1] ) - dff <= 1'b1; - else - dff <= dinA[0]; - - always @( negedge clk, negedge dinA[1], negedge dinA[2] ) - if ( !dinA[2] ) - ndff <= 1'b0; - else if ( !dinA[1] ) - ndff <= 1'b1; - else - ndff <= dinA[0]; - - always @( posedge clk, posedge dinA[2] ) - if ( dinA[2] ) - adff <= 1'b0; - else - adff <= dinA[0]; - - always @( posedge clk, negedge dinA[2] ) - if ( !dinA[2] ) - adffn <= 1'b0; - else - adffn <= dinA[0]; - - always @( posedge clk ) - if ( dinA[2] ) - dffe <= dinA[0]; - - assert_dff dff_test(.clk(clk), .test(doutB), .pat(dff)); - assert_dff ndff_test(.clk(clk), .test(doutB1), .pat(ndff)); - assert_dff adff_test(.clk(clk), .test(doutB2), .pat(adff)); - //assert_dff adffn_test(.clk(clk), .test(doutB3), .pat(adffn)); - //assert_dff dffe_test(.clk(clk), .test(doutB4), .pat(dffe)); - -endmodule From 0b25dbf1c6107fc993ab3c88b82c3e33f0bbd516 Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Fri, 23 Aug 2019 12:40:14 +0300 Subject: [PATCH 053/130] Fix path in run-test.sh --- tests/ice40/run-test.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ice40/run-test.sh b/tests/ice40/run-test.sh index 90a8a3c83..ddd6d349f 100755 --- a/tests/ice40/run-test.sh +++ b/tests/ice40/run-test.sh @@ -1,7 +1,7 @@ set -e -if [ -f "../../../../../techlibs/common/simcells.v" ]; then - COMMON_PREFIX=../../../../../techlibs/common - TECHLIBS_PREFIX=../../../../../techlibs +if [ -f "../../techlibs/common/simcells.v" ]; then + COMMON_PREFIX=../../techlibs/common + TECHLIBS_PREFIX=../../techlibs else COMMON_PREFIX=/usr/local/share/yosys TECHLIBS_PREFIX=/usr/local/share/yosys From 3c10f58d043432197fdf5169404710f8ab68db8c Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Fri, 23 Aug 2019 17:00:16 +0300 Subject: [PATCH 054/130] Fix run-test.sh; Add new test for dpram. --- tests/ice40/dpram.v | 20 ++++++++++ tests/ice40/dpram.ys | 18 +++++++++ tests/ice40/dpram_tb.v | 81 +++++++++++++++++++++++++++++++++++++++++ tests/ice40/run-test.sh | 2 +- 4 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 tests/ice40/dpram.v create mode 100644 tests/ice40/dpram.ys create mode 100644 tests/ice40/dpram_tb.v diff --git a/tests/ice40/dpram.v b/tests/ice40/dpram.v new file mode 100644 index 000000000..2e69d6b3b --- /dev/null +++ b/tests/ice40/dpram.v @@ -0,0 +1,20 @@ +module top (din, write_en, waddr, wclk, raddr, rclk, dout); +parameter addr_width = 8; +parameter data_width = 8; +input [addr_width-1:0] waddr, raddr; +input [data_width-1:0] din; +input write_en, wclk, rclk; +output [data_width-1:0] dout; +reg [data_width-1:0] dout; +reg [data_width-1:0] mem [(1< 6'h3E) + mem_init <= 1; + end + + always @(posedge clk) begin + //#3; + we_a <= !we_a; + end + + reg [7:0] mem [(1<<8)-1:0]; + + always @(posedge clk) // Write memory. + begin + if (we_a) + mem[addr_a] <= data_a; // Using write address bus. + end + always @(posedge clk) // Read memory. + begin + pq_a <= mem[addr_b]; // Using read address bus. + end + + top uut ( + .din(data_a), + .write_en(we_a), + .waddr(addr_a), + .wclk(clk), + .raddr(addr_b), + .rclk(clk), + .dout(q_a) + ); + + uut_mem_checker port_a_test(.clk(clk), .init(mem_init), .en(!we_a), .A(q_a), .B(pq_a)); + +endmodule + +module uut_mem_checker(input clk, input init, input en, input [7:0] A, input [7:0] B); + always @(posedge clk) + begin + #1; + if (en == 1 & init == 1 & A !== B) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); + $stop; + end + end +endmodule diff --git a/tests/ice40/run-test.sh b/tests/ice40/run-test.sh index ddd6d349f..75aa08339 100755 --- a/tests/ice40/run-test.sh +++ b/tests/ice40/run-test.sh @@ -16,7 +16,7 @@ for x in *.ys; do done for t in *_tb.v; do echo "all:: run-$t" - echo "run-$t:" + echo "run-$t: ${t%_tb.v}_synth.v" echo " @echo 'Running $t..'" echo " @iverilog -o ${t%_tb.v}_testbench $t ${t%_tb.v}_synth.v common.v $TECHLIBS_PREFIX/ice40/cells_sim.v" echo " @vvp -N ${t%_tb.v}_testbench" From c29380b381b68396342990822c63c36381f3ee3a Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Fri, 23 Aug 2019 18:55:01 +0300 Subject: [PATCH 055/130] Fix pull request --- tests/ice40/.gitignore | 2 ++ tests/ice40/run-test.sh | 14 +++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/ice40/.gitignore b/tests/ice40/.gitignore index 1d329c933..9a71dca69 100644 --- a/tests/ice40/.gitignore +++ b/tests/ice40/.gitignore @@ -1,2 +1,4 @@ *.log /run-test.mk ++*_synth.v ++*_testbench diff --git a/tests/ice40/run-test.sh b/tests/ice40/run-test.sh index 75aa08339..bd9d35314 100755 --- a/tests/ice40/run-test.sh +++ b/tests/ice40/run-test.sh @@ -13,14 +13,14 @@ for x in *.ys; do echo "run-$x:" echo " @echo 'Running $x..'" echo " @../../yosys -ql ${x%.ys}.log $x -w 'Yosys has only limited support for tri-state logic at the moment.'" + + if [ -f "${x%.ys}_tb.v" ]; then + echo " @echo 'Running ${x%.ys}_tb.v..'" + echo " @iverilog -o ${x%.ys}_testbench $t ${x%.ys}_synth.v common.v $TECHLIBS_PREFIX/ice40/cells_sim.v" + echo " @vvp -N ${x%.ys}_testbench" + fi done -for t in *_tb.v; do - echo "all:: run-$t" - echo "run-$t: ${t%_tb.v}_synth.v" - echo " @echo 'Running $t..'" - echo " @iverilog -o ${t%_tb.v}_testbench $t ${t%_tb.v}_synth.v common.v $TECHLIBS_PREFIX/ice40/cells_sim.v" - echo " @vvp -N ${t%_tb.v}_testbench" -done + for s in *.sh; do if [ "$s" != "run-test.sh" ]; then echo "all:: run-$s" From 18b64609c25313c73ac18af1c5963bf830f95dba Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 12:22:06 -0700 Subject: [PATCH 056/130] xilinx_srl to use 'slice' features of pmgen for word level --- passes/pmgen/xilinx_srl.cc | 47 ++++++++++++++++++++++++------------- passes/pmgen/xilinx_srl.pmg | 34 ++++++++++++++------------- 2 files changed, 49 insertions(+), 32 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index 22fb93e18..da7acf745 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -105,13 +105,15 @@ void run_variable(xilinx_srl_pm &pm) log("Found variable chain of length %d (%s):\n", GetSize(ud.chain), log_id(st.first->type)); - auto last_cell = ud.chain.back(); + auto last_cell = ud.chain.back().first; SigSpec initval; - for (auto cell : ud.chain) { + for (const auto &i : ud.chain) { + auto cell = i.first; + auto slice = i.second; log_debug(" %s\n", log_id(cell)); - if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) { - SigBit Q = cell->getPort(ID(Q)); + if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID($dff), ID($dffe))) { + SigBit Q = cell->getPort(ID(Q))[slice]; log_assert(Q.wire); auto it = Q.wire->attributes.find(ID(init)); if (it != Q.wire->attributes.end()) { @@ -123,7 +125,7 @@ void run_variable(xilinx_srl_pm &pm) else log_abort(); if (cell != last_cell) - pm.autoremove(cell); + cell->connections_.at(ID(Q))[slice] = pm.module->addWire(NEW_ID); } pm.autoremove(st.shiftx); @@ -131,23 +133,36 @@ void run_variable(xilinx_srl_pm &pm) SigBit Q = st.first->getPort(ID(Q)); c->setPort(ID(Q), Q); - if (c->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) { - c->parameters.clear(); - c->setParam(ID(DEPTH), GetSize(ud.chain)); - c->setParam(ID(INIT), initval.as_const()); + if (c->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID($dff), ID($dffe))) { + Const clkpol, enpol; if (c->type.in(ID($_DFF_P_), ID($_DFFE_PN_), ID($_DFFE_PP_))) - c->setParam(ID(CLKPOL), 1); - else if (c->type.in(ID($_DFF_N_), ID($DFFE_NN_), ID($_DFFE_NP_), ID(FDRE_1))) - c->setParam(ID(CLKPOL), 0); + clkpol = 1; + else if (c->type.in(ID($_DFF_N_), ID($DFFE_NN_), ID($_DFFE_NP_))) + clkpol = 0; + else if (c->type.in(ID($dff), ID($dffe))) { + clkpol = c->getParam(ID(CLK_POLARITY)); + c->setPort(ID(C), c->getPort(ID(CLK))); + c->unsetPort(ID(CLK)); + } else log_abort(); if (c->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_))) - c->setParam(ID(ENPOL), 1); + enpol = 1; else if (c->type.in(ID($_DFFE_NN_), ID($_DFFE_PN_))) - c->setParam(ID(ENPOL), 0); + enpol = 0; + else if (c->type.in(ID($dffe))) { + enpol = c->getParam(ID(EN_POLARITY)); + c->setPort(ID(E), c->getPort(ID(EN))); + c->unsetPort(ID(EN)); + } else - c->setParam(ID(ENPOL), 2); - if (c->type.in(ID($_DFF_N_), ID($_DFF_P_))) + enpol = 2; + c->parameters.clear(); + c->setParam(ID(DEPTH), GetSize(ud.chain)); + c->setParam(ID(INIT), initval.as_const()); + c->setParam(ID(CLKPOL), clkpol); + c->setParam(ID(ENPOL), enpol); + if (c->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($dff))) c->setPort(ID(E), State::S1); c->setPort(ID(L), st.shiftx->getPort(ID(B))); c->setPort(ID(Q), st.shiftx->getPort(ID(Y))); diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 0cc551e92..fffff91e8 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -151,8 +151,9 @@ endcode pattern variable state shiftx_width +state slice udata minlen -udata > chain +udata >> chain match shiftx select shiftx->type.in($shiftx) @@ -166,13 +167,16 @@ code shiftx_width endcode match first - select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_) - select nusers(port(first, \Q)) == 2 - index port(first, \Q) === port(shiftx, \A)[shiftx_width-1] + select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, $dff, $dffe) + select !first->has_keep_attr() + slice idx GetSize(port(first, \Q)) + select nusers(port(first, \Q)[idx]) == 2 + index port(first, \Q)[idx] === port(shiftx, \A)[shiftx_width-1] + set slice idx endmatch code - chain.push_back(first); + chain.emplace_back(first, slice); subpattern(tail); finally if (GetSize(chain) == shiftx_width) @@ -185,26 +189,24 @@ endcode subpattern tail arg shiftx arg shiftx_width +arg slice match next semioptional - select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_) + select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, $dff, $dffe) select !next->has_keep_attr() select !port(next, \D)[0].wire->get_bool_attribute(\keep) - select nusers(port(next, \Q)) == 3 - index next->type === chain.back()->type - index port(next, \Q) === port(chain.back(), \D) - index port(next, \Q) === port(shiftx, \A)[shiftx_width-1-GetSize(chain)] + slice idx GetSize(port(next, \Q)) + select nusers(port(next, \Q)[idx]) == 3 + index next->type === chain.back().first->type + index port(next, \Q)[idx] === port(chain.back().first, \D)[chain.back().second] + index port(next, \Q)[idx] === port(shiftx, \A)[shiftx_width-1-GetSize(chain)] + set slice idx endmatch code if (next) { - auto sig = port(next, \Q); - log_warning("nusers of '%s'\n", log_signal(sig)); - for (auto bit : sigmap(sig)) - for (auto user : sigusers[bit]) - log_warning("\t%s\n", log_id(user)); - chain.push_back(next); + chain.emplace_back(next, slice); if (GetSize(chain) < shiftx_width) subpattern(tail); } From 08139aa53ab2aa7916c9c42fab9bf6261621c265 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 12:22:46 -0700 Subject: [PATCH 057/130] xilinx_srl now copes with word-level flops $dff{,e} --- techlibs/xilinx/synth_xilinx.cc | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 8bf43bf97..5e9cd8a0e 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -265,9 +265,8 @@ struct SynthXilinxPass : public ScriptPass if (widemux > 0 || help_mode) run("muxpack", " ('-widemux' only)"); - // shregmap -tech xilinx can cope with $shiftx and $mux - // cells for identifying variable-length shift registers, - // so attempt to convert $pmux-es to the former + // xilinx_srl looks for $shiftx cells for identifying variable-length + // shift registers, so attempt to convert $pmux-es to this // Also: wide multiplexer inference benefits from this too if (!(nosrl && widemux == 0) || help_mode) { run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')"); @@ -349,12 +348,8 @@ struct SynthXilinxPass : public ScriptPass } run("opt -full"); - if (!nosrl || help_mode) { - // shregmap operates on bit-level flops, not word-level, - // so break those down here - run("simplemap t:$dff t:$dffe", " (skip if '-nosrl')"); + if (!nosrl || help_mode) run("xilinx_srl -variable -minlen 3", "(skip if '-nosrl')"); - } std::string techmap_args = " -map +/techmap.v"; if (help_mode) From cee30deef5f48b97af961ecb6f7194eac14d891c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 12:24:25 -0700 Subject: [PATCH 058/130] Mention shregmap -tech xilinx is superseded --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index b4b3005d4..5848ae705 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -29,7 +29,7 @@ Yosys 0.9 .. Yosys 0.9-dev - Removed "ice40_unlut" - Improvements in pmgen: slices, choices, define, generate - Added "xilinx_srl" for Xilinx shift register extraction - - Removed "shregmap -tech xilinx" + - Removed "shregmap -tech xilinx" (superseded by "xilinx_srl") Yosys 0.8 .. Yosys 0.8-dev -------------------------- From 242b3083eac817c927624db735ca3196223f97c0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 13:06:31 -0700 Subject: [PATCH 059/130] Cope with possibility that D could connect to Q on same cell --- passes/pmgen/xilinx_srl.pmg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index fffff91e8..5d74b91bc 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -197,7 +197,7 @@ match next select !next->has_keep_attr() select !port(next, \D)[0].wire->get_bool_attribute(\keep) slice idx GetSize(port(next, \Q)) - select nusers(port(next, \Q)[idx]) == 3 + select nusers(port(next, \Q)[idx]) <= 3 index next->type === chain.back().first->type index port(next, \Q)[idx] === port(chain.back().first, \D)[chain.back().second] index port(next, \Q)[idx] === port(shiftx, \A)[shiftx_width-1-GetSize(chain)] From 5939ffdc077eb155e5ecf21da08bb18b69924854 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 13:06:59 -0700 Subject: [PATCH 060/130] Forgot to slice --- passes/pmgen/xilinx_srl.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index da7acf745..e21a826df 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -106,6 +106,7 @@ void run_variable(xilinx_srl_pm &pm) log("Found variable chain of length %d (%s):\n", GetSize(ud.chain), log_id(st.first->type)); auto last_cell = ud.chain.back().first; + auto last_slice = ud.chain.back().second; SigSpec initval; for (const auto &i : ud.chain) { @@ -130,7 +131,7 @@ void run_variable(xilinx_srl_pm &pm) pm.autoremove(st.shiftx); Cell *c = last_cell; - SigBit Q = st.first->getPort(ID(Q)); + SigBit Q = st.first->getPort(ID(Q))[last_slice]; c->setPort(ID(Q), Q); if (c->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID($dff), ID($dffe))) { From a1f78eab0466ca328b39750b7746deb336c5c973 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 13:15:41 -0700 Subject: [PATCH 061/130] indo -> into --- passes/pmgen/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/README.md b/passes/pmgen/README.md index 27ed77091..0856c9ba3 100644 --- a/passes/pmgen/README.md +++ b/passes/pmgen/README.md @@ -195,7 +195,7 @@ create matches for different sections of a cell. For example: The first argument to `slice` is the local variable name used to identify the slice. The second argument is the number of slices that should be created for -this cell. The `set` statement can be used to copy that index indo a state +this cell. The `set` statement can be used to copy that index into a state variable so that later matches and/or code blocks can refer to it. A similar mechanism is "choices", where a list of options is given as From 3d7f4aa0c8841739eb30fa667181475ce22b4187 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 13:56:01 -0700 Subject: [PATCH 062/130] Remove (* init *) entry when consumed into SRL --- passes/pmgen/xilinx_srl.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index e21a826df..d446bf47a 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -52,7 +52,9 @@ void run_fixed(xilinx_srl_pm &pm) log_assert(Q.wire); auto it = Q.wire->attributes.find(ID(init)); if (it != Q.wire->attributes.end()) { - initval.append(it->second[Q.offset]); + auto &i = it->second[Q.offset]; + initval.append(i); + i = State::Sx; } else initval.append(State::Sx); @@ -118,7 +120,9 @@ void run_variable(xilinx_srl_pm &pm) log_assert(Q.wire); auto it = Q.wire->attributes.find(ID(init)); if (it != Q.wire->attributes.end()) { - initval.append(it->second[Q.offset]); + auto &i = it->second[Q.offset]; + initval.append(i); + i = State::Sx; } else initval.append(State::Sx); From 8ecfd55d5a02854abf2f59f4bc19ce94479b82fb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 14:16:41 -0700 Subject: [PATCH 063/130] Update doc --- passes/pmgen/xilinx_srl.cc | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index d446bf47a..ef3e61661 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -42,7 +42,7 @@ void run_fixed(xilinx_srl_pm &pm) log("Found fixed chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type)); - auto last_cell = ud.longest_chain.back(); + auto first_cell = ud.longest_chain.back(); SigSpec initval; for (auto cell : ud.longest_chain) { @@ -63,11 +63,11 @@ void run_fixed(xilinx_srl_pm &pm) initval.append(param_def(cell, ID(INIT))); else log_abort(); - if (cell != last_cell) + if (cell != first_cell) pm.autoremove(cell); } - Cell *c = last_cell; + Cell *c = first_cell; SigBit Q = st.first->getPort(ID(Q)); c->setPort(ID(Q), Q); @@ -107,8 +107,8 @@ void run_variable(xilinx_srl_pm &pm) log("Found variable chain of length %d (%s):\n", GetSize(ud.chain), log_id(st.first->type)); - auto last_cell = ud.chain.back().first; - auto last_slice = ud.chain.back().second; + auto first_cell = ud.chain.back().first; + auto first_slice = ud.chain.back().second; SigSpec initval; for (const auto &i : ud.chain) { @@ -129,14 +129,21 @@ void run_variable(xilinx_srl_pm &pm) } else log_abort(); - if (cell != last_cell) + if (cell != first_cell) cell->connections_.at(ID(Q))[slice] = pm.module->addWire(NEW_ID); } pm.autoremove(st.shiftx); + auto last_cell = ud.chain.front().first; + auto last_slice = ud.chain.front().second; + Cell *c = last_cell; - SigBit Q = st.first->getPort(ID(Q))[last_slice]; - c->setPort(ID(Q), Q); + if (c->type.in(ID($dff), ID($dffe))) { + auto &Q = last_cell->connections_.at(ID(Q)); + Q = Q[last_slice]; + auto &D = first_cell->connections_.at(ID(D)); + D = D[first_slice]; + } if (c->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID($dff), ID($dffe))) { Const clkpol, enpol; @@ -177,7 +184,6 @@ void run_variable(xilinx_srl_pm &pm) log_abort(); log(" -> %s (%s)\n", log_id(c), log_id(c->type)); - } struct XilinxSrlPass : public Pass { @@ -188,9 +194,10 @@ struct XilinxSrlPass : public Pass { log("\n"); log(" xilinx_srl [options] [selection]\n"); log("\n"); - log("This pass converts chains of built-in flops ($_DFF_[NP]_, $_DFFE_*) as well as\n"); - log("Xilinx flops (FDRE, FDRE_1) into a $__XILINX_SHREG cell. Chains must be of the\n"); - log("same type, clock, clock polarity, enable, enable polarity (when relevant).\n"); + log("This pass converts chains of built-in flops (bit-level: $_DFF_[NP]_, $_DFFE_*\n"); + log("and word-level: $dff, $dffe) as well as Xilinx flops (FDRE, FDRE_1) into a\n"); + log("$__XILINX_SHREG cell. Chains must be of the same cell type, clock, clock polarity,\n"); + log("enable, and enable polarity (where relevant).\n"); log("Flops with resets cannot be mapped to Xilinx devices and will not be inferred."); log("\n"); log(" -minlen N\n"); From 1d88887cfdbeedff7dce9024d8fb4ceb014cb2ef Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 14:32:17 -0700 Subject: [PATCH 064/130] Add a unique argument to pmgen's nusers() --- passes/pmgen/pmgen.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py index 573722d68..2f2545c22 100644 --- a/passes/pmgen/pmgen.py +++ b/passes/pmgen/pmgen.py @@ -458,12 +458,16 @@ with open(outfile, "w") as f: print(" }", file=f) print("", file=f) - print(" int nusers(const SigSpec &sig) {", file=f) + print(" int nusers(const SigSpec &sig, bool unique=true) {", file=f) + print(" int i = 0;", file=f) print(" pool users;", file=f) print(" for (auto bit : sigmap(sig))", file=f) - print(" for (auto user : sigusers[bit])", file=f) - print(" users.insert(user);", file=f) - print(" return GetSize(users);", file=f) + print(" if (unique)", file=f); + print(" i += GetSize(sigusers[bit]);", file=f); + print(" else", file=f); + print(" for (auto user : sigusers[bit])", file=f) + print(" users.insert(user);", file=f) + print(" return unique ? GetSize(users) : i;", file=f) print(" }", file=f) print("", file=f) From c2757613b643f11e1b735b8bc4506750bb0f9522 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 14:32:36 -0700 Subject: [PATCH 065/130] Check for non unique nusers/fanouts --- passes/pmgen/xilinx_srl.pmg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 5d74b91bc..99fefba00 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -170,7 +170,7 @@ match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, $dff, $dffe) select !first->has_keep_attr() slice idx GetSize(port(first, \Q)) - select nusers(port(first, \Q)[idx]) == 2 + select nusers(port(first, \Q)[idx], false /* unique */) == 2 index port(first, \Q)[idx] === port(shiftx, \A)[shiftx_width-1] set slice idx endmatch @@ -197,7 +197,7 @@ match next select !next->has_keep_attr() select !port(next, \D)[0].wire->get_bool_attribute(\keep) slice idx GetSize(port(next, \Q)) - select nusers(port(next, \Q)[idx]) <= 3 + select nusers(port(next, \Q)[idx], false /* unique */) == 3 index next->type === chain.back().first->type index port(next, \Q)[idx] === port(chain.back().first, \D)[chain.back().second] index port(next, \Q)[idx] === port(shiftx, \A)[shiftx_width-1-GetSize(chain)] From 9cd23cf0feda3e12ceda1f8fa5d28d2b38f2314d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 14:49:34 -0700 Subject: [PATCH 066/130] Fix polarity --- passes/pmgen/pmgen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py index 2f2545c22..c21fe8f87 100644 --- a/passes/pmgen/pmgen.py +++ b/passes/pmgen/pmgen.py @@ -462,7 +462,7 @@ with open(outfile, "w") as f: print(" int i = 0;", file=f) print(" pool users;", file=f) print(" for (auto bit : sigmap(sig))", file=f) - print(" if (unique)", file=f); + print(" if (!unique)", file=f); print(" i += GetSize(sigusers[bit]);", file=f); print(" else", file=f); print(" for (auto user : sigusers[bit])", file=f) From e85e6e8d452e8f2605214cc40a5b4fc4b0e2cdc2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 15:03:42 -0700 Subject: [PATCH 067/130] Revert "Fix polarity" This reverts commit 9cd23cf0feda3e12ceda1f8fa5d28d2b38f2314d. --- passes/pmgen/pmgen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py index c21fe8f87..2f2545c22 100644 --- a/passes/pmgen/pmgen.py +++ b/passes/pmgen/pmgen.py @@ -462,7 +462,7 @@ with open(outfile, "w") as f: print(" int i = 0;", file=f) print(" pool users;", file=f) print(" for (auto bit : sigmap(sig))", file=f) - print(" if (!unique)", file=f); + print(" if (unique)", file=f); print(" i += GetSize(sigusers[bit]);", file=f); print(" else", file=f); print(" for (auto user : sigusers[bit])", file=f) From ca5de78e762172a6c602470560354eff1de73cf7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 15:04:00 -0700 Subject: [PATCH 068/130] Revert "Add a unique argument to pmgen's nusers()" This reverts commit 1d88887cfdbeedff7dce9024d8fb4ceb014cb2ef. --- passes/pmgen/pmgen.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py index 2f2545c22..573722d68 100644 --- a/passes/pmgen/pmgen.py +++ b/passes/pmgen/pmgen.py @@ -458,16 +458,12 @@ with open(outfile, "w") as f: print(" }", file=f) print("", file=f) - print(" int nusers(const SigSpec &sig, bool unique=true) {", file=f) - print(" int i = 0;", file=f) + print(" int nusers(const SigSpec &sig) {", file=f) print(" pool users;", file=f) print(" for (auto bit : sigmap(sig))", file=f) - print(" if (unique)", file=f); - print(" i += GetSize(sigusers[bit]);", file=f); - print(" else", file=f); - print(" for (auto user : sigusers[bit])", file=f) - print(" users.insert(user);", file=f) - print(" return unique ? GetSize(users) : i;", file=f) + print(" for (auto user : sigusers[bit])", file=f) + print(" users.insert(user);", file=f) + print(" return GetSize(users);", file=f) print(" }", file=f) print("", file=f) From c76261878340bc87fc5ab2f5ac8c7a1fb5a1b3a2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 15:08:49 -0700 Subject: [PATCH 069/130] Fix last_cell.D --- passes/pmgen/xilinx_srl.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index ef3e61661..c0c827a25 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -141,8 +141,7 @@ void run_variable(xilinx_srl_pm &pm) if (c->type.in(ID($dff), ID($dffe))) { auto &Q = last_cell->connections_.at(ID(Q)); Q = Q[last_slice]; - auto &D = first_cell->connections_.at(ID(D)); - D = D[first_slice]; + last_cell->setPort(ID(D), first_cell->getPort(ID(D))[first_slice]); } if (c->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID($dff), ID($dffe))) { From 513af10d77b865fa0a1a6d9a320298ed08a8b4ac Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 15:18:26 -0700 Subject: [PATCH 070/130] Check clock is consistent --- passes/pmgen/xilinx_srl.pmg | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 99fefba00..df78cc18e 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -1,5 +1,6 @@ pattern fixed +state clk_port udata > chain longest_chain udata > non_first_cells udata minlen @@ -32,7 +33,10 @@ match first // } endmatch -code +code clk_port + if (first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1)) + clk_port = \C; + else log_abort(); longest_chain.clear(); chain.push_back(first); subpattern(tail); @@ -46,13 +50,17 @@ endcode // ------------------------------------------------------------------ subpattern setup +arg clk_port match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !first->has_keep_attr() endmatch -code +code clk_port + if (first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1)) + clk_port = \C; + else log_abort(); if (first->type.in(\FDRE, \FDRE_1)) { SigBit R = port(first, \R); if (first->type == \FDRE) { @@ -77,6 +85,7 @@ match next select nusers(port(next, \Q)) == 2 index next->type === first->type index port(next, \Q) === port(first, \D) + filter port(next, clk_port) == port(first, clk_port) endmatch code @@ -101,6 +110,7 @@ endcode subpattern tail arg first +arg clk_port match next semioptional @@ -110,6 +120,7 @@ match next select nusers(port(next, \Q)) == 2 index next->type === chain.back()->type index port(next, \Q) === port(chain.back(), \D) + filter port(next, clk_port) == port(first, clk_port) //generate 10 // SigSpec A = module->addWire(NEW_ID); // SigSpec B = module->addWire(NEW_ID); @@ -150,6 +161,7 @@ endcode pattern variable +state clk_port state shiftx_width state slice udata minlen @@ -170,12 +182,17 @@ match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, $dff, $dffe) select !first->has_keep_attr() slice idx GetSize(port(first, \Q)) - select nusers(port(first, \Q)[idx], false /* unique */) == 2 + select nusers(port(first, \Q)[idx]) <= 2 index port(first, \Q)[idx] === port(shiftx, \A)[shiftx_width-1] set slice idx endmatch -code +code clk_port + if (first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_)) + clk_port = \C; + else if (first->type.in($dff, $dffe)) + clk_port = \CLK; + else log_abort(); chain.emplace_back(first, slice); subpattern(tail); finally @@ -187,9 +204,11 @@ endcode // ------------------------------------------------------------------ subpattern tail +arg first arg shiftx arg shiftx_width arg slice +arg clk_port match next semioptional @@ -197,10 +216,11 @@ match next select !next->has_keep_attr() select !port(next, \D)[0].wire->get_bool_attribute(\keep) slice idx GetSize(port(next, \Q)) - select nusers(port(next, \Q)[idx], false /* unique */) == 3 + select nusers(port(next, \Q)[idx]) <= 3 index next->type === chain.back().first->type index port(next, \Q)[idx] === port(chain.back().first, \D)[chain.back().second] index port(next, \Q)[idx] === port(shiftx, \A)[shiftx_width-1-GetSize(chain)] + filter port(next, clk_port) == port(first, clk_port) set slice idx endmatch From b1caf7be5eef134f7bd84c5336560dd3dff1e29b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 16:09:46 -0700 Subject: [PATCH 071/130] Filter on en_port for fixed length --- passes/pmgen/xilinx_srl.pmg | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index df78cc18e..cefd1ea71 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -1,6 +1,6 @@ pattern fixed -state clk_port +state clk_port en_port udata > chain longest_chain udata > non_first_cells udata minlen @@ -33,10 +33,18 @@ match first // } endmatch -code clk_port +code clk_port en_port if (first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1)) clk_port = \C; else log_abort(); + if (first->type.in($_DFF_N_, $_DFF_P_)) + en_port = IdString(); + else if (first->type.in($_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_)) + en_port = \E; + else if (first->type.in(\FDRE, \FDRE_1)) + en_port = \CE; + else log_abort(); + longest_chain.clear(); chain.push_back(first); subpattern(tail); @@ -51,16 +59,24 @@ endcode subpattern setup arg clk_port +arg en_port match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !first->has_keep_attr() endmatch -code clk_port +code clk_port en_port if (first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1)) clk_port = \C; else log_abort(); + if (first->type.in($_DFF_N_, $_DFF_P_)) + en_port = IdString(); + else if (first->type.in($_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_)) + en_port = \E; + else if (first->type.in(\FDRE, \FDRE_1)) + en_port = \CE; + else log_abort(); if (first->type.in(\FDRE, \FDRE_1)) { SigBit R = port(first, \R); if (first->type == \FDRE) { @@ -86,6 +102,7 @@ match next index next->type === first->type index port(next, \Q) === port(first, \D) filter port(next, clk_port) == port(first, clk_port) + filter en_port == IdString() || port(next, en_port) == port(first, en_port) endmatch code @@ -111,6 +128,7 @@ endcode subpattern tail arg first arg clk_port +arg en_port match next semioptional @@ -121,6 +139,7 @@ match next index next->type === chain.back()->type index port(next, \Q) === port(chain.back(), \D) filter port(next, clk_port) == port(first, clk_port) + filter en_port == IdString() || port(next, en_port) == port(first, en_port) //generate 10 // SigSpec A = module->addWire(NEW_ID); // SigSpec B = module->addWire(NEW_ID); @@ -131,6 +150,8 @@ endmatch code if (next) { + chain.push_back(next); + if (next->type.in(\FDRE, \FDRE_1)) { for (auto p : { \R }) if (port(next, p) != port(first, p)) @@ -146,7 +167,6 @@ code } } - chain.push_back(next); subpattern(tail); } else { if (GetSize(chain) > GetSize(longest_chain)) From 2217d926a9d353d732ba7dd81a3782f964463f5d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 16:13:16 -0700 Subject: [PATCH 072/130] Same for variable length --- passes/pmgen/xilinx_srl.pmg | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index cefd1ea71..531ea1828 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -181,7 +181,7 @@ endcode pattern variable -state clk_port +state clk_port en_port state shiftx_width state slice udata minlen @@ -207,12 +207,18 @@ match first set slice idx endmatch -code clk_port +code clk_port en_port if (first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_)) clk_port = \C; else if (first->type.in($dff, $dffe)) clk_port = \CLK; else log_abort(); + if (first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_)) + en_port = \E; + else if (first->type.in($dff, $dffe)) + en_port = \EN; + else log_abort(); + chain.emplace_back(first, slice); subpattern(tail); finally @@ -229,6 +235,7 @@ arg shiftx arg shiftx_width arg slice arg clk_port +arg en_port match next semioptional @@ -241,6 +248,7 @@ match next index port(next, \Q)[idx] === port(chain.back().first, \D)[chain.back().second] index port(next, \Q)[idx] === port(shiftx, \A)[shiftx_width-1-GetSize(chain)] filter port(next, clk_port) == port(first, clk_port) + filter en_port == IdString() || port(next, en_port) == port(first, en_port) set slice idx endmatch From f2d48142843f2ed8bc9f0e55197ba347d210a6e1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 16:14:57 -0700 Subject: [PATCH 073/130] Don't forget $dff has no EN --- passes/pmgen/xilinx_srl.pmg | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 531ea1828..fcfa79ea6 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -213,9 +213,11 @@ code clk_port en_port else if (first->type.in($dff, $dffe)) clk_port = \CLK; else log_abort(); - if (first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_)) + if (first->type.in($_DFF_N_, $_DFF_P_, $dff)) + en_port = IdString(); + else if (first->type.in($_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_)) en_port = \E; - else if (first->type.in($dff, $dffe)) + else if (first->type.in($dffe)) en_port = \EN; else log_abort(); From 83e2d87fb80cc5aed018b0f3409f256ef7f7b385 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 16:21:10 -0700 Subject: [PATCH 074/130] Keep track of bits in variable length chain, to check for taps --- passes/pmgen/xilinx_srl.pmg | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index fcfa79ea6..d17799208 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -186,6 +186,11 @@ state shiftx_width state slice udata minlen udata >> chain +udata > chain_bits + +code + chain_bits.clear(); +endcode match shiftx select shiftx->type.in($shiftx) @@ -251,13 +256,20 @@ match next index port(next, \Q)[idx] === port(shiftx, \A)[shiftx_width-1-GetSize(chain)] filter port(next, clk_port) == port(first, clk_port) filter en_port == IdString() || port(next, en_port) == port(first, en_port) + filter !chain_bits.count(port(next, \D)[idx]) set slice idx endmatch code if (next) { + chain_bits.insert(port(next, \Q)[slice]); chain.emplace_back(next, slice); if (GetSize(chain) < shiftx_width) subpattern(tail); } +finally + if (next) { + chain_bits.erase(port(next, \Q)[slice]); + chain.pop_back(); + } endcode From 54488cfb82907429f7637201e925e84977f7f5ba Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 16:39:37 -0700 Subject: [PATCH 075/130] Oops don't need a finally block --- passes/pmgen/xilinx_srl.pmg | 5 ----- 1 file changed, 5 deletions(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index d17799208..622655ce8 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -267,9 +267,4 @@ code if (GetSize(chain) < shiftx_width) subpattern(tail); } -finally - if (next) { - chain_bits.erase(port(next, \Q)[slice]); - chain.pop_back(); - } endcode From e081303ee895f2f65465e930d0df8c92fc26c058 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 17:23:52 -0700 Subject: [PATCH 076/130] Cleanup FDRE matching --- passes/pmgen/xilinx_srl.pmg | 64 +++++++++++-------------------------- 1 file changed, 19 insertions(+), 45 deletions(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 622655ce8..9f9308c2a 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -14,6 +14,9 @@ endcode match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !first->has_keep_attr() + select !first->type.in(\FDRE) || !first->hasParam(\IS_R_INVERTED) || !param(first, \IS_R_INVERTED).as_bool() + select !first->type.in(\FDRE) || !first->hasParam(\IS_D_INVERTED) || !param(first, \IS_D_INVERTED).as_bool() + select !first->type.in(\FDRE, \FDRE_1) || port(first, \R) == State::S0 filter !non_first_cells.count(first) //generate // SigSpec A = module->addWire(NEW_ID); @@ -64,6 +67,9 @@ arg en_port match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !first->has_keep_attr() + select !first->type.in(\FDRE) || !first->hasParam(\IS_R_INVERTED) || !param(first, \IS_R_INVERTED).as_bool() + select !first->type.in(\FDRE) || !first->hasParam(\IS_D_INVERTED) || !param(first, \IS_D_INVERTED).as_bool() + select !first->type.in(\FDRE, \FDRE_1) || port(first, \R) == State::S0 endmatch code clk_port en_port @@ -77,21 +83,6 @@ code clk_port en_port else if (first->type.in(\FDRE, \FDRE_1)) en_port = \CE; else log_abort(); - if (first->type.in(\FDRE, \FDRE_1)) { - SigBit R = port(first, \R); - if (first->type == \FDRE) { - auto inverted = first->parameters.at(\IS_R_INVERTED, default_params.at(std::make_pair(first->type,\IS_R_INVERTED))).as_bool(); - if (!inverted && R != State::S0) - reject; - if (inverted && R != State::S1) - reject; - } - else if (first->type == \FDRE_1) { - if (R == State::S0) - reject; - } - else log_abort(); - } endcode match next @@ -99,27 +90,18 @@ match next select !next->has_keep_attr() select !port(next, \D)[0].wire->get_bool_attribute(\keep) select nusers(port(next, \Q)) == 2 + select !next->type.in(\FDRE, \FDRE_1) || port(next, \R) == State::S0 index next->type === first->type index port(next, \Q) === port(first, \D) filter port(next, clk_port) == port(first, clk_port) filter en_port == IdString() || port(next, en_port) == port(first, en_port) + filter !next->type.in(\FDRE) || !first->hasParam(\IS_C_INVERTED) || (next->hasParam(\IS_C_INVERTED) && param(next, \IS_C_INVERTED).as_bool() == param(first, \IS_C_INVERTED).as_bool()) + filter !next->type.in(\FDRE) || !first->hasParam(\IS_D_INVERTED) || (next->hasParam(\IS_D_INVERTED) && param(next, \IS_D_INVERTED).as_bool() == param(first, \IS_D_INVERTED).as_bool()) + filter !next->type.in(\FDRE) || !first->hasParam(\IS_R_INVERTED) || (next->hasParam(\IS_R_INVERTED) && param(next, \IS_R_INVERTED).as_bool() == param(first, \IS_R_INVERTED).as_bool()) + filter !next->type.in(\FDRE, \FDRE_1) || port(next, \R) == port(first, \R) endmatch code - if (next->type.in(\FDRE, \FDRE_1)) { - for (auto p : { \R }) - if (port(next, p) != port(first, p)) - reject; - - if (next->type == \FDRE) { - for (auto p : { \IS_C_INVERTED, \IS_D_INVERTED, \IS_R_INVERTED }) { - auto n = next->parameters.at(p, default_params.at(std::make_pair(next->type,p))); - auto f = first->parameters.at(p, default_params.at(std::make_pair(first->type,p))); - if (n != f) - reject; - } - } - } non_first_cells.insert(next); endcode @@ -140,6 +122,10 @@ match next index port(next, \Q) === port(chain.back(), \D) filter port(next, clk_port) == port(first, clk_port) filter en_port == IdString() || port(next, en_port) == port(first, en_port) + filter !next->type.in(\FDRE) || !first->hasParam(\IS_C_INVERTED) || (next->hasParam(\IS_C_INVERTED) && param(next, \IS_C_INVERTED).as_bool() == param(first, \IS_C_INVERTED).as_bool()) + filter !next->type.in(\FDRE) || !first->hasParam(\IS_D_INVERTED) || (next->hasParam(\IS_D_INVERTED) && param(next, \IS_D_INVERTED).as_bool() == param(first, \IS_D_INVERTED).as_bool()) + filter !next->type.in(\FDRE) || !first->hasParam(\IS_R_INVERTED) || (next->hasParam(\IS_R_INVERTED) && param(next, \IS_R_INVERTED).as_bool() == param(first, \IS_R_INVERTED).as_bool()) + filter !next->type.in(\FDRE, \FDRE_1) || port(next, \R) == port(first, \R) //generate 10 // SigSpec A = module->addWire(NEW_ID); // SigSpec B = module->addWire(NEW_ID); @@ -151,22 +137,6 @@ endmatch code if (next) { chain.push_back(next); - - if (next->type.in(\FDRE, \FDRE_1)) { - for (auto p : { \R }) - if (port(next, p) != port(first, p)) - reject; - - if (next->type == \FDRE) { - for (auto p : { \IS_C_INVERTED, \IS_D_INVERTED, \IS_R_INVERTED }) { - auto n = next->parameters.at(p, default_params.at(std::make_pair(next->type,p))); - auto f = first->parameters.at(p, default_params.at(std::make_pair(first->type,p))); - if (n != f) - reject; - } - } - } - subpattern(tail); } else { if (GetSize(chain) > GetSize(longest_chain)) @@ -206,6 +176,7 @@ endcode match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, $dff, $dffe) select !first->has_keep_attr() + select !first->type.in($dffe) || !param(first, \EN_POLARITY).as_bool() slice idx GetSize(port(first, \Q)) select nusers(port(first, \Q)[idx]) <= 2 index port(first, \Q)[idx] === port(shiftx, \A)[shiftx_width-1] @@ -249,6 +220,7 @@ match next select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, $dff, $dffe) select !next->has_keep_attr() select !port(next, \D)[0].wire->get_bool_attribute(\keep) + select !next->type.in($dffe) || !param(next, \EN_POLARITY).as_bool() slice idx GetSize(port(next, \Q)) select nusers(port(next, \Q)[idx]) <= 3 index next->type === chain.back().first->type @@ -256,6 +228,8 @@ match next index port(next, \Q)[idx] === port(shiftx, \A)[shiftx_width-1-GetSize(chain)] filter port(next, clk_port) == port(first, clk_port) filter en_port == IdString() || port(next, en_port) == port(first, en_port) + filter !next->type.in($dff, $dffe) || param(next, \CLK_POLARITY).as_bool() == param(first, \CLK_POLARITY).as_bool() + filter !next->type.in($dffe) || param(next, \EN_POLARITY).as_bool() == param(first, \EN_POLARITY).as_bool() filter !chain_bits.count(port(next, \D)[idx]) set slice idx endmatch From 188b49378a47c7bfc311b4e439ac74635ba85a77 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 17:25:30 -0700 Subject: [PATCH 077/130] Create new cell for fixed length SRL --- passes/pmgen/xilinx_srl.cc | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index c0c827a25..e1d38d7bd 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -67,32 +67,40 @@ void run_fixed(xilinx_srl_pm &pm) pm.autoremove(cell); } - Cell *c = first_cell; - SigBit Q = st.first->getPort(ID(Q)); - c->setPort(ID(Q), Q); + auto last_cell = ud.longest_chain.front(); + Cell *c = pm.module->addCell(NEW_ID, ID($__XILINX_SHREG_)); + pm.module->swap_names(c, first_cell); - if (c->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID(FDRE), ID(FDRE_1))) { - c->parameters.clear(); + if (first_cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID(FDRE), ID(FDRE_1))) { c->setParam(ID(DEPTH), GetSize(ud.longest_chain)); c->setParam(ID(INIT), initval.as_const()); - if (c->type.in(ID($_DFF_P_), ID($_DFFE_PN_), ID($_DFFE_PP_))) + if (first_cell->type.in(ID($_DFF_P_), ID($_DFFE_PN_), ID($_DFFE_PP_))) c->setParam(ID(CLKPOL), 1); - else if (c->type.in(ID($_DFF_N_), ID($DFFE_NN_), ID($_DFFE_NP_), ID(FDRE_1))) + else if (first_cell->type.in(ID($_DFF_N_), ID($DFFE_NN_), ID($_DFFE_NP_), ID(FDRE_1))) c->setParam(ID(CLKPOL), 0); - else if (c->type.in(ID(FDRE))) - c->setParam(ID(CLKPOL), param_def(c, ID(IS_C_INVERTED)).as_bool() ? 0 : 1); + else if (first_cell->type.in(ID(FDRE))) + c->setParam(ID(CLKPOL), param_def(first_cell, ID(IS_C_INVERTED)).as_bool() ? 0 : 1); else log_abort(); - if (c->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_))) + if (first_cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_))) c->setParam(ID(ENPOL), 1); - else if (c->type.in(ID($_DFFE_NN_), ID($_DFFE_PN_))) + else if (first_cell->type.in(ID($_DFFE_NN_), ID($_DFFE_PN_))) c->setParam(ID(ENPOL), 0); else c->setParam(ID(ENPOL), 2); - if (c->type.in(ID($_DFF_N_), ID($_DFF_P_))) - c->setPort(ID(E), State::S1); + + c->setPort(ID(C), first_cell->getPort(ID(C))); + c->setPort(ID(D), first_cell->getPort(ID(D))); + c->setPort(ID(Q), last_cell->getPort(ID(Q))); c->setPort(ID(L), GetSize(ud.longest_chain)-1); - c->type = ID($__XILINX_SHREG_); + if (first_cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) + c->setPort(ID(E), State::S1); + else if (first_cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) + c->setPort(ID(E), first_cell->getPort(ID(E))); + else if (first_cell->type.in(ID(FDRE), ID(FDRE_1))) + c->setPort(ID(E), first_cell->getPort(ID(CE))); + else + log_abort(); } else log_abort(); From 70ce3d067010d67154c3cd5437caa16b4c8ca195 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 18:11:28 -0700 Subject: [PATCH 078/130] Do not enforce !EN_POLARITY on $dffe --- passes/pmgen/xilinx_srl.pmg | 2 -- 1 file changed, 2 deletions(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 9f9308c2a..d41bd3be9 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -176,7 +176,6 @@ endcode match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, $dff, $dffe) select !first->has_keep_attr() - select !first->type.in($dffe) || !param(first, \EN_POLARITY).as_bool() slice idx GetSize(port(first, \Q)) select nusers(port(first, \Q)[idx]) <= 2 index port(first, \Q)[idx] === port(shiftx, \A)[shiftx_width-1] @@ -220,7 +219,6 @@ match next select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, $dff, $dffe) select !next->has_keep_attr() select !port(next, \D)[0].wire->get_bool_attribute(\keep) - select !next->type.in($dffe) || !param(next, \EN_POLARITY).as_bool() slice idx GetSize(port(next, \Q)) select nusers(port(next, \Q)[idx]) <= 3 index next->type === chain.back().first->type From ee9f6e6243cbea9efbd0f1b0a236e33ac6a0450e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 18:14:06 -0700 Subject: [PATCH 079/130] Also add first.Q to chain_bits since variable length --- passes/pmgen/xilinx_srl.pmg | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index d41bd3be9..76134de1a 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -196,6 +196,7 @@ code clk_port en_port en_port = \EN; else log_abort(); + chain_bits.insert(port(first, \Q)[slice]); chain.emplace_back(first, slice); subpattern(tail); finally From a048fc93e8cf187b28bd5ed924643671b9314678 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 18:15:24 -0700 Subject: [PATCH 080/130] Do not allow Q of last cell of variable length SRL to be (* keep *) --- passes/pmgen/xilinx_srl.pmg | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 76134de1a..cfa1cacfb 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -176,6 +176,7 @@ endcode match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, $dff, $dffe) select !first->has_keep_attr() + select !port(first, \Q)[0].wire->get_bool_attribute(\keep) slice idx GetSize(port(first, \Q)) select nusers(port(first, \Q)[idx]) <= 2 index port(first, \Q)[idx] === port(shiftx, \A)[shiftx_width-1] From 791114382774cdf70b16cc5f1cec689f0ddb5c0b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 23 Aug 2019 18:15:49 -0700 Subject: [PATCH 081/130] Create new $__XILINX_SHREG_ cell for variable length too --- passes/pmgen/xilinx_srl.cc | 75 +++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index e1d38d7bd..c332ccb9f 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -142,50 +142,49 @@ void run_variable(xilinx_srl_pm &pm) } pm.autoremove(st.shiftx); - auto last_cell = ud.chain.front().first; - auto last_slice = ud.chain.front().second; + Cell *c = pm.module->addCell(NEW_ID, ID($__XILINX_SHREG_)); + pm.module->swap_names(c, first_cell); - Cell *c = last_cell; - if (c->type.in(ID($dff), ID($dffe))) { - auto &Q = last_cell->connections_.at(ID(Q)); - Q = Q[last_slice]; - last_cell->setPort(ID(D), first_cell->getPort(ID(D))[first_slice]); - } - - if (c->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID($dff), ID($dffe))) { - Const clkpol, enpol; - if (c->type.in(ID($_DFF_P_), ID($_DFFE_PN_), ID($_DFFE_PP_))) - clkpol = 1; - else if (c->type.in(ID($_DFF_N_), ID($DFFE_NN_), ID($_DFFE_NP_))) - clkpol = 0; - else if (c->type.in(ID($dff), ID($dffe))) { - clkpol = c->getParam(ID(CLK_POLARITY)); - c->setPort(ID(C), c->getPort(ID(CLK))); - c->unsetPort(ID(CLK)); - } - else - log_abort(); - if (c->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_))) - enpol = 1; - else if (c->type.in(ID($_DFFE_NN_), ID($_DFFE_PN_))) - enpol = 0; - else if (c->type.in(ID($dffe))) { - enpol = c->getParam(ID(EN_POLARITY)); - c->setPort(ID(E), c->getPort(ID(EN))); - c->unsetPort(ID(EN)); - } - else - enpol = 2; - c->parameters.clear(); + if (first_cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID($dff), ID($dffe))) { c->setParam(ID(DEPTH), GetSize(ud.chain)); c->setParam(ID(INIT), initval.as_const()); + Const clkpol, enpol; + if (first_cell->type.in(ID($_DFF_P_), ID($_DFFE_PN_), ID($_DFFE_PP_))) + clkpol = 1; + else if (first_cell->type.in(ID($_DFF_N_), ID($DFFE_NN_), ID($_DFFE_NP_))) + clkpol = 0; + else if (first_cell->type.in(ID($dff), ID($dffe))) + clkpol = first_cell->getParam(ID(CLK_POLARITY)); + else + log_abort(); + if (first_cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_))) + enpol = 1; + else if (first_cell->type.in(ID($_DFFE_NN_), ID($_DFFE_PN_))) + enpol = 0; + else if (first_cell->type.in(ID($dffe))) + enpol = first_cell->getParam(ID(EN_POLARITY)); + else + enpol = 2; c->setParam(ID(CLKPOL), clkpol); c->setParam(ID(ENPOL), enpol); - if (c->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($dff))) - c->setPort(ID(E), State::S1); - c->setPort(ID(L), st.shiftx->getPort(ID(B))); + + if (first_cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) + c->setPort(ID(C), first_cell->getPort(ID(C))); + else if (first_cell->type.in(ID($dff), ID($dffe))) + c->setPort(ID(C), first_cell->getPort(ID(CLK))); + else + log_abort(); + c->setPort(ID(D), first_cell->getPort(ID(D))[first_slice]); c->setPort(ID(Q), st.shiftx->getPort(ID(Y))); - c->type = ID($__XILINX_SHREG_); + c->setPort(ID(L), st.shiftx->getPort(ID(B))); + if (first_cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($dff))) + c->setPort(ID(E), State::S1); + else if (first_cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) + c->setPort(ID(E), first_cell->getPort(ID(E))); + else if (first_cell->type.in(ID($dffe))) + c->setPort(ID(E), first_cell->getPort(ID(EN))); + else + log_abort(); } else log_abort(); From cf9e0171273daa1bc36174aa83bd02f9cfdb5e7a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 26 Aug 2019 14:20:06 -0700 Subject: [PATCH 082/130] Add xilinx_srl_fixed, fix typos --- passes/pmgen/test_pmgen.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/test_pmgen.cc b/passes/pmgen/test_pmgen.cc index 0ad769dfd..b406f90f8 100644 --- a/passes/pmgen/test_pmgen.cc +++ b/passes/pmgen/test_pmgen.cc @@ -28,6 +28,7 @@ bool did_something; #include "passes/pmgen/test_pmgen_pm.h" #include "passes/pmgen/ice40_dsp_pm.h" +#include "passes/pmgen/xilinx_srl_pm.h" #include "passes/pmgen/peepopt_pm.h" void reduce_chain(test_pmgen_pm &pm) @@ -180,7 +181,7 @@ void generate_pattern(std::function)> run, const while (modcnt < maxmodcnt && submodcnt < maxsubcnt && itercnt++ < 1000) { if (timeout++ > 10000) - log_error("pmgen generator is stuck: 10000 iterations an no matching module generated.\n"); + log_error("pmgen generator is stuck: 10000 iterations with no matching module generated.\n"); pm matcher(mod, mod->cells()); @@ -349,13 +350,16 @@ struct TestPmgenPass : public Pass { if (pattern == "ice40_dsp") return GENERATE_PATTERN(ice40_dsp_pm, ice40_dsp); + if (pattern == "xilinx_srl_fixed") + return GENERATE_PATTERN(xilinx_srl_pm, fixed); + if (pattern == "peepopt-muldiv") return GENERATE_PATTERN(peepopt_pm, muldiv); if (pattern == "peepopt-shiftmul") return GENERATE_PATTERN(peepopt_pm, shiftmul); - log_cmd_error("Unkown pattern: %s\n", pattern.c_str()); + log_cmd_error("Unknown pattern: %s\n", pattern.c_str()); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE From e574edc3e920c687856a0d69e358ba0c8ab678ff Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 26 Aug 2019 14:21:17 -0700 Subject: [PATCH 083/130] Populate generate for xilinx_srl.fixed pattern --- passes/pmgen/xilinx_srl.pmg | 76 ++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index cfa1cacfb..355f0aa90 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -18,22 +18,46 @@ match first select !first->type.in(\FDRE) || !first->hasParam(\IS_D_INVERTED) || !param(first, \IS_D_INVERTED).as_bool() select !first->type.in(\FDRE, \FDRE_1) || port(first, \R) == State::S0 filter !non_first_cells.count(first) -//generate -// SigSpec A = module->addWire(NEW_ID); -// SigSpec B = module->addWire(NEW_ID); -// SigSpec Y = module->addWire(NEW_ID); -// switch (rng(3)) -// { -// case 0: -// module->addAndGate(NEW_ID, A, B, Y); -// break; -// case 1: -// module->addOrGate(NEW_ID, A, B, Y); -// break; -// case 2: -// module->addXorGate(NEW_ID, A, B, Y); -// break; -// } +generate + SigSpec C = module->addWire(NEW_ID); + SigSpec D = module->addWire(NEW_ID); + SigSpec Q = module->addWire(NEW_ID); + auto r = rng(8); + Cell* cell; + switch (r) + { + case 0: + case 1: + case 2: + case 3: + cell = module->addCell(NEW_ID, \FDRE); + if (r & 1) + cell->setPort(\R, State::S1); + else + cell->setPort(\R, State::S0); + if (r & 2) + cell->setPort(\CE, State::S1); + else + cell->setPort(\CE, State::S0); + break; + case 4: + cell = module->addCell(NEW_ID, $_DFF_N_); + break; + case 5: + case 6: + cell = module->addCell(NEW_ID, $_DFFE_PP_); + if (r & 1) + cell->setPort(\E, State::S1); + else + cell->setPort(\E, State::S0); + break; + case 7: + cell = module->addCell(NEW_ID, \foobar); + break; + } + cell->setPort(\C, C); + cell->setPort(\D, D); + cell->setPort(\Q, Q); endmatch code clk_port en_port @@ -126,12 +150,20 @@ match next filter !next->type.in(\FDRE) || !first->hasParam(\IS_D_INVERTED) || (next->hasParam(\IS_D_INVERTED) && param(next, \IS_D_INVERTED).as_bool() == param(first, \IS_D_INVERTED).as_bool()) filter !next->type.in(\FDRE) || !first->hasParam(\IS_R_INVERTED) || (next->hasParam(\IS_R_INVERTED) && param(next, \IS_R_INVERTED).as_bool() == param(first, \IS_R_INVERTED).as_bool()) filter !next->type.in(\FDRE, \FDRE_1) || port(next, \R) == port(first, \R) -//generate 10 -// SigSpec A = module->addWire(NEW_ID); -// SigSpec B = module->addWire(NEW_ID); -// SigSpec Y = port(chain.back().first, chain.back().second); -// Cell *c = module->addAndGate(NEW_ID, A, B, Y); -// c->type = chain.back().first->type; +generate 10 + SigSpec C = chain.back()->getPort(\C); + SigSpec D = module->addWire(NEW_ID); + SigSpec Q = chain.back()->getPort(\D); + Cell *cell = module->addCell(NEW_ID, chain.back()->type); + cell->setPort(\C, C); + cell->setPort(\D, D); + cell->setPort(\Q, Q); + if (cell->type == \FDRE) { + cell->setPort(\R, chain.back()->getPort(\R)); + cell->setPort(\CE, chain.back()->getPort(\CE)); + } + else if (cell->type == $_DFFE_PP_) + cell->setPort(\E, chain.back()->getPort(\E)); endmatch code From b32d6bf403baa15539e1ceae2c1af6b3c63b2e8e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 26 Aug 2019 17:44:57 -0700 Subject: [PATCH 084/130] Add xilinx_srl_pm.variable to test_pmgen --- passes/pmgen/test_pmgen.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/passes/pmgen/test_pmgen.cc b/passes/pmgen/test_pmgen.cc index b406f90f8..5b0cf0751 100644 --- a/passes/pmgen/test_pmgen.cc +++ b/passes/pmgen/test_pmgen.cc @@ -352,6 +352,8 @@ struct TestPmgenPass : public Pass { if (pattern == "xilinx_srl_fixed") return GENERATE_PATTERN(xilinx_srl_pm, fixed); + if (pattern == "xilinx_srl_variable") + return GENERATE_PATTERN(xilinx_srl_pm, variable); if (pattern == "peepopt-muldiv") return GENERATE_PATTERN(peepopt_pm, muldiv); From 45c34c87eeb0a530a7aae14a0d538c5b6ff53faa Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 26 Aug 2019 17:48:54 -0700 Subject: [PATCH 085/130] Account for maxsubcnt overflowing --- passes/pmgen/test_pmgen.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/test_pmgen.cc b/passes/pmgen/test_pmgen.cc index 5b0cf0751..2695fe802 100644 --- a/passes/pmgen/test_pmgen.cc +++ b/passes/pmgen/test_pmgen.cc @@ -217,7 +217,7 @@ void generate_pattern(std::function)> run, const run(matcher, [](){}); } - if (submodcnt) + if (submodcnt && maxsubcnt < (1 << 16)) maxsubcnt *= 2; design->remove(mod); From e95fb24574a033bda54740733c931868d3bc1df5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 26 Aug 2019 17:49:08 -0700 Subject: [PATCH 086/130] Improve xilinx_srl.fixed generate, add .variable generate --- passes/pmgen/xilinx_srl.pmg | 101 ++++++++++++++++++++++++++---------- 1 file changed, 75 insertions(+), 26 deletions(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 355f0aa90..e8288c54a 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -28,36 +28,28 @@ generate { case 0: case 1: - case 2: - case 3: cell = module->addCell(NEW_ID, \FDRE); + cell->setPort(\C, C); + cell->setPort(\D, D); + cell->setPort(\Q, Q); + cell->setPort(\CE, module->addWire(NEW_ID)); if (r & 1) - cell->setPort(\R, State::S1); + cell->setPort(\R, module->addWire(NEW_ID)); else cell->setPort(\R, State::S0); - if (r & 2) - cell->setPort(\CE, State::S1); - else - cell->setPort(\CE, State::S0); + break; + case 2: + case 3: + cell = module->addDffGate(NEW_ID, C, D, Q, r & 1); break; case 4: - cell = module->addCell(NEW_ID, $_DFF_N_); - break; case 5: case 6: - cell = module->addCell(NEW_ID, $_DFFE_PP_); - if (r & 1) - cell->setPort(\E, State::S1); - else - cell->setPort(\E, State::S0); - break; case 7: - cell = module->addCell(NEW_ID, \foobar); + cell = module->addDffeGate(NEW_ID, C, module->addWire(NEW_ID), D, Q, r & 1, r & 2); break; + default: log_abort(); } - cell->setPort(\C, C); - cell->setPort(\D, D); - cell->setPort(\Q, Q); endmatch code clk_port en_port @@ -151,18 +143,15 @@ match next filter !next->type.in(\FDRE) || !first->hasParam(\IS_R_INVERTED) || (next->hasParam(\IS_R_INVERTED) && param(next, \IS_R_INVERTED).as_bool() == param(first, \IS_R_INVERTED).as_bool()) filter !next->type.in(\FDRE, \FDRE_1) || port(next, \R) == port(first, \R) generate 10 - SigSpec C = chain.back()->getPort(\C); - SigSpec D = module->addWire(NEW_ID); - SigSpec Q = chain.back()->getPort(\D); Cell *cell = module->addCell(NEW_ID, chain.back()->type); - cell->setPort(\C, C); - cell->setPort(\D, D); - cell->setPort(\Q, Q); + cell->setPort(\C, chain.back()->getPort(\C)); + cell->setPort(\D, module->addWire(NEW_ID)); + cell->setPort(\Q, chain.back()->getPort(\D)); if (cell->type == \FDRE) { cell->setPort(\R, chain.back()->getPort(\R)); cell->setPort(\CE, chain.back()->getPort(\CE)); } - else if (cell->type == $_DFFE_PP_) + else if (cell->type.begins_with("$_DFFE_")) cell->setPort(\E, chain.back()->getPort(\E)); endmatch @@ -199,6 +188,9 @@ match shiftx select !shiftx->has_keep_attr() select param(shiftx, \Y_WIDTH).as_int() == 1 filter param(shiftx, \A_WIDTH).as_int() >= minlen +generate + minlen = 3; + module->addShiftx(NEW_ID, module->addWire(NEW_ID, rng(6)+minlen), module->addWire(NEW_ID, 3), module->addWire(NEW_ID)); endmatch code shiftx_width @@ -213,6 +205,33 @@ match first select nusers(port(first, \Q)[idx]) <= 2 index port(first, \Q)[idx] === port(shiftx, \A)[shiftx_width-1] set slice idx +generate + SigSpec C = module->addWire(NEW_ID); + auto WIDTH = rng(3)+1; + SigSpec D = module->addWire(NEW_ID, WIDTH); + SigSpec Q = module->addWire(NEW_ID, WIDTH); + auto r = rng(8); + Cell *cell = nullptr; + switch (r) + { + case 0: + case 1: + cell = module->addDff(NEW_ID, C, D, Q, r & 1); + break; + case 2: + case 3: + case 4: + case 5: + //cell = module->addDffe(NEW_ID, C, module->addWire(NEW_ID), D, Q, r & 1, r & 4); + //break; + case 6: + case 7: + WIDTH = 1; + cell = module->addDffGate(NEW_ID, C, D[0], Q[0], r & 1); + break; + default: log_abort(); + } + shiftx->connections_.at(\A)[shiftx_width-1] = port(cell, \Q)[rng(WIDTH)]; endmatch code clk_port en_port @@ -264,6 +283,36 @@ match next filter !next->type.in($dffe) || param(next, \EN_POLARITY).as_bool() == param(first, \EN_POLARITY).as_bool() filter !chain_bits.count(port(next, \D)[idx]) set slice idx +generate + if (GetSize(chain) < shiftx_width) { + auto back = chain.back().first; + auto slice = chain.back().second; + if (back->type.in($dff, $dffe)) { + auto WIDTH = GetSize(port(back, \D)); + if (rng(2) == 0 && slice < WIDTH-1) { + auto new_slice = slice + rng(WIDTH-1-slice); + back->connections_.at(\D)[slice] = port(back, \Q)[new_slice]; + } + else { + auto D = module->addWire(NEW_ID, WIDTH); + if (back->type == $dff) + module->addDff(NEW_ID, port(back, \CLK), D, port(back, \D), param(back, \CLK_POLARITY).as_bool()); + else if (back->type == $dffe) + module->addDffe(NEW_ID, port(back, \CLK), port(back, \EN), D, port(back, \D), param(back, \CLK_POLARITY).as_bool(), param(back, \EN_POLARITY).as_bool()); + else + log_abort(); + } + } + else if (back->type.begins_with("$_DFF_")) { + Cell *cell = module->addCell(NEW_ID, back->type); + cell->setPort(\C, back->getPort(\C)); + cell->setPort(\D, module->addWire(NEW_ID)); + cell->setPort(\Q, back->getPort(\D)); + } + else + log_abort(); + shiftx->connections_.at(\A)[shiftx_width-1-GetSize(chain)] = port(back, \D)[slice]; + } endmatch code From 54422c5bb4cdd3488fa1849af9049d0f4bb24603 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 26 Aug 2019 17:51:13 -0700 Subject: [PATCH 087/130] Remove leftover header --- passes/pmgen/xilinx_srl.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index c332ccb9f..a8264cab2 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -28,7 +28,6 @@ PRIVATE_NAMESPACE_BEGIN bool did_something; #include "passes/pmgen/xilinx_srl_pm.h" -#include "passes/pmgen/ice40_dsp_pm.h" #include "passes/pmgen/peepopt_pm.h" void run_fixed(xilinx_srl_pm &pm) From 6b5e65919a6ec14d4bfc85f80d1f7492d5b86c16 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 26 Aug 2019 17:52:57 -0700 Subject: [PATCH 088/130] Revert "In sat: 'x' in init attr should not override constant" This reverts commit 2b37a093e95036b267481b2dae2046278eef4040. --- passes/sat/sat.cc | 2 -- tests/sat/initval.v | 4 ---- tests/sat/initval.ys | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index bcc690fa3..dd56d8c71 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -268,8 +268,6 @@ struct SatHelper RTLIL::SigSpec removed_bits; for (int i = 0; i < lhs.size(); i++) { RTLIL::SigSpec bit = lhs.extract(i, 1); - if (bit.is_fully_const() && rhs[i] == State::Sx) - rhs[i] = bit; if (!satgen.initial_state.check_all(bit)) { removed_bits.append(bit); lhs.remove(i, 1); diff --git a/tests/sat/initval.v b/tests/sat/initval.v index d46ccae48..5b661f8d6 100644 --- a/tests/sat/initval.v +++ b/tests/sat/initval.v @@ -1,7 +1,6 @@ module test(input clk, input [3:0] bar, output [3:0] foo); reg [3:0] foo = 0; reg [3:0] last_bar = 0; - reg [3:0] asdf = 4'b1xxx; always @* foo[1:0] <= bar[1:0]; @@ -12,8 +11,5 @@ module test(input clk, input [3:0] bar, output [3:0] foo); always @(posedge clk) last_bar <= bar; - always @* - asdf[2:0] <= 3'b111; - assert property (foo == {last_bar[3:2], bar[1:0]}); endmodule diff --git a/tests/sat/initval.ys b/tests/sat/initval.ys index 3d88aa971..2079d2f34 100644 --- a/tests/sat/initval.ys +++ b/tests/sat/initval.ys @@ -1,4 +1,4 @@ read_verilog -sv initval.v -proc; +proc;; sat -seq 10 -prove-asserts From 9172d4a6740145e7b3c7c34b8fb5effd23598a94 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 26 Aug 2019 21:02:52 -0700 Subject: [PATCH 089/130] Missing close bracket --- passes/pmgen/xilinx_srl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index a8264cab2..b9cdbfaa1 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -213,7 +213,7 @@ struct XilinxSrlPass : public Pass { log("\n"); log(" -variable\n"); log(" infer variable-length shift registers (i.e. fixed-length shifts where\n"); - log(" each element also fans-out to a $shiftx cell.\n"); + log(" each element also fans-out to a $shiftx cell).\n"); log("\n"); } From aad9bad32604645e2d61f0858234a1838e8b88eb Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Tue, 27 Aug 2019 13:56:26 +0300 Subject: [PATCH 090/130] Add tests for macc and rom; Test cases from https://www.latticesemi.com/-/media/LatticeSemi/Documents/UserManuals/EI/iCEcube201701UserGuide.ashx?document_id=52071; In both cases synthesized only LUTs and DFFs. --- tests/ice40/macc.v | 22 ++++++++++++++++++++++ tests/ice40/macc.ys | 10 ++++++++++ tests/ice40/rom.v | 15 +++++++++++++++ tests/ice40/rom.ys | 8 ++++++++ 4 files changed, 55 insertions(+) create mode 100644 tests/ice40/macc.v create mode 100644 tests/ice40/macc.ys create mode 100644 tests/ice40/rom.v create mode 100644 tests/ice40/rom.ys diff --git a/tests/ice40/macc.v b/tests/ice40/macc.v new file mode 100644 index 000000000..115f8ce42 --- /dev/null +++ b/tests/ice40/macc.v @@ -0,0 +1,22 @@ +module top(clk,a,b,c,set); +parameter A_WIDTH = 4; +parameter B_WIDTH = 3; +input set; +input clk; +input signed [(A_WIDTH - 1):0] a; +input signed [(B_WIDTH - 1):0] b; +output signed [(A_WIDTH + B_WIDTH - 1):0] c; +reg [(A_WIDTH + B_WIDTH - 1):0] reg_tmp_c; +assign c = reg_tmp_c; +always @(posedge clk) +begin +if(set) +begin +reg_tmp_c <= 0; +end +else +begin +reg_tmp_c <= a * b + c; +end +end +endmodule diff --git a/tests/ice40/macc.ys b/tests/ice40/macc.ys new file mode 100644 index 000000000..233e7e890 --- /dev/null +++ b/tests/ice40/macc.ys @@ -0,0 +1,10 @@ +read_verilog macc.v +proc +hierarchy -top top +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -dsp # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 41 t:SB_LUT4 +select -assert-count 6 t:SB_CARRY +select -assert-count 7 t:SB_DFFSR +select -assert-none t:SB_LUT4 t:SB_CARRY t:SB_DFFSR %% t:* %D diff --git a/tests/ice40/rom.v b/tests/ice40/rom.v new file mode 100644 index 000000000..c31ca3b2b --- /dev/null +++ b/tests/ice40/rom.v @@ -0,0 +1,15 @@ +module top(data, addr); +output [3:0] data; +input [4:0] addr; +always @(addr) begin +case (addr) +0 : data = 'h4; +1 : data = 'h9; +2 : data = 'h1; +15 : data = 'h8; +16 : data = 'h1; +17 : data = 'h0; +default : data = 'h0; +endcase +end +endmodule diff --git a/tests/ice40/rom.ys b/tests/ice40/rom.ys new file mode 100644 index 000000000..41d214e2a --- /dev/null +++ b/tests/ice40/rom.ys @@ -0,0 +1,8 @@ +read_verilog rom.v +proc +flatten +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 5 t:SB_LUT4 +select -assert-none t:SB_LUT4 %% t:* %D From 134d3fea909bae02f4f814e3d649658502b44b73 Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Tue, 27 Aug 2019 18:12:18 +0300 Subject: [PATCH 091/130] Add tests for ecp5 architecture. --- Makefile | 1 + tests/ecp5/.gitignore | 4 ++ tests/ecp5/add_sub.v | 13 ++++++ tests/ecp5/add_sub.ys | 8 ++++ tests/ecp5/adffs.v | 91 ++++++++++++++++++++++++++++++++++++ tests/ecp5/adffs.ys | 12 +++++ tests/ecp5/common.v | 47 +++++++++++++++++++ tests/ecp5/dffs.v | 37 +++++++++++++++ tests/ecp5/dffs.ys | 10 ++++ tests/ecp5/div_mod.v | 13 ++++++ tests/ecp5/div_mod.ys | 12 +++++ tests/ecp5/dpram.v | 20 ++++++++ tests/ecp5/dpram.ys | 18 ++++++++ tests/ecp5/dpram_tb.v | 81 ++++++++++++++++++++++++++++++++ tests/ecp5/latches.v | 58 +++++++++++++++++++++++ tests/ecp5/latches.ys | 7 +++ tests/ecp5/latches_tb.v | 57 +++++++++++++++++++++++ tests/ecp5/macc.v | 22 +++++++++ tests/ecp5/macc.ys | 10 ++++ tests/ecp5/memory.v | 21 +++++++++ tests/ecp5/memory.ys | 22 +++++++++ tests/ecp5/memory_tb.v | 79 +++++++++++++++++++++++++++++++ tests/ecp5/mul.v | 11 +++++ tests/ecp5/mul.ys | 11 +++++ tests/ecp5/mux.v | 100 ++++++++++++++++++++++++++++++++++++++++ tests/ecp5/mux.ys | 11 +++++ tests/ecp5/rom.v | 15 ++++++ tests/ecp5/rom.ys | 9 ++++ tests/ecp5/run-test.sh | 33 +++++++++++++ tests/ecp5/tribuf.v | 23 +++++++++ tests/ecp5/tribuf.ys | 9 ++++ 31 files changed, 865 insertions(+) create mode 100644 tests/ecp5/.gitignore create mode 100644 tests/ecp5/add_sub.v create mode 100644 tests/ecp5/add_sub.ys create mode 100644 tests/ecp5/adffs.v create mode 100644 tests/ecp5/adffs.ys create mode 100644 tests/ecp5/common.v create mode 100644 tests/ecp5/dffs.v create mode 100644 tests/ecp5/dffs.ys create mode 100644 tests/ecp5/div_mod.v create mode 100644 tests/ecp5/div_mod.ys create mode 100644 tests/ecp5/dpram.v create mode 100644 tests/ecp5/dpram.ys create mode 100644 tests/ecp5/dpram_tb.v create mode 100644 tests/ecp5/latches.v create mode 100644 tests/ecp5/latches.ys create mode 100644 tests/ecp5/latches_tb.v create mode 100644 tests/ecp5/macc.v create mode 100644 tests/ecp5/macc.ys create mode 100644 tests/ecp5/memory.v create mode 100644 tests/ecp5/memory.ys create mode 100644 tests/ecp5/memory_tb.v create mode 100644 tests/ecp5/mul.v create mode 100644 tests/ecp5/mul.ys create mode 100644 tests/ecp5/mux.v create mode 100644 tests/ecp5/mux.ys create mode 100644 tests/ecp5/rom.v create mode 100644 tests/ecp5/rom.ys create mode 100755 tests/ecp5/run-test.sh create mode 100644 tests/ecp5/tribuf.v create mode 100644 tests/ecp5/tribuf.ys diff --git a/Makefile b/Makefile index 9cfa6a0de..d94ab2465 100644 --- a/Makefile +++ b/Makefile @@ -700,6 +700,7 @@ test: $(TARGETS) $(EXTRA_TARGETS) +cd tests/aiger && bash run-test.sh $(ABCOPT) +cd tests/arch && bash run-test.sh +cd tests/ice40 && bash run-test.sh $(SEEDOPT) + +cd tests/ecp5 && bash run-test.sh $(SEEDOPT) @echo "" @echo " Passed \"make test\"." @echo "" diff --git a/tests/ecp5/.gitignore b/tests/ecp5/.gitignore new file mode 100644 index 000000000..9a71dca69 --- /dev/null +++ b/tests/ecp5/.gitignore @@ -0,0 +1,4 @@ +*.log +/run-test.mk ++*_synth.v ++*_testbench diff --git a/tests/ecp5/add_sub.v b/tests/ecp5/add_sub.v new file mode 100644 index 000000000..177c32e30 --- /dev/null +++ b/tests/ecp5/add_sub.v @@ -0,0 +1,13 @@ +module top +( + input [3:0] x, + input [3:0] y, + + output [3:0] A, + output [3:0] B + ); + +assign A = x + y; +assign B = x - y; + +endmodule diff --git a/tests/ecp5/add_sub.ys b/tests/ecp5/add_sub.ys new file mode 100644 index 000000000..03aec6694 --- /dev/null +++ b/tests/ecp5/add_sub.ys @@ -0,0 +1,8 @@ +read_verilog add_sub.v +hierarchy -top top +equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 10 t:LUT4 +select -assert-none t:LUT4 %% t:* %D + diff --git a/tests/ecp5/adffs.v b/tests/ecp5/adffs.v new file mode 100644 index 000000000..93c8bf52c --- /dev/null +++ b/tests/ecp5/adffs.v @@ -0,0 +1,91 @@ +module adff + ( input d, clk, clr, output reg q ); + initial begin + q = 0; + end + always @( posedge clk, posedge clr ) + if ( clr ) + q <= 1'b0; + else + q <= d; +endmodule + +module adffn + ( input d, clk, clr, output reg q ); + initial begin + q = 0; + end + always @( posedge clk, negedge clr ) + if ( !clr ) + q <= 1'b0; + else + q <= d; +endmodule + +module dffsr + ( input d, clk, pre, clr, output reg q ); + initial begin + q = 0; + end + always @( posedge clk, posedge pre, posedge clr ) + if ( clr ) + q <= 1'b0; + else if ( pre ) + q <= 1'b1; + else + q <= d; +endmodule + +module ndffnsnr + ( input d, clk, pre, clr, output reg q ); + initial begin + q = 0; + end + always @( negedge clk, negedge pre, negedge clr ) + if ( !clr ) + q <= 1'b0; + else if ( !pre ) + q <= 1'b1; + else + q <= d; +endmodule + +module top ( +input clk, +input clr, +input pre, +input a, +output b,b1,b2,b3 +); + +dffsr u_dffsr ( + .clk (clk ), + .clr (clr), + .pre (pre), + .d (a ), + .q (b ) + ); + +ndffnsnr u_ndffnsnr ( + .clk (clk ), + .clr (clr), + .pre (pre), + .d (a ), + .q (b1 ) + ); + +adff u_adff ( + .clk (clk ), + .clr (clr), + .d (a ), + .q (b2 ) + ); + +adffn u_adffn ( + .clk (clk ), + .clr (clr), + .d (a ), + .q (b3 ) + ); + +endmodule diff --git a/tests/ecp5/adffs.ys b/tests/ecp5/adffs.ys new file mode 100644 index 000000000..5829fef5f --- /dev/null +++ b/tests/ecp5/adffs.ys @@ -0,0 +1,12 @@ +read_verilog adffs.v +proc +async2sync # converts async flops to a 'sync' variant clocked by a 'super'-clock +flatten +equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 1 t:DFF +select -assert-count 1 t:DFFN +select -assert-count 2 t:DFFSR +select -assert-count 7 t:LUT4 +select -assert-none t:DFF t:DFFN t:DFFSR t:LUT4 %% t:* %D diff --git a/tests/ecp5/common.v b/tests/ecp5/common.v new file mode 100644 index 000000000..5446f0817 --- /dev/null +++ b/tests/ecp5/common.v @@ -0,0 +1,47 @@ +module assert_dff(input clk, input test, input pat); + always @(posedge clk) + begin + #1; + if (test != pat) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time); + $stop; + end + end +endmodule + +module assert_tri(input en, input A, input B); + always @(posedge en) + begin + #1; + if (A !== B) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); + $stop; + end + end +endmodule + +module assert_Z(input clk, input A); + always @(posedge clk) + begin + #1; + if (A === 1'bZ) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A); + $stop; + end + end +endmodule + +module assert_comb(input A, input B); + always @(*) + begin + #1; + if (A !== B) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); + $stop; + end + end +endmodule diff --git a/tests/ecp5/dffs.v b/tests/ecp5/dffs.v new file mode 100644 index 000000000..d97840c43 --- /dev/null +++ b/tests/ecp5/dffs.v @@ -0,0 +1,37 @@ +module dff + ( input d, clk, output reg q ); + always @( posedge clk ) + q <= d; +endmodule + +module dffe + ( input d, clk, en, output reg q ); + initial begin + q = 0; + end + always @( posedge clk ) + if ( en ) + q <= d; +endmodule + +module top ( +input clk, +input en, +input a, +output b,b1, +); + +dff u_dff ( + .clk (clk ), + .d (a ), + .q (b ) + ); + +dffe u_ndffe ( + .clk (clk ), + .en (en), + .d (a ), + .q (b1 ) + ); + +endmodule diff --git a/tests/ecp5/dffs.ys b/tests/ecp5/dffs.ys new file mode 100644 index 000000000..07470c5ba --- /dev/null +++ b/tests/ecp5/dffs.ys @@ -0,0 +1,10 @@ +read_verilog dffs.v +hierarchy -top top +proc +flatten +equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 1 t:DFF +select -assert-count 1 t:DFFE +select -assert-none t:DFF t:DFFE %% t:* %D diff --git a/tests/ecp5/div_mod.v b/tests/ecp5/div_mod.v new file mode 100644 index 000000000..64a36707d --- /dev/null +++ b/tests/ecp5/div_mod.v @@ -0,0 +1,13 @@ +module top +( + input [3:0] x, + input [3:0] y, + + output [3:0] A, + output [3:0] B + ); + +assign A = x % y; +assign B = x / y; + +endmodule diff --git a/tests/ecp5/div_mod.ys b/tests/ecp5/div_mod.ys new file mode 100644 index 000000000..169c5978e --- /dev/null +++ b/tests/ecp5/div_mod.ys @@ -0,0 +1,12 @@ +read_verilog div_mod.v +hierarchy -top top +flatten +equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 28 t:CCU2C +select -assert-count 45 t:L6MUX21 +select -assert-count 183 t:LUT4 +select -assert-count 79 t:PFUMX +select -assert-none t:LUT4 t:CCU2C t:L6MUX21 t:PFUMX %% t:* %D diff --git a/tests/ecp5/dpram.v b/tests/ecp5/dpram.v new file mode 100644 index 000000000..2e69d6b3b --- /dev/null +++ b/tests/ecp5/dpram.v @@ -0,0 +1,20 @@ +module top (din, write_en, waddr, wclk, raddr, rclk, dout); +parameter addr_width = 8; +parameter data_width = 8; +input [addr_width-1:0] waddr, raddr; +input [data_width-1:0] din; +input write_en, wclk, rclk; +output [data_width-1:0] dout; +reg [data_width-1:0] dout; +reg [data_width-1:0] mem [(1< 6'h3E) + mem_init <= 1; + end + + always @(posedge clk) begin + //#3; + we_a <= !we_a; + end + + reg [7:0] mem [(1<<8)-1:0]; + + always @(posedge clk) // Write memory. + begin + if (we_a) + mem[addr_a] <= data_a; // Using write address bus. + end + always @(posedge clk) // Read memory. + begin + pq_a <= mem[addr_b]; // Using read address bus. + end + + top uut ( + .din(data_a), + .write_en(we_a), + .waddr(addr_a), + .wclk(clk), + .raddr(addr_b), + .rclk(clk), + .dout(q_a) + ); + + uut_mem_checker port_a_test(.clk(clk), .init(mem_init), .en(!we_a), .A(q_a), .B(pq_a)); + +endmodule + +module uut_mem_checker(input clk, input init, input en, input [7:0] A, input [7:0] B); + always @(posedge clk) + begin + #1; + if (en == 1 & init == 1 & A !== B) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); + $stop; + end + end +endmodule diff --git a/tests/ecp5/latches.v b/tests/ecp5/latches.v new file mode 100644 index 000000000..9dc43e4c2 --- /dev/null +++ b/tests/ecp5/latches.v @@ -0,0 +1,58 @@ +module latchp + ( input d, clk, en, output reg q ); + always @* + if ( en ) + q <= d; +endmodule + +module latchn + ( input d, clk, en, output reg q ); + always @* + if ( !en ) + q <= d; +endmodule + +module latchsr + ( input d, clk, en, clr, pre, output reg q ); + always @* + if ( clr ) + q <= 1'b0; + else if ( pre ) + q <= 1'b1; + else if ( en ) + q <= d; +endmodule + + +module top ( +input clk, +input clr, +input pre, +input a, +output b,b1,b2 +); + + +latchp u_latchp ( + .en (clk ), + .d (a ), + .q (b ) + ); + + +latchn u_latchn ( + .en (clk ), + .d (a ), + .q (b1 ) + ); + + +latchsr u_latchsr ( + .en (clk ), + .clr (clr), + .pre (pre), + .d (a ), + .q (b2 ) + ); + +endmodule diff --git a/tests/ecp5/latches.ys b/tests/ecp5/latches.ys new file mode 100644 index 000000000..2c77304a1 --- /dev/null +++ b/tests/ecp5/latches.ys @@ -0,0 +1,7 @@ +read_verilog latches.v +synth_ecp5 +cd top +select -assert-count 4 t:LUT4 +select -assert-count 1 t:PFUMX +select -assert-none t:LUT4 t:PFUMX %% t:* %D +write_verilog latches_synth.v diff --git a/tests/ecp5/latches_tb.v b/tests/ecp5/latches_tb.v new file mode 100644 index 000000000..b0585264b --- /dev/null +++ b/tests/ecp5/latches_tb.v @@ -0,0 +1,57 @@ +module testbench; + reg clk; + + initial begin + // $dumpfile("testbench.vcd"); + // $dumpvars(0, testbench); + + #5 clk = 0; + repeat (10000) begin + #5 clk = 1; + #5 clk = 0; + end + end + + + reg [2:0] dinA = 0; + wire doutB,doutB1,doutB2; + reg lat,latn,latsr = 0; + + top uut ( + .clk (clk ), + .a (dinA[0] ), + .pre (dinA[1] ), + .clr (dinA[2] ), + .b (doutB ), + .b1 (doutB1 ), + .b2 (doutB2 ) + ); + + always @(posedge clk) begin + #3; + dinA <= dinA + 1; + end + + always @* + if ( clk ) + lat <= dinA[0]; + + + always @* + if ( !clk ) + latn <= dinA[0]; + + + always @* + if ( dinA[2] ) + latsr <= 1'b0; + else if ( dinA[1] ) + latsr <= 1'b1; + else if ( clk ) + latsr <= dinA[0]; + + assert_dff lat_test(.clk(clk), .test(doutB), .pat(lat)); + assert_dff latn_test(.clk(clk), .test(doutB1), .pat(latn)); + assert_dff latsr_test(.clk(clk), .test(doutB2), .pat(latsr)); + +endmodule diff --git a/tests/ecp5/macc.v b/tests/ecp5/macc.v new file mode 100644 index 000000000..115f8ce42 --- /dev/null +++ b/tests/ecp5/macc.v @@ -0,0 +1,22 @@ +module top(clk,a,b,c,set); +parameter A_WIDTH = 4; +parameter B_WIDTH = 3; +input set; +input clk; +input signed [(A_WIDTH - 1):0] a; +input signed [(B_WIDTH - 1):0] b; +output signed [(A_WIDTH + B_WIDTH - 1):0] c; +reg [(A_WIDTH + B_WIDTH - 1):0] reg_tmp_c; +assign c = reg_tmp_c; +always @(posedge clk) +begin +if(set) +begin +reg_tmp_c <= 0; +end +else +begin +reg_tmp_c <= a * b + c; +end +end +endmodule diff --git a/tests/ecp5/macc.ys b/tests/ecp5/macc.ys new file mode 100644 index 000000000..530877727 --- /dev/null +++ b/tests/ecp5/macc.ys @@ -0,0 +1,10 @@ +read_verilog macc.v +proc +hierarchy -top top +equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 41 t:LUT4 +select -assert-count 6 t:CARRY +select -assert-count 7 t:DFFSR +select -assert-none t:LUT4 t:CARRY t:DFFSR %% t:* %D diff --git a/tests/ecp5/memory.v b/tests/ecp5/memory.v new file mode 100644 index 000000000..cb7753f7b --- /dev/null +++ b/tests/ecp5/memory.v @@ -0,0 +1,21 @@ +module top +( + input [7:0] data_a, + input [6:1] addr_a, + input we_a, clk, + output reg [7:0] q_a +); + // Declare the RAM variable + reg [7:0] ram[63:0]; + + // Port A + always @ (posedge clk) + begin + if (we_a) + begin + ram[addr_a] <= data_a; + q_a <= data_a; + end + q_a <= ram[addr_a]; + end +endmodule diff --git a/tests/ecp5/memory.ys b/tests/ecp5/memory.ys new file mode 100644 index 000000000..9fdeb0d16 --- /dev/null +++ b/tests/ecp5/memory.ys @@ -0,0 +1,22 @@ +read_verilog memory.v +hierarchy -top top +proc +memory -nomap +equiv_opt -run :prove -map +/ecp5/cells_sim.v synth_ecp5 +memory +opt -full + +# TODO +#equiv_opt -run prove: -assert null +miter -equiv -flatten -make_assert -make_outputs gold gate miter +#sat -verify -prove-asserts -tempinduct -show-inputs -show-outputs miter + +design -load postopt +cd top +select -assert-count 24 t:L6MUX21 +select -assert-count 71 t:LUT4 +select -assert-count 32 t:PFUMX +select -assert-count 8 t:TRELLIS_DPR16X4 +select -assert-count 35 t:TRELLIS_FF +select -assert-none t:L6MUX21 t:LUT4 t:PFUMX t:TRELLIS_DPR16X4 t:TRELLIS_FF %% t:* %D +write_verilog memory_synth.v diff --git a/tests/ecp5/memory_tb.v b/tests/ecp5/memory_tb.v new file mode 100644 index 000000000..be69374eb --- /dev/null +++ b/tests/ecp5/memory_tb.v @@ -0,0 +1,79 @@ +module testbench; + reg clk; + + initial begin + // $dumpfile("testbench.vcd"); + // $dumpvars(0, testbench); + + #5 clk = 0; + repeat (10000) begin + #5 clk = 1; + #5 clk = 0; + end + end + + + reg [7:0] data_a = 0; + reg [5:0] addr_a = 0; + reg we_a = 0; + reg re_a = 1; + wire [7:0] q_a; + reg mem_init = 0; + + reg [7:0] pq_a; + + top uut ( + .data_a(data_a), + .addr_a(addr_a), + .we_a(we_a), + .clk(clk), + .q_a(q_a) + ); + + always @(posedge clk) begin + #3; + data_a <= data_a + 17; + + addr_a <= addr_a + 1; + end + + always @(posedge addr_a) begin + #10; + if(addr_a > 6'h3E) + mem_init <= 1; + end + + always @(posedge clk) begin + //#3; + we_a <= !we_a; + end + + // Declare the RAM variable for check + reg [7:0] ram[63:0]; + + // Port A for check + always @ (posedge clk) + begin + if (we_a) + begin + ram[addr_a] <= data_a; + pq_a <= data_a; + end + pq_a <= ram[addr_a]; + end + + uut_mem_checker port_a_test(.clk(clk), .init(mem_init), .en(!we_a), .A(q_a), .B(pq_a)); + +endmodule + +module uut_mem_checker(input clk, input init, input en, input [7:0] A, input [7:0] B); + always @(posedge clk) + begin + #1; + if (en == 1 & init == 1 & A !== B) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); + $stop; + end + end +endmodule diff --git a/tests/ecp5/mul.v b/tests/ecp5/mul.v new file mode 100644 index 000000000..d5b48b1d7 --- /dev/null +++ b/tests/ecp5/mul.v @@ -0,0 +1,11 @@ +module top +( + input [5:0] x, + input [5:0] y, + + output [11:0] A, + ); + +assign A = x * y; + +endmodule diff --git a/tests/ecp5/mul.ys b/tests/ecp5/mul.ys new file mode 100644 index 000000000..0e8d6908f --- /dev/null +++ b/tests/ecp5/mul.ys @@ -0,0 +1,11 @@ +read_verilog mul.v +hierarchy -top top +equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 6 t:CCU2C +select -assert-count 46 t:L6MUX21 +select -assert-count 169 t:LUT4 +select -assert-count 72 t:PFUMX + +select -assert-none t:CCU2C t:L6MUX21 t:LUT4 t:PFUMX %% t:* %D diff --git a/tests/ecp5/mux.v b/tests/ecp5/mux.v new file mode 100644 index 000000000..0814b733e --- /dev/null +++ b/tests/ecp5/mux.v @@ -0,0 +1,100 @@ +module mux2 (S,A,B,Y); + input S; + input A,B; + output reg Y; + + always @(*) + Y = (S)? B : A; +endmodule + +module mux4 ( S, D, Y ); + +input[1:0] S; +input[3:0] D; +output Y; + +reg Y; +wire[1:0] S; +wire[3:0] D; + +always @* +begin + case( S ) + 0 : Y = D[0]; + 1 : Y = D[1]; + 2 : Y = D[2]; + 3 : Y = D[3]; + endcase +end + +endmodule + +module mux8 ( S, D, Y ); + +input[2:0] S; +input[7:0] D; +output Y; + +reg Y; +wire[2:0] S; +wire[7:0] D; + +always @* +begin + case( S ) + 0 : Y = D[0]; + 1 : Y = D[1]; + 2 : Y = D[2]; + 3 : Y = D[3]; + 4 : Y = D[4]; + 5 : Y = D[5]; + 6 : Y = D[6]; + 7 : Y = D[7]; + endcase +end + +endmodule + +module mux16 (D, S, Y); + input [15:0] D; + input [3:0] S; + output Y; + +assign Y = D[S]; + +endmodule + + +module top ( +input [3:0] S, +input [15:0] D, +output M2,M4,M8,M16 +); + +mux2 u_mux2 ( + .S (S[0]), + .A (D[0]), + .B (D[1]), + .Y (M2) + ); + + +mux4 u_mux4 ( + .S (S[1:0]), + .D (D[3:0]), + .Y (M4) + ); + +mux8 u_mux8 ( + .S (S[2:0]), + .D (D[7:0]), + .Y (M8) + ); + +mux16 u_mux16 ( + .S (S[3:0]), + .D (D[15:0]), + .Y (M16) + ); + +endmodule diff --git a/tests/ecp5/mux.ys b/tests/ecp5/mux.ys new file mode 100644 index 000000000..47a965dd3 --- /dev/null +++ b/tests/ecp5/mux.ys @@ -0,0 +1,11 @@ +read_verilog mux.v +proc +flatten +equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 30 t:LUT4 +select -assert-count 7 t:L6MUX21 +select -assert-count 12 t:PFUMX + +select -assert-none t:LUT4 t:L6MUX21 t:PFUMX %% t:* %D diff --git a/tests/ecp5/rom.v b/tests/ecp5/rom.v new file mode 100644 index 000000000..c31ca3b2b --- /dev/null +++ b/tests/ecp5/rom.v @@ -0,0 +1,15 @@ +module top(data, addr); +output [3:0] data; +input [4:0] addr; +always @(addr) begin +case (addr) +0 : data = 'h4; +1 : data = 'h9; +2 : data = 'h1; +15 : data = 'h8; +16 : data = 'h1; +17 : data = 'h0; +default : data = 'h0; +endcase +end +endmodule diff --git a/tests/ecp5/rom.ys b/tests/ecp5/rom.ys new file mode 100644 index 000000000..8a52749a1 --- /dev/null +++ b/tests/ecp5/rom.ys @@ -0,0 +1,9 @@ +read_verilog rom.v +proc +flatten +equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 6 t:LUT4 +select -assert-count 3 t:PFUMX +select -assert-none t:LUT4 t:PFUMX %% t:* %D diff --git a/tests/ecp5/run-test.sh b/tests/ecp5/run-test.sh new file mode 100755 index 000000000..bd9d35314 --- /dev/null +++ b/tests/ecp5/run-test.sh @@ -0,0 +1,33 @@ +set -e +if [ -f "../../techlibs/common/simcells.v" ]; then + COMMON_PREFIX=../../techlibs/common + TECHLIBS_PREFIX=../../techlibs +else + COMMON_PREFIX=/usr/local/share/yosys + TECHLIBS_PREFIX=/usr/local/share/yosys +fi +{ +echo "all::" +for x in *.ys; do + echo "all:: run-$x" + echo "run-$x:" + echo " @echo 'Running $x..'" + echo " @../../yosys -ql ${x%.ys}.log $x -w 'Yosys has only limited support for tri-state logic at the moment.'" + + if [ -f "${x%.ys}_tb.v" ]; then + echo " @echo 'Running ${x%.ys}_tb.v..'" + echo " @iverilog -o ${x%.ys}_testbench $t ${x%.ys}_synth.v common.v $TECHLIBS_PREFIX/ice40/cells_sim.v" + echo " @vvp -N ${x%.ys}_testbench" + fi +done + +for s in *.sh; do + if [ "$s" != "run-test.sh" ]; then + echo "all:: run-$s" + echo "run-$s:" + echo " @echo 'Running $s..'" + echo " @bash $s" + fi +done +} > run-test.mk +exec ${MAKE:-make} -f run-test.mk diff --git a/tests/ecp5/tribuf.v b/tests/ecp5/tribuf.v new file mode 100644 index 000000000..870a02584 --- /dev/null +++ b/tests/ecp5/tribuf.v @@ -0,0 +1,23 @@ +module tristate (en, i, o); + input en; + input i; + output o; + + assign o = en ? i : 1'bz; + +endmodule + + +module top ( +input en, +input a, +output b +); + +tristate u_tri ( + .en (en ), + .i (a ), + .o (b ) + ); + +endmodule diff --git a/tests/ecp5/tribuf.ys b/tests/ecp5/tribuf.ys new file mode 100644 index 000000000..f454a0c02 --- /dev/null +++ b/tests/ecp5/tribuf.ys @@ -0,0 +1,9 @@ +read_verilog tribuf.v +hierarchy -top top +proc +flatten +equiv_opt -assert -map +/ecp5/cells_sim.v -map +/simcells.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 1 t:$_TBUF_ +select -assert-none t:$_TBUF_ %% t:* %D From 980830f7b82f2a974f43580f61e917f99fbb4e7e Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Tue, 27 Aug 2019 18:28:05 +0300 Subject: [PATCH 092/130] Revert "Add tests for ecp5 architecture." This reverts commit 134d3fea909bae02f4f814e3d649658502b44b73. --- Makefile | 1 - tests/ecp5/.gitignore | 4 -- tests/ecp5/add_sub.v | 13 ------ tests/ecp5/add_sub.ys | 8 ---- tests/ecp5/adffs.v | 91 ------------------------------------ tests/ecp5/adffs.ys | 12 ----- tests/ecp5/common.v | 47 ------------------- tests/ecp5/dffs.v | 37 --------------- tests/ecp5/dffs.ys | 10 ---- tests/ecp5/div_mod.v | 13 ------ tests/ecp5/div_mod.ys | 12 ----- tests/ecp5/dpram.v | 20 -------- tests/ecp5/dpram.ys | 18 -------- tests/ecp5/dpram_tb.v | 81 -------------------------------- tests/ecp5/latches.v | 58 ----------------------- tests/ecp5/latches.ys | 7 --- tests/ecp5/latches_tb.v | 57 ----------------------- tests/ecp5/macc.v | 22 --------- tests/ecp5/macc.ys | 10 ---- tests/ecp5/memory.v | 21 --------- tests/ecp5/memory.ys | 22 --------- tests/ecp5/memory_tb.v | 79 ------------------------------- tests/ecp5/mul.v | 11 ----- tests/ecp5/mul.ys | 11 ----- tests/ecp5/mux.v | 100 ---------------------------------------- tests/ecp5/mux.ys | 11 ----- tests/ecp5/rom.v | 15 ------ tests/ecp5/rom.ys | 9 ---- tests/ecp5/run-test.sh | 33 ------------- tests/ecp5/tribuf.v | 23 --------- tests/ecp5/tribuf.ys | 9 ---- 31 files changed, 865 deletions(-) delete mode 100644 tests/ecp5/.gitignore delete mode 100644 tests/ecp5/add_sub.v delete mode 100644 tests/ecp5/add_sub.ys delete mode 100644 tests/ecp5/adffs.v delete mode 100644 tests/ecp5/adffs.ys delete mode 100644 tests/ecp5/common.v delete mode 100644 tests/ecp5/dffs.v delete mode 100644 tests/ecp5/dffs.ys delete mode 100644 tests/ecp5/div_mod.v delete mode 100644 tests/ecp5/div_mod.ys delete mode 100644 tests/ecp5/dpram.v delete mode 100644 tests/ecp5/dpram.ys delete mode 100644 tests/ecp5/dpram_tb.v delete mode 100644 tests/ecp5/latches.v delete mode 100644 tests/ecp5/latches.ys delete mode 100644 tests/ecp5/latches_tb.v delete mode 100644 tests/ecp5/macc.v delete mode 100644 tests/ecp5/macc.ys delete mode 100644 tests/ecp5/memory.v delete mode 100644 tests/ecp5/memory.ys delete mode 100644 tests/ecp5/memory_tb.v delete mode 100644 tests/ecp5/mul.v delete mode 100644 tests/ecp5/mul.ys delete mode 100644 tests/ecp5/mux.v delete mode 100644 tests/ecp5/mux.ys delete mode 100644 tests/ecp5/rom.v delete mode 100644 tests/ecp5/rom.ys delete mode 100755 tests/ecp5/run-test.sh delete mode 100644 tests/ecp5/tribuf.v delete mode 100644 tests/ecp5/tribuf.ys diff --git a/Makefile b/Makefile index d94ab2465..9cfa6a0de 100644 --- a/Makefile +++ b/Makefile @@ -700,7 +700,6 @@ test: $(TARGETS) $(EXTRA_TARGETS) +cd tests/aiger && bash run-test.sh $(ABCOPT) +cd tests/arch && bash run-test.sh +cd tests/ice40 && bash run-test.sh $(SEEDOPT) - +cd tests/ecp5 && bash run-test.sh $(SEEDOPT) @echo "" @echo " Passed \"make test\"." @echo "" diff --git a/tests/ecp5/.gitignore b/tests/ecp5/.gitignore deleted file mode 100644 index 9a71dca69..000000000 --- a/tests/ecp5/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*.log -/run-test.mk -+*_synth.v -+*_testbench diff --git a/tests/ecp5/add_sub.v b/tests/ecp5/add_sub.v deleted file mode 100644 index 177c32e30..000000000 --- a/tests/ecp5/add_sub.v +++ /dev/null @@ -1,13 +0,0 @@ -module top -( - input [3:0] x, - input [3:0] y, - - output [3:0] A, - output [3:0] B - ); - -assign A = x + y; -assign B = x - y; - -endmodule diff --git a/tests/ecp5/add_sub.ys b/tests/ecp5/add_sub.ys deleted file mode 100644 index 03aec6694..000000000 --- a/tests/ecp5/add_sub.ys +++ /dev/null @@ -1,8 +0,0 @@ -read_verilog add_sub.v -hierarchy -top top -equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -select -assert-count 10 t:LUT4 -select -assert-none t:LUT4 %% t:* %D - diff --git a/tests/ecp5/adffs.v b/tests/ecp5/adffs.v deleted file mode 100644 index 93c8bf52c..000000000 --- a/tests/ecp5/adffs.v +++ /dev/null @@ -1,91 +0,0 @@ -module adff - ( input d, clk, clr, output reg q ); - initial begin - q = 0; - end - always @( posedge clk, posedge clr ) - if ( clr ) - q <= 1'b0; - else - q <= d; -endmodule - -module adffn - ( input d, clk, clr, output reg q ); - initial begin - q = 0; - end - always @( posedge clk, negedge clr ) - if ( !clr ) - q <= 1'b0; - else - q <= d; -endmodule - -module dffsr - ( input d, clk, pre, clr, output reg q ); - initial begin - q = 0; - end - always @( posedge clk, posedge pre, posedge clr ) - if ( clr ) - q <= 1'b0; - else if ( pre ) - q <= 1'b1; - else - q <= d; -endmodule - -module ndffnsnr - ( input d, clk, pre, clr, output reg q ); - initial begin - q = 0; - end - always @( negedge clk, negedge pre, negedge clr ) - if ( !clr ) - q <= 1'b0; - else if ( !pre ) - q <= 1'b1; - else - q <= d; -endmodule - -module top ( -input clk, -input clr, -input pre, -input a, -output b,b1,b2,b3 -); - -dffsr u_dffsr ( - .clk (clk ), - .clr (clr), - .pre (pre), - .d (a ), - .q (b ) - ); - -ndffnsnr u_ndffnsnr ( - .clk (clk ), - .clr (clr), - .pre (pre), - .d (a ), - .q (b1 ) - ); - -adff u_adff ( - .clk (clk ), - .clr (clr), - .d (a ), - .q (b2 ) - ); - -adffn u_adffn ( - .clk (clk ), - .clr (clr), - .d (a ), - .q (b3 ) - ); - -endmodule diff --git a/tests/ecp5/adffs.ys b/tests/ecp5/adffs.ys deleted file mode 100644 index 5829fef5f..000000000 --- a/tests/ecp5/adffs.ys +++ /dev/null @@ -1,12 +0,0 @@ -read_verilog adffs.v -proc -async2sync # converts async flops to a 'sync' variant clocked by a 'super'-clock -flatten -equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -select -assert-count 1 t:DFF -select -assert-count 1 t:DFFN -select -assert-count 2 t:DFFSR -select -assert-count 7 t:LUT4 -select -assert-none t:DFF t:DFFN t:DFFSR t:LUT4 %% t:* %D diff --git a/tests/ecp5/common.v b/tests/ecp5/common.v deleted file mode 100644 index 5446f0817..000000000 --- a/tests/ecp5/common.v +++ /dev/null @@ -1,47 +0,0 @@ -module assert_dff(input clk, input test, input pat); - always @(posedge clk) - begin - #1; - if (test != pat) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time); - $stop; - end - end -endmodule - -module assert_tri(input en, input A, input B); - always @(posedge en) - begin - #1; - if (A !== B) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); - $stop; - end - end -endmodule - -module assert_Z(input clk, input A); - always @(posedge clk) - begin - #1; - if (A === 1'bZ) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A); - $stop; - end - end -endmodule - -module assert_comb(input A, input B); - always @(*) - begin - #1; - if (A !== B) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); - $stop; - end - end -endmodule diff --git a/tests/ecp5/dffs.v b/tests/ecp5/dffs.v deleted file mode 100644 index d97840c43..000000000 --- a/tests/ecp5/dffs.v +++ /dev/null @@ -1,37 +0,0 @@ -module dff - ( input d, clk, output reg q ); - always @( posedge clk ) - q <= d; -endmodule - -module dffe - ( input d, clk, en, output reg q ); - initial begin - q = 0; - end - always @( posedge clk ) - if ( en ) - q <= d; -endmodule - -module top ( -input clk, -input en, -input a, -output b,b1, -); - -dff u_dff ( - .clk (clk ), - .d (a ), - .q (b ) - ); - -dffe u_ndffe ( - .clk (clk ), - .en (en), - .d (a ), - .q (b1 ) - ); - -endmodule diff --git a/tests/ecp5/dffs.ys b/tests/ecp5/dffs.ys deleted file mode 100644 index 07470c5ba..000000000 --- a/tests/ecp5/dffs.ys +++ /dev/null @@ -1,10 +0,0 @@ -read_verilog dffs.v -hierarchy -top top -proc -flatten -equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -select -assert-count 1 t:DFF -select -assert-count 1 t:DFFE -select -assert-none t:DFF t:DFFE %% t:* %D diff --git a/tests/ecp5/div_mod.v b/tests/ecp5/div_mod.v deleted file mode 100644 index 64a36707d..000000000 --- a/tests/ecp5/div_mod.v +++ /dev/null @@ -1,13 +0,0 @@ -module top -( - input [3:0] x, - input [3:0] y, - - output [3:0] A, - output [3:0] B - ); - -assign A = x % y; -assign B = x / y; - -endmodule diff --git a/tests/ecp5/div_mod.ys b/tests/ecp5/div_mod.ys deleted file mode 100644 index 169c5978e..000000000 --- a/tests/ecp5/div_mod.ys +++ /dev/null @@ -1,12 +0,0 @@ -read_verilog div_mod.v -hierarchy -top top -flatten -equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module - -select -assert-count 28 t:CCU2C -select -assert-count 45 t:L6MUX21 -select -assert-count 183 t:LUT4 -select -assert-count 79 t:PFUMX -select -assert-none t:LUT4 t:CCU2C t:L6MUX21 t:PFUMX %% t:* %D diff --git a/tests/ecp5/dpram.v b/tests/ecp5/dpram.v deleted file mode 100644 index 2e69d6b3b..000000000 --- a/tests/ecp5/dpram.v +++ /dev/null @@ -1,20 +0,0 @@ -module top (din, write_en, waddr, wclk, raddr, rclk, dout); -parameter addr_width = 8; -parameter data_width = 8; -input [addr_width-1:0] waddr, raddr; -input [data_width-1:0] din; -input write_en, wclk, rclk; -output [data_width-1:0] dout; -reg [data_width-1:0] dout; -reg [data_width-1:0] mem [(1< 6'h3E) - mem_init <= 1; - end - - always @(posedge clk) begin - //#3; - we_a <= !we_a; - end - - reg [7:0] mem [(1<<8)-1:0]; - - always @(posedge clk) // Write memory. - begin - if (we_a) - mem[addr_a] <= data_a; // Using write address bus. - end - always @(posedge clk) // Read memory. - begin - pq_a <= mem[addr_b]; // Using read address bus. - end - - top uut ( - .din(data_a), - .write_en(we_a), - .waddr(addr_a), - .wclk(clk), - .raddr(addr_b), - .rclk(clk), - .dout(q_a) - ); - - uut_mem_checker port_a_test(.clk(clk), .init(mem_init), .en(!we_a), .A(q_a), .B(pq_a)); - -endmodule - -module uut_mem_checker(input clk, input init, input en, input [7:0] A, input [7:0] B); - always @(posedge clk) - begin - #1; - if (en == 1 & init == 1 & A !== B) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); - $stop; - end - end -endmodule diff --git a/tests/ecp5/latches.v b/tests/ecp5/latches.v deleted file mode 100644 index 9dc43e4c2..000000000 --- a/tests/ecp5/latches.v +++ /dev/null @@ -1,58 +0,0 @@ -module latchp - ( input d, clk, en, output reg q ); - always @* - if ( en ) - q <= d; -endmodule - -module latchn - ( input d, clk, en, output reg q ); - always @* - if ( !en ) - q <= d; -endmodule - -module latchsr - ( input d, clk, en, clr, pre, output reg q ); - always @* - if ( clr ) - q <= 1'b0; - else if ( pre ) - q <= 1'b1; - else if ( en ) - q <= d; -endmodule - - -module top ( -input clk, -input clr, -input pre, -input a, -output b,b1,b2 -); - - -latchp u_latchp ( - .en (clk ), - .d (a ), - .q (b ) - ); - - -latchn u_latchn ( - .en (clk ), - .d (a ), - .q (b1 ) - ); - - -latchsr u_latchsr ( - .en (clk ), - .clr (clr), - .pre (pre), - .d (a ), - .q (b2 ) - ); - -endmodule diff --git a/tests/ecp5/latches.ys b/tests/ecp5/latches.ys deleted file mode 100644 index 2c77304a1..000000000 --- a/tests/ecp5/latches.ys +++ /dev/null @@ -1,7 +0,0 @@ -read_verilog latches.v -synth_ecp5 -cd top -select -assert-count 4 t:LUT4 -select -assert-count 1 t:PFUMX -select -assert-none t:LUT4 t:PFUMX %% t:* %D -write_verilog latches_synth.v diff --git a/tests/ecp5/latches_tb.v b/tests/ecp5/latches_tb.v deleted file mode 100644 index b0585264b..000000000 --- a/tests/ecp5/latches_tb.v +++ /dev/null @@ -1,57 +0,0 @@ -module testbench; - reg clk; - - initial begin - // $dumpfile("testbench.vcd"); - // $dumpvars(0, testbench); - - #5 clk = 0; - repeat (10000) begin - #5 clk = 1; - #5 clk = 0; - end - end - - - reg [2:0] dinA = 0; - wire doutB,doutB1,doutB2; - reg lat,latn,latsr = 0; - - top uut ( - .clk (clk ), - .a (dinA[0] ), - .pre (dinA[1] ), - .clr (dinA[2] ), - .b (doutB ), - .b1 (doutB1 ), - .b2 (doutB2 ) - ); - - always @(posedge clk) begin - #3; - dinA <= dinA + 1; - end - - always @* - if ( clk ) - lat <= dinA[0]; - - - always @* - if ( !clk ) - latn <= dinA[0]; - - - always @* - if ( dinA[2] ) - latsr <= 1'b0; - else if ( dinA[1] ) - latsr <= 1'b1; - else if ( clk ) - latsr <= dinA[0]; - - assert_dff lat_test(.clk(clk), .test(doutB), .pat(lat)); - assert_dff latn_test(.clk(clk), .test(doutB1), .pat(latn)); - assert_dff latsr_test(.clk(clk), .test(doutB2), .pat(latsr)); - -endmodule diff --git a/tests/ecp5/macc.v b/tests/ecp5/macc.v deleted file mode 100644 index 115f8ce42..000000000 --- a/tests/ecp5/macc.v +++ /dev/null @@ -1,22 +0,0 @@ -module top(clk,a,b,c,set); -parameter A_WIDTH = 4; -parameter B_WIDTH = 3; -input set; -input clk; -input signed [(A_WIDTH - 1):0] a; -input signed [(B_WIDTH - 1):0] b; -output signed [(A_WIDTH + B_WIDTH - 1):0] c; -reg [(A_WIDTH + B_WIDTH - 1):0] reg_tmp_c; -assign c = reg_tmp_c; -always @(posedge clk) -begin -if(set) -begin -reg_tmp_c <= 0; -end -else -begin -reg_tmp_c <= a * b + c; -end -end -endmodule diff --git a/tests/ecp5/macc.ys b/tests/ecp5/macc.ys deleted file mode 100644 index 530877727..000000000 --- a/tests/ecp5/macc.ys +++ /dev/null @@ -1,10 +0,0 @@ -read_verilog macc.v -proc -hierarchy -top top -equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -select -assert-count 41 t:LUT4 -select -assert-count 6 t:CARRY -select -assert-count 7 t:DFFSR -select -assert-none t:LUT4 t:CARRY t:DFFSR %% t:* %D diff --git a/tests/ecp5/memory.v b/tests/ecp5/memory.v deleted file mode 100644 index cb7753f7b..000000000 --- a/tests/ecp5/memory.v +++ /dev/null @@ -1,21 +0,0 @@ -module top -( - input [7:0] data_a, - input [6:1] addr_a, - input we_a, clk, - output reg [7:0] q_a -); - // Declare the RAM variable - reg [7:0] ram[63:0]; - - // Port A - always @ (posedge clk) - begin - if (we_a) - begin - ram[addr_a] <= data_a; - q_a <= data_a; - end - q_a <= ram[addr_a]; - end -endmodule diff --git a/tests/ecp5/memory.ys b/tests/ecp5/memory.ys deleted file mode 100644 index 9fdeb0d16..000000000 --- a/tests/ecp5/memory.ys +++ /dev/null @@ -1,22 +0,0 @@ -read_verilog memory.v -hierarchy -top top -proc -memory -nomap -equiv_opt -run :prove -map +/ecp5/cells_sim.v synth_ecp5 -memory -opt -full - -# TODO -#equiv_opt -run prove: -assert null -miter -equiv -flatten -make_assert -make_outputs gold gate miter -#sat -verify -prove-asserts -tempinduct -show-inputs -show-outputs miter - -design -load postopt -cd top -select -assert-count 24 t:L6MUX21 -select -assert-count 71 t:LUT4 -select -assert-count 32 t:PFUMX -select -assert-count 8 t:TRELLIS_DPR16X4 -select -assert-count 35 t:TRELLIS_FF -select -assert-none t:L6MUX21 t:LUT4 t:PFUMX t:TRELLIS_DPR16X4 t:TRELLIS_FF %% t:* %D -write_verilog memory_synth.v diff --git a/tests/ecp5/memory_tb.v b/tests/ecp5/memory_tb.v deleted file mode 100644 index be69374eb..000000000 --- a/tests/ecp5/memory_tb.v +++ /dev/null @@ -1,79 +0,0 @@ -module testbench; - reg clk; - - initial begin - // $dumpfile("testbench.vcd"); - // $dumpvars(0, testbench); - - #5 clk = 0; - repeat (10000) begin - #5 clk = 1; - #5 clk = 0; - end - end - - - reg [7:0] data_a = 0; - reg [5:0] addr_a = 0; - reg we_a = 0; - reg re_a = 1; - wire [7:0] q_a; - reg mem_init = 0; - - reg [7:0] pq_a; - - top uut ( - .data_a(data_a), - .addr_a(addr_a), - .we_a(we_a), - .clk(clk), - .q_a(q_a) - ); - - always @(posedge clk) begin - #3; - data_a <= data_a + 17; - - addr_a <= addr_a + 1; - end - - always @(posedge addr_a) begin - #10; - if(addr_a > 6'h3E) - mem_init <= 1; - end - - always @(posedge clk) begin - //#3; - we_a <= !we_a; - end - - // Declare the RAM variable for check - reg [7:0] ram[63:0]; - - // Port A for check - always @ (posedge clk) - begin - if (we_a) - begin - ram[addr_a] <= data_a; - pq_a <= data_a; - end - pq_a <= ram[addr_a]; - end - - uut_mem_checker port_a_test(.clk(clk), .init(mem_init), .en(!we_a), .A(q_a), .B(pq_a)); - -endmodule - -module uut_mem_checker(input clk, input init, input en, input [7:0] A, input [7:0] B); - always @(posedge clk) - begin - #1; - if (en == 1 & init == 1 & A !== B) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); - $stop; - end - end -endmodule diff --git a/tests/ecp5/mul.v b/tests/ecp5/mul.v deleted file mode 100644 index d5b48b1d7..000000000 --- a/tests/ecp5/mul.v +++ /dev/null @@ -1,11 +0,0 @@ -module top -( - input [5:0] x, - input [5:0] y, - - output [11:0] A, - ); - -assign A = x * y; - -endmodule diff --git a/tests/ecp5/mul.ys b/tests/ecp5/mul.ys deleted file mode 100644 index 0e8d6908f..000000000 --- a/tests/ecp5/mul.ys +++ /dev/null @@ -1,11 +0,0 @@ -read_verilog mul.v -hierarchy -top top -equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -select -assert-count 6 t:CCU2C -select -assert-count 46 t:L6MUX21 -select -assert-count 169 t:LUT4 -select -assert-count 72 t:PFUMX - -select -assert-none t:CCU2C t:L6MUX21 t:LUT4 t:PFUMX %% t:* %D diff --git a/tests/ecp5/mux.v b/tests/ecp5/mux.v deleted file mode 100644 index 0814b733e..000000000 --- a/tests/ecp5/mux.v +++ /dev/null @@ -1,100 +0,0 @@ -module mux2 (S,A,B,Y); - input S; - input A,B; - output reg Y; - - always @(*) - Y = (S)? B : A; -endmodule - -module mux4 ( S, D, Y ); - -input[1:0] S; -input[3:0] D; -output Y; - -reg Y; -wire[1:0] S; -wire[3:0] D; - -always @* -begin - case( S ) - 0 : Y = D[0]; - 1 : Y = D[1]; - 2 : Y = D[2]; - 3 : Y = D[3]; - endcase -end - -endmodule - -module mux8 ( S, D, Y ); - -input[2:0] S; -input[7:0] D; -output Y; - -reg Y; -wire[2:0] S; -wire[7:0] D; - -always @* -begin - case( S ) - 0 : Y = D[0]; - 1 : Y = D[1]; - 2 : Y = D[2]; - 3 : Y = D[3]; - 4 : Y = D[4]; - 5 : Y = D[5]; - 6 : Y = D[6]; - 7 : Y = D[7]; - endcase -end - -endmodule - -module mux16 (D, S, Y); - input [15:0] D; - input [3:0] S; - output Y; - -assign Y = D[S]; - -endmodule - - -module top ( -input [3:0] S, -input [15:0] D, -output M2,M4,M8,M16 -); - -mux2 u_mux2 ( - .S (S[0]), - .A (D[0]), - .B (D[1]), - .Y (M2) - ); - - -mux4 u_mux4 ( - .S (S[1:0]), - .D (D[3:0]), - .Y (M4) - ); - -mux8 u_mux8 ( - .S (S[2:0]), - .D (D[7:0]), - .Y (M8) - ); - -mux16 u_mux16 ( - .S (S[3:0]), - .D (D[15:0]), - .Y (M16) - ); - -endmodule diff --git a/tests/ecp5/mux.ys b/tests/ecp5/mux.ys deleted file mode 100644 index 47a965dd3..000000000 --- a/tests/ecp5/mux.ys +++ /dev/null @@ -1,11 +0,0 @@ -read_verilog mux.v -proc -flatten -equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -select -assert-count 30 t:LUT4 -select -assert-count 7 t:L6MUX21 -select -assert-count 12 t:PFUMX - -select -assert-none t:LUT4 t:L6MUX21 t:PFUMX %% t:* %D diff --git a/tests/ecp5/rom.v b/tests/ecp5/rom.v deleted file mode 100644 index c31ca3b2b..000000000 --- a/tests/ecp5/rom.v +++ /dev/null @@ -1,15 +0,0 @@ -module top(data, addr); -output [3:0] data; -input [4:0] addr; -always @(addr) begin -case (addr) -0 : data = 'h4; -1 : data = 'h9; -2 : data = 'h1; -15 : data = 'h8; -16 : data = 'h1; -17 : data = 'h0; -default : data = 'h0; -endcase -end -endmodule diff --git a/tests/ecp5/rom.ys b/tests/ecp5/rom.ys deleted file mode 100644 index 8a52749a1..000000000 --- a/tests/ecp5/rom.ys +++ /dev/null @@ -1,9 +0,0 @@ -read_verilog rom.v -proc -flatten -equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -select -assert-count 6 t:LUT4 -select -assert-count 3 t:PFUMX -select -assert-none t:LUT4 t:PFUMX %% t:* %D diff --git a/tests/ecp5/run-test.sh b/tests/ecp5/run-test.sh deleted file mode 100755 index bd9d35314..000000000 --- a/tests/ecp5/run-test.sh +++ /dev/null @@ -1,33 +0,0 @@ -set -e -if [ -f "../../techlibs/common/simcells.v" ]; then - COMMON_PREFIX=../../techlibs/common - TECHLIBS_PREFIX=../../techlibs -else - COMMON_PREFIX=/usr/local/share/yosys - TECHLIBS_PREFIX=/usr/local/share/yosys -fi -{ -echo "all::" -for x in *.ys; do - echo "all:: run-$x" - echo "run-$x:" - echo " @echo 'Running $x..'" - echo " @../../yosys -ql ${x%.ys}.log $x -w 'Yosys has only limited support for tri-state logic at the moment.'" - - if [ -f "${x%.ys}_tb.v" ]; then - echo " @echo 'Running ${x%.ys}_tb.v..'" - echo " @iverilog -o ${x%.ys}_testbench $t ${x%.ys}_synth.v common.v $TECHLIBS_PREFIX/ice40/cells_sim.v" - echo " @vvp -N ${x%.ys}_testbench" - fi -done - -for s in *.sh; do - if [ "$s" != "run-test.sh" ]; then - echo "all:: run-$s" - echo "run-$s:" - echo " @echo 'Running $s..'" - echo " @bash $s" - fi -done -} > run-test.mk -exec ${MAKE:-make} -f run-test.mk diff --git a/tests/ecp5/tribuf.v b/tests/ecp5/tribuf.v deleted file mode 100644 index 870a02584..000000000 --- a/tests/ecp5/tribuf.v +++ /dev/null @@ -1,23 +0,0 @@ -module tristate (en, i, o); - input en; - input i; - output o; - - assign o = en ? i : 1'bz; - -endmodule - - -module top ( -input en, -input a, -output b -); - -tristate u_tri ( - .en (en ), - .i (a ), - .o (b ) - ); - -endmodule diff --git a/tests/ecp5/tribuf.ys b/tests/ecp5/tribuf.ys deleted file mode 100644 index f454a0c02..000000000 --- a/tests/ecp5/tribuf.ys +++ /dev/null @@ -1,9 +0,0 @@ -read_verilog tribuf.v -hierarchy -top top -proc -flatten -equiv_opt -assert -map +/ecp5/cells_sim.v -map +/simcells.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -select -assert-count 1 t:$_TBUF_ -select -assert-none t:$_TBUF_ %% t:* %D From 2270ead09fb4695442c66fe5c06445235f390f2b Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Wed, 28 Aug 2019 09:47:03 +0300 Subject: [PATCH 093/130] Add tests for ecp5 --- Makefile | 1 + tests/ecp5/.gitignore | 2 + tests/ecp5/add_sub.v | 13 ++++++ tests/ecp5/add_sub.ys | 8 ++++ tests/ecp5/adffs.v | 91 ++++++++++++++++++++++++++++++++++++ tests/ecp5/adffs.ys | 12 +++++ tests/ecp5/common.v | 47 +++++++++++++++++++ tests/ecp5/dffs.v | 37 +++++++++++++++ tests/ecp5/dffs.ys | 10 ++++ tests/ecp5/div_mod.v | 13 ++++++ tests/ecp5/div_mod.ys | 12 +++++ tests/ecp5/dpram.v | 20 ++++++++ tests/ecp5/dpram.ys | 18 ++++++++ tests/ecp5/dpram_tb.v | 81 ++++++++++++++++++++++++++++++++ tests/ecp5/latches.v | 58 +++++++++++++++++++++++ tests/ecp5/latches.ys | 7 +++ tests/ecp5/latches_tb.v | 57 +++++++++++++++++++++++ tests/ecp5/macc.v | 22 +++++++++ tests/ecp5/macc.ys | 10 ++++ tests/ecp5/memory.v | 21 +++++++++ tests/ecp5/memory.ys | 22 +++++++++ tests/ecp5/memory_tb.v | 79 +++++++++++++++++++++++++++++++ tests/ecp5/mul.v | 11 +++++ tests/ecp5/mul.ys | 11 +++++ tests/ecp5/mux.v | 100 ++++++++++++++++++++++++++++++++++++++++ tests/ecp5/mux.ys | 11 +++++ tests/ecp5/rom.v | 15 ++++++ tests/ecp5/rom.ys | 9 ++++ tests/ecp5/run-test.sh | 33 +++++++++++++ tests/ecp5/tribuf.v | 23 +++++++++ tests/ecp5/tribuf.ys | 9 ++++ 31 files changed, 863 insertions(+) create mode 100644 tests/ecp5/.gitignore create mode 100644 tests/ecp5/add_sub.v create mode 100644 tests/ecp5/add_sub.ys create mode 100644 tests/ecp5/adffs.v create mode 100644 tests/ecp5/adffs.ys create mode 100644 tests/ecp5/common.v create mode 100644 tests/ecp5/dffs.v create mode 100644 tests/ecp5/dffs.ys create mode 100644 tests/ecp5/div_mod.v create mode 100644 tests/ecp5/div_mod.ys create mode 100644 tests/ecp5/dpram.v create mode 100644 tests/ecp5/dpram.ys create mode 100644 tests/ecp5/dpram_tb.v create mode 100644 tests/ecp5/latches.v create mode 100644 tests/ecp5/latches.ys create mode 100644 tests/ecp5/latches_tb.v create mode 100644 tests/ecp5/macc.v create mode 100644 tests/ecp5/macc.ys create mode 100644 tests/ecp5/memory.v create mode 100644 tests/ecp5/memory.ys create mode 100644 tests/ecp5/memory_tb.v create mode 100644 tests/ecp5/mul.v create mode 100644 tests/ecp5/mul.ys create mode 100644 tests/ecp5/mux.v create mode 100644 tests/ecp5/mux.ys create mode 100644 tests/ecp5/rom.v create mode 100644 tests/ecp5/rom.ys create mode 100755 tests/ecp5/run-test.sh create mode 100644 tests/ecp5/tribuf.v create mode 100644 tests/ecp5/tribuf.ys diff --git a/Makefile b/Makefile index 9cfa6a0de..d94ab2465 100644 --- a/Makefile +++ b/Makefile @@ -700,6 +700,7 @@ test: $(TARGETS) $(EXTRA_TARGETS) +cd tests/aiger && bash run-test.sh $(ABCOPT) +cd tests/arch && bash run-test.sh +cd tests/ice40 && bash run-test.sh $(SEEDOPT) + +cd tests/ecp5 && bash run-test.sh $(SEEDOPT) @echo "" @echo " Passed \"make test\"." @echo "" diff --git a/tests/ecp5/.gitignore b/tests/ecp5/.gitignore new file mode 100644 index 000000000..1d329c933 --- /dev/null +++ b/tests/ecp5/.gitignore @@ -0,0 +1,2 @@ +*.log +/run-test.mk diff --git a/tests/ecp5/add_sub.v b/tests/ecp5/add_sub.v new file mode 100644 index 000000000..177c32e30 --- /dev/null +++ b/tests/ecp5/add_sub.v @@ -0,0 +1,13 @@ +module top +( + input [3:0] x, + input [3:0] y, + + output [3:0] A, + output [3:0] B + ); + +assign A = x + y; +assign B = x - y; + +endmodule diff --git a/tests/ecp5/add_sub.ys b/tests/ecp5/add_sub.ys new file mode 100644 index 000000000..03aec6694 --- /dev/null +++ b/tests/ecp5/add_sub.ys @@ -0,0 +1,8 @@ +read_verilog add_sub.v +hierarchy -top top +equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 10 t:LUT4 +select -assert-none t:LUT4 %% t:* %D + diff --git a/tests/ecp5/adffs.v b/tests/ecp5/adffs.v new file mode 100644 index 000000000..93c8bf52c --- /dev/null +++ b/tests/ecp5/adffs.v @@ -0,0 +1,91 @@ +module adff + ( input d, clk, clr, output reg q ); + initial begin + q = 0; + end + always @( posedge clk, posedge clr ) + if ( clr ) + q <= 1'b0; + else + q <= d; +endmodule + +module adffn + ( input d, clk, clr, output reg q ); + initial begin + q = 0; + end + always @( posedge clk, negedge clr ) + if ( !clr ) + q <= 1'b0; + else + q <= d; +endmodule + +module dffsr + ( input d, clk, pre, clr, output reg q ); + initial begin + q = 0; + end + always @( posedge clk, posedge pre, posedge clr ) + if ( clr ) + q <= 1'b0; + else if ( pre ) + q <= 1'b1; + else + q <= d; +endmodule + +module ndffnsnr + ( input d, clk, pre, clr, output reg q ); + initial begin + q = 0; + end + always @( negedge clk, negedge pre, negedge clr ) + if ( !clr ) + q <= 1'b0; + else if ( !pre ) + q <= 1'b1; + else + q <= d; +endmodule + +module top ( +input clk, +input clr, +input pre, +input a, +output b,b1,b2,b3 +); + +dffsr u_dffsr ( + .clk (clk ), + .clr (clr), + .pre (pre), + .d (a ), + .q (b ) + ); + +ndffnsnr u_ndffnsnr ( + .clk (clk ), + .clr (clr), + .pre (pre), + .d (a ), + .q (b1 ) + ); + +adff u_adff ( + .clk (clk ), + .clr (clr), + .d (a ), + .q (b2 ) + ); + +adffn u_adffn ( + .clk (clk ), + .clr (clr), + .d (a ), + .q (b3 ) + ); + +endmodule diff --git a/tests/ecp5/adffs.ys b/tests/ecp5/adffs.ys new file mode 100644 index 000000000..5829fef5f --- /dev/null +++ b/tests/ecp5/adffs.ys @@ -0,0 +1,12 @@ +read_verilog adffs.v +proc +async2sync # converts async flops to a 'sync' variant clocked by a 'super'-clock +flatten +equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 1 t:DFF +select -assert-count 1 t:DFFN +select -assert-count 2 t:DFFSR +select -assert-count 7 t:LUT4 +select -assert-none t:DFF t:DFFN t:DFFSR t:LUT4 %% t:* %D diff --git a/tests/ecp5/common.v b/tests/ecp5/common.v new file mode 100644 index 000000000..5446f0817 --- /dev/null +++ b/tests/ecp5/common.v @@ -0,0 +1,47 @@ +module assert_dff(input clk, input test, input pat); + always @(posedge clk) + begin + #1; + if (test != pat) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time); + $stop; + end + end +endmodule + +module assert_tri(input en, input A, input B); + always @(posedge en) + begin + #1; + if (A !== B) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); + $stop; + end + end +endmodule + +module assert_Z(input clk, input A); + always @(posedge clk) + begin + #1; + if (A === 1'bZ) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A); + $stop; + end + end +endmodule + +module assert_comb(input A, input B); + always @(*) + begin + #1; + if (A !== B) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); + $stop; + end + end +endmodule diff --git a/tests/ecp5/dffs.v b/tests/ecp5/dffs.v new file mode 100644 index 000000000..d97840c43 --- /dev/null +++ b/tests/ecp5/dffs.v @@ -0,0 +1,37 @@ +module dff + ( input d, clk, output reg q ); + always @( posedge clk ) + q <= d; +endmodule + +module dffe + ( input d, clk, en, output reg q ); + initial begin + q = 0; + end + always @( posedge clk ) + if ( en ) + q <= d; +endmodule + +module top ( +input clk, +input en, +input a, +output b,b1, +); + +dff u_dff ( + .clk (clk ), + .d (a ), + .q (b ) + ); + +dffe u_ndffe ( + .clk (clk ), + .en (en), + .d (a ), + .q (b1 ) + ); + +endmodule diff --git a/tests/ecp5/dffs.ys b/tests/ecp5/dffs.ys new file mode 100644 index 000000000..07470c5ba --- /dev/null +++ b/tests/ecp5/dffs.ys @@ -0,0 +1,10 @@ +read_verilog dffs.v +hierarchy -top top +proc +flatten +equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 1 t:DFF +select -assert-count 1 t:DFFE +select -assert-none t:DFF t:DFFE %% t:* %D diff --git a/tests/ecp5/div_mod.v b/tests/ecp5/div_mod.v new file mode 100644 index 000000000..64a36707d --- /dev/null +++ b/tests/ecp5/div_mod.v @@ -0,0 +1,13 @@ +module top +( + input [3:0] x, + input [3:0] y, + + output [3:0] A, + output [3:0] B + ); + +assign A = x % y; +assign B = x / y; + +endmodule diff --git a/tests/ecp5/div_mod.ys b/tests/ecp5/div_mod.ys new file mode 100644 index 000000000..169c5978e --- /dev/null +++ b/tests/ecp5/div_mod.ys @@ -0,0 +1,12 @@ +read_verilog div_mod.v +hierarchy -top top +flatten +equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 28 t:CCU2C +select -assert-count 45 t:L6MUX21 +select -assert-count 183 t:LUT4 +select -assert-count 79 t:PFUMX +select -assert-none t:LUT4 t:CCU2C t:L6MUX21 t:PFUMX %% t:* %D diff --git a/tests/ecp5/dpram.v b/tests/ecp5/dpram.v new file mode 100644 index 000000000..2e69d6b3b --- /dev/null +++ b/tests/ecp5/dpram.v @@ -0,0 +1,20 @@ +module top (din, write_en, waddr, wclk, raddr, rclk, dout); +parameter addr_width = 8; +parameter data_width = 8; +input [addr_width-1:0] waddr, raddr; +input [data_width-1:0] din; +input write_en, wclk, rclk; +output [data_width-1:0] dout; +reg [data_width-1:0] dout; +reg [data_width-1:0] mem [(1< 6'h3E) + mem_init <= 1; + end + + always @(posedge clk) begin + //#3; + we_a <= !we_a; + end + + reg [7:0] mem [(1<<8)-1:0]; + + always @(posedge clk) // Write memory. + begin + if (we_a) + mem[addr_a] <= data_a; // Using write address bus. + end + always @(posedge clk) // Read memory. + begin + pq_a <= mem[addr_b]; // Using read address bus. + end + + top uut ( + .din(data_a), + .write_en(we_a), + .waddr(addr_a), + .wclk(clk), + .raddr(addr_b), + .rclk(clk), + .dout(q_a) + ); + + uut_mem_checker port_a_test(.clk(clk), .init(mem_init), .en(!we_a), .A(q_a), .B(pq_a)); + +endmodule + +module uut_mem_checker(input clk, input init, input en, input [7:0] A, input [7:0] B); + always @(posedge clk) + begin + #1; + if (en == 1 & init == 1 & A !== B) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); + $stop; + end + end +endmodule diff --git a/tests/ecp5/latches.v b/tests/ecp5/latches.v new file mode 100644 index 000000000..9dc43e4c2 --- /dev/null +++ b/tests/ecp5/latches.v @@ -0,0 +1,58 @@ +module latchp + ( input d, clk, en, output reg q ); + always @* + if ( en ) + q <= d; +endmodule + +module latchn + ( input d, clk, en, output reg q ); + always @* + if ( !en ) + q <= d; +endmodule + +module latchsr + ( input d, clk, en, clr, pre, output reg q ); + always @* + if ( clr ) + q <= 1'b0; + else if ( pre ) + q <= 1'b1; + else if ( en ) + q <= d; +endmodule + + +module top ( +input clk, +input clr, +input pre, +input a, +output b,b1,b2 +); + + +latchp u_latchp ( + .en (clk ), + .d (a ), + .q (b ) + ); + + +latchn u_latchn ( + .en (clk ), + .d (a ), + .q (b1 ) + ); + + +latchsr u_latchsr ( + .en (clk ), + .clr (clr), + .pre (pre), + .d (a ), + .q (b2 ) + ); + +endmodule diff --git a/tests/ecp5/latches.ys b/tests/ecp5/latches.ys new file mode 100644 index 000000000..2c77304a1 --- /dev/null +++ b/tests/ecp5/latches.ys @@ -0,0 +1,7 @@ +read_verilog latches.v +synth_ecp5 +cd top +select -assert-count 4 t:LUT4 +select -assert-count 1 t:PFUMX +select -assert-none t:LUT4 t:PFUMX %% t:* %D +write_verilog latches_synth.v diff --git a/tests/ecp5/latches_tb.v b/tests/ecp5/latches_tb.v new file mode 100644 index 000000000..b0585264b --- /dev/null +++ b/tests/ecp5/latches_tb.v @@ -0,0 +1,57 @@ +module testbench; + reg clk; + + initial begin + // $dumpfile("testbench.vcd"); + // $dumpvars(0, testbench); + + #5 clk = 0; + repeat (10000) begin + #5 clk = 1; + #5 clk = 0; + end + end + + + reg [2:0] dinA = 0; + wire doutB,doutB1,doutB2; + reg lat,latn,latsr = 0; + + top uut ( + .clk (clk ), + .a (dinA[0] ), + .pre (dinA[1] ), + .clr (dinA[2] ), + .b (doutB ), + .b1 (doutB1 ), + .b2 (doutB2 ) + ); + + always @(posedge clk) begin + #3; + dinA <= dinA + 1; + end + + always @* + if ( clk ) + lat <= dinA[0]; + + + always @* + if ( !clk ) + latn <= dinA[0]; + + + always @* + if ( dinA[2] ) + latsr <= 1'b0; + else if ( dinA[1] ) + latsr <= 1'b1; + else if ( clk ) + latsr <= dinA[0]; + + assert_dff lat_test(.clk(clk), .test(doutB), .pat(lat)); + assert_dff latn_test(.clk(clk), .test(doutB1), .pat(latn)); + assert_dff latsr_test(.clk(clk), .test(doutB2), .pat(latsr)); + +endmodule diff --git a/tests/ecp5/macc.v b/tests/ecp5/macc.v new file mode 100644 index 000000000..115f8ce42 --- /dev/null +++ b/tests/ecp5/macc.v @@ -0,0 +1,22 @@ +module top(clk,a,b,c,set); +parameter A_WIDTH = 4; +parameter B_WIDTH = 3; +input set; +input clk; +input signed [(A_WIDTH - 1):0] a; +input signed [(B_WIDTH - 1):0] b; +output signed [(A_WIDTH + B_WIDTH - 1):0] c; +reg [(A_WIDTH + B_WIDTH - 1):0] reg_tmp_c; +assign c = reg_tmp_c; +always @(posedge clk) +begin +if(set) +begin +reg_tmp_c <= 0; +end +else +begin +reg_tmp_c <= a * b + c; +end +end +endmodule diff --git a/tests/ecp5/macc.ys b/tests/ecp5/macc.ys new file mode 100644 index 000000000..530877727 --- /dev/null +++ b/tests/ecp5/macc.ys @@ -0,0 +1,10 @@ +read_verilog macc.v +proc +hierarchy -top top +equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 41 t:LUT4 +select -assert-count 6 t:CARRY +select -assert-count 7 t:DFFSR +select -assert-none t:LUT4 t:CARRY t:DFFSR %% t:* %D diff --git a/tests/ecp5/memory.v b/tests/ecp5/memory.v new file mode 100644 index 000000000..cb7753f7b --- /dev/null +++ b/tests/ecp5/memory.v @@ -0,0 +1,21 @@ +module top +( + input [7:0] data_a, + input [6:1] addr_a, + input we_a, clk, + output reg [7:0] q_a +); + // Declare the RAM variable + reg [7:0] ram[63:0]; + + // Port A + always @ (posedge clk) + begin + if (we_a) + begin + ram[addr_a] <= data_a; + q_a <= data_a; + end + q_a <= ram[addr_a]; + end +endmodule diff --git a/tests/ecp5/memory.ys b/tests/ecp5/memory.ys new file mode 100644 index 000000000..9fdeb0d16 --- /dev/null +++ b/tests/ecp5/memory.ys @@ -0,0 +1,22 @@ +read_verilog memory.v +hierarchy -top top +proc +memory -nomap +equiv_opt -run :prove -map +/ecp5/cells_sim.v synth_ecp5 +memory +opt -full + +# TODO +#equiv_opt -run prove: -assert null +miter -equiv -flatten -make_assert -make_outputs gold gate miter +#sat -verify -prove-asserts -tempinduct -show-inputs -show-outputs miter + +design -load postopt +cd top +select -assert-count 24 t:L6MUX21 +select -assert-count 71 t:LUT4 +select -assert-count 32 t:PFUMX +select -assert-count 8 t:TRELLIS_DPR16X4 +select -assert-count 35 t:TRELLIS_FF +select -assert-none t:L6MUX21 t:LUT4 t:PFUMX t:TRELLIS_DPR16X4 t:TRELLIS_FF %% t:* %D +write_verilog memory_synth.v diff --git a/tests/ecp5/memory_tb.v b/tests/ecp5/memory_tb.v new file mode 100644 index 000000000..be69374eb --- /dev/null +++ b/tests/ecp5/memory_tb.v @@ -0,0 +1,79 @@ +module testbench; + reg clk; + + initial begin + // $dumpfile("testbench.vcd"); + // $dumpvars(0, testbench); + + #5 clk = 0; + repeat (10000) begin + #5 clk = 1; + #5 clk = 0; + end + end + + + reg [7:0] data_a = 0; + reg [5:0] addr_a = 0; + reg we_a = 0; + reg re_a = 1; + wire [7:0] q_a; + reg mem_init = 0; + + reg [7:0] pq_a; + + top uut ( + .data_a(data_a), + .addr_a(addr_a), + .we_a(we_a), + .clk(clk), + .q_a(q_a) + ); + + always @(posedge clk) begin + #3; + data_a <= data_a + 17; + + addr_a <= addr_a + 1; + end + + always @(posedge addr_a) begin + #10; + if(addr_a > 6'h3E) + mem_init <= 1; + end + + always @(posedge clk) begin + //#3; + we_a <= !we_a; + end + + // Declare the RAM variable for check + reg [7:0] ram[63:0]; + + // Port A for check + always @ (posedge clk) + begin + if (we_a) + begin + ram[addr_a] <= data_a; + pq_a <= data_a; + end + pq_a <= ram[addr_a]; + end + + uut_mem_checker port_a_test(.clk(clk), .init(mem_init), .en(!we_a), .A(q_a), .B(pq_a)); + +endmodule + +module uut_mem_checker(input clk, input init, input en, input [7:0] A, input [7:0] B); + always @(posedge clk) + begin + #1; + if (en == 1 & init == 1 & A !== B) + begin + $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); + $stop; + end + end +endmodule diff --git a/tests/ecp5/mul.v b/tests/ecp5/mul.v new file mode 100644 index 000000000..d5b48b1d7 --- /dev/null +++ b/tests/ecp5/mul.v @@ -0,0 +1,11 @@ +module top +( + input [5:0] x, + input [5:0] y, + + output [11:0] A, + ); + +assign A = x * y; + +endmodule diff --git a/tests/ecp5/mul.ys b/tests/ecp5/mul.ys new file mode 100644 index 000000000..0e8d6908f --- /dev/null +++ b/tests/ecp5/mul.ys @@ -0,0 +1,11 @@ +read_verilog mul.v +hierarchy -top top +equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 6 t:CCU2C +select -assert-count 46 t:L6MUX21 +select -assert-count 169 t:LUT4 +select -assert-count 72 t:PFUMX + +select -assert-none t:CCU2C t:L6MUX21 t:LUT4 t:PFUMX %% t:* %D diff --git a/tests/ecp5/mux.v b/tests/ecp5/mux.v new file mode 100644 index 000000000..0814b733e --- /dev/null +++ b/tests/ecp5/mux.v @@ -0,0 +1,100 @@ +module mux2 (S,A,B,Y); + input S; + input A,B; + output reg Y; + + always @(*) + Y = (S)? B : A; +endmodule + +module mux4 ( S, D, Y ); + +input[1:0] S; +input[3:0] D; +output Y; + +reg Y; +wire[1:0] S; +wire[3:0] D; + +always @* +begin + case( S ) + 0 : Y = D[0]; + 1 : Y = D[1]; + 2 : Y = D[2]; + 3 : Y = D[3]; + endcase +end + +endmodule + +module mux8 ( S, D, Y ); + +input[2:0] S; +input[7:0] D; +output Y; + +reg Y; +wire[2:0] S; +wire[7:0] D; + +always @* +begin + case( S ) + 0 : Y = D[0]; + 1 : Y = D[1]; + 2 : Y = D[2]; + 3 : Y = D[3]; + 4 : Y = D[4]; + 5 : Y = D[5]; + 6 : Y = D[6]; + 7 : Y = D[7]; + endcase +end + +endmodule + +module mux16 (D, S, Y); + input [15:0] D; + input [3:0] S; + output Y; + +assign Y = D[S]; + +endmodule + + +module top ( +input [3:0] S, +input [15:0] D, +output M2,M4,M8,M16 +); + +mux2 u_mux2 ( + .S (S[0]), + .A (D[0]), + .B (D[1]), + .Y (M2) + ); + + +mux4 u_mux4 ( + .S (S[1:0]), + .D (D[3:0]), + .Y (M4) + ); + +mux8 u_mux8 ( + .S (S[2:0]), + .D (D[7:0]), + .Y (M8) + ); + +mux16 u_mux16 ( + .S (S[3:0]), + .D (D[15:0]), + .Y (M16) + ); + +endmodule diff --git a/tests/ecp5/mux.ys b/tests/ecp5/mux.ys new file mode 100644 index 000000000..47a965dd3 --- /dev/null +++ b/tests/ecp5/mux.ys @@ -0,0 +1,11 @@ +read_verilog mux.v +proc +flatten +equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 30 t:LUT4 +select -assert-count 7 t:L6MUX21 +select -assert-count 12 t:PFUMX + +select -assert-none t:LUT4 t:L6MUX21 t:PFUMX %% t:* %D diff --git a/tests/ecp5/rom.v b/tests/ecp5/rom.v new file mode 100644 index 000000000..c31ca3b2b --- /dev/null +++ b/tests/ecp5/rom.v @@ -0,0 +1,15 @@ +module top(data, addr); +output [3:0] data; +input [4:0] addr; +always @(addr) begin +case (addr) +0 : data = 'h4; +1 : data = 'h9; +2 : data = 'h1; +15 : data = 'h8; +16 : data = 'h1; +17 : data = 'h0; +default : data = 'h0; +endcase +end +endmodule diff --git a/tests/ecp5/rom.ys b/tests/ecp5/rom.ys new file mode 100644 index 000000000..8a52749a1 --- /dev/null +++ b/tests/ecp5/rom.ys @@ -0,0 +1,9 @@ +read_verilog rom.v +proc +flatten +equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 6 t:LUT4 +select -assert-count 3 t:PFUMX +select -assert-none t:LUT4 t:PFUMX %% t:* %D diff --git a/tests/ecp5/run-test.sh b/tests/ecp5/run-test.sh new file mode 100755 index 000000000..22c495784 --- /dev/null +++ b/tests/ecp5/run-test.sh @@ -0,0 +1,33 @@ +set -e +if [ -f "../../techlibs/common/simcells.v" ]; then + COMMON_PREFIX=../../techlibs/common + TECHLIBS_PREFIX=../../techlibs +else + COMMON_PREFIX=/usr/local/share/yosys + TECHLIBS_PREFIX=/usr/local/share/yosys +fi +{ +echo "all::" +for x in *.ys; do + echo "all:: run-$x" + echo "run-$x:" + echo " @echo 'Running $x..'" + echo " @../../yosys -ql ${x%.ys}.log $x -w 'Yosys has only limited support for tri-state logic at the moment.'" +done +for t in *_tb.v; do + echo "all:: run-$t" + echo "run-$t: ${t%_tb.v}_synth.v" + echo " @echo 'Running $t..'" + echo " @iverilog -o ${t%_tb.v}_testbench $t ${t%_tb.v}_synth.v common.v $TECHLIBS_PREFIX/ecp5/cells_sim.v" + echo " @vvp -N ${t%_tb.v}_testbench" +done +for s in *.sh; do + if [ "$s" != "run-test.sh" ]; then + echo "all:: run-$s" + echo "run-$s:" + echo " @echo 'Running $s..'" + echo " @bash $s" + fi +done +} > run-test.mk +exec ${MAKE:-make} -f run-test.mk diff --git a/tests/ecp5/tribuf.v b/tests/ecp5/tribuf.v new file mode 100644 index 000000000..870a02584 --- /dev/null +++ b/tests/ecp5/tribuf.v @@ -0,0 +1,23 @@ +module tristate (en, i, o); + input en; + input i; + output o; + + assign o = en ? i : 1'bz; + +endmodule + + +module top ( +input en, +input a, +output b +); + +tristate u_tri ( + .en (en ), + .i (a ), + .o (b ) + ); + +endmodule diff --git a/tests/ecp5/tribuf.ys b/tests/ecp5/tribuf.ys new file mode 100644 index 000000000..f454a0c02 --- /dev/null +++ b/tests/ecp5/tribuf.ys @@ -0,0 +1,9 @@ +read_verilog tribuf.v +hierarchy -top top +proc +flatten +equiv_opt -assert -map +/ecp5/cells_sim.v -map +/simcells.v synth_ecp5 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 1 t:$_TBUF_ +select -assert-none t:$_TBUF_ %% t:* %D From fe58790f3789a79b867660031d7e3e28cb3fff20 Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Wed, 28 Aug 2019 09:49:58 +0300 Subject: [PATCH 094/130] Revert "Add tests for ecp5" This reverts commit 2270ead09fb4695442c66fe5c06445235f390f2b. --- Makefile | 1 - tests/ecp5/.gitignore | 2 - tests/ecp5/add_sub.v | 13 ------ tests/ecp5/add_sub.ys | 8 ---- tests/ecp5/adffs.v | 91 ------------------------------------ tests/ecp5/adffs.ys | 12 ----- tests/ecp5/common.v | 47 ------------------- tests/ecp5/dffs.v | 37 --------------- tests/ecp5/dffs.ys | 10 ---- tests/ecp5/div_mod.v | 13 ------ tests/ecp5/div_mod.ys | 12 ----- tests/ecp5/dpram.v | 20 -------- tests/ecp5/dpram.ys | 18 -------- tests/ecp5/dpram_tb.v | 81 -------------------------------- tests/ecp5/latches.v | 58 ----------------------- tests/ecp5/latches.ys | 7 --- tests/ecp5/latches_tb.v | 57 ----------------------- tests/ecp5/macc.v | 22 --------- tests/ecp5/macc.ys | 10 ---- tests/ecp5/memory.v | 21 --------- tests/ecp5/memory.ys | 22 --------- tests/ecp5/memory_tb.v | 79 ------------------------------- tests/ecp5/mul.v | 11 ----- tests/ecp5/mul.ys | 11 ----- tests/ecp5/mux.v | 100 ---------------------------------------- tests/ecp5/mux.ys | 11 ----- tests/ecp5/rom.v | 15 ------ tests/ecp5/rom.ys | 9 ---- tests/ecp5/run-test.sh | 33 ------------- tests/ecp5/tribuf.v | 23 --------- tests/ecp5/tribuf.ys | 9 ---- 31 files changed, 863 deletions(-) delete mode 100644 tests/ecp5/.gitignore delete mode 100644 tests/ecp5/add_sub.v delete mode 100644 tests/ecp5/add_sub.ys delete mode 100644 tests/ecp5/adffs.v delete mode 100644 tests/ecp5/adffs.ys delete mode 100644 tests/ecp5/common.v delete mode 100644 tests/ecp5/dffs.v delete mode 100644 tests/ecp5/dffs.ys delete mode 100644 tests/ecp5/div_mod.v delete mode 100644 tests/ecp5/div_mod.ys delete mode 100644 tests/ecp5/dpram.v delete mode 100644 tests/ecp5/dpram.ys delete mode 100644 tests/ecp5/dpram_tb.v delete mode 100644 tests/ecp5/latches.v delete mode 100644 tests/ecp5/latches.ys delete mode 100644 tests/ecp5/latches_tb.v delete mode 100644 tests/ecp5/macc.v delete mode 100644 tests/ecp5/macc.ys delete mode 100644 tests/ecp5/memory.v delete mode 100644 tests/ecp5/memory.ys delete mode 100644 tests/ecp5/memory_tb.v delete mode 100644 tests/ecp5/mul.v delete mode 100644 tests/ecp5/mul.ys delete mode 100644 tests/ecp5/mux.v delete mode 100644 tests/ecp5/mux.ys delete mode 100644 tests/ecp5/rom.v delete mode 100644 tests/ecp5/rom.ys delete mode 100755 tests/ecp5/run-test.sh delete mode 100644 tests/ecp5/tribuf.v delete mode 100644 tests/ecp5/tribuf.ys diff --git a/Makefile b/Makefile index d94ab2465..9cfa6a0de 100644 --- a/Makefile +++ b/Makefile @@ -700,7 +700,6 @@ test: $(TARGETS) $(EXTRA_TARGETS) +cd tests/aiger && bash run-test.sh $(ABCOPT) +cd tests/arch && bash run-test.sh +cd tests/ice40 && bash run-test.sh $(SEEDOPT) - +cd tests/ecp5 && bash run-test.sh $(SEEDOPT) @echo "" @echo " Passed \"make test\"." @echo "" diff --git a/tests/ecp5/.gitignore b/tests/ecp5/.gitignore deleted file mode 100644 index 1d329c933..000000000 --- a/tests/ecp5/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.log -/run-test.mk diff --git a/tests/ecp5/add_sub.v b/tests/ecp5/add_sub.v deleted file mode 100644 index 177c32e30..000000000 --- a/tests/ecp5/add_sub.v +++ /dev/null @@ -1,13 +0,0 @@ -module top -( - input [3:0] x, - input [3:0] y, - - output [3:0] A, - output [3:0] B - ); - -assign A = x + y; -assign B = x - y; - -endmodule diff --git a/tests/ecp5/add_sub.ys b/tests/ecp5/add_sub.ys deleted file mode 100644 index 03aec6694..000000000 --- a/tests/ecp5/add_sub.ys +++ /dev/null @@ -1,8 +0,0 @@ -read_verilog add_sub.v -hierarchy -top top -equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -select -assert-count 10 t:LUT4 -select -assert-none t:LUT4 %% t:* %D - diff --git a/tests/ecp5/adffs.v b/tests/ecp5/adffs.v deleted file mode 100644 index 93c8bf52c..000000000 --- a/tests/ecp5/adffs.v +++ /dev/null @@ -1,91 +0,0 @@ -module adff - ( input d, clk, clr, output reg q ); - initial begin - q = 0; - end - always @( posedge clk, posedge clr ) - if ( clr ) - q <= 1'b0; - else - q <= d; -endmodule - -module adffn - ( input d, clk, clr, output reg q ); - initial begin - q = 0; - end - always @( posedge clk, negedge clr ) - if ( !clr ) - q <= 1'b0; - else - q <= d; -endmodule - -module dffsr - ( input d, clk, pre, clr, output reg q ); - initial begin - q = 0; - end - always @( posedge clk, posedge pre, posedge clr ) - if ( clr ) - q <= 1'b0; - else if ( pre ) - q <= 1'b1; - else - q <= d; -endmodule - -module ndffnsnr - ( input d, clk, pre, clr, output reg q ); - initial begin - q = 0; - end - always @( negedge clk, negedge pre, negedge clr ) - if ( !clr ) - q <= 1'b0; - else if ( !pre ) - q <= 1'b1; - else - q <= d; -endmodule - -module top ( -input clk, -input clr, -input pre, -input a, -output b,b1,b2,b3 -); - -dffsr u_dffsr ( - .clk (clk ), - .clr (clr), - .pre (pre), - .d (a ), - .q (b ) - ); - -ndffnsnr u_ndffnsnr ( - .clk (clk ), - .clr (clr), - .pre (pre), - .d (a ), - .q (b1 ) - ); - -adff u_adff ( - .clk (clk ), - .clr (clr), - .d (a ), - .q (b2 ) - ); - -adffn u_adffn ( - .clk (clk ), - .clr (clr), - .d (a ), - .q (b3 ) - ); - -endmodule diff --git a/tests/ecp5/adffs.ys b/tests/ecp5/adffs.ys deleted file mode 100644 index 5829fef5f..000000000 --- a/tests/ecp5/adffs.ys +++ /dev/null @@ -1,12 +0,0 @@ -read_verilog adffs.v -proc -async2sync # converts async flops to a 'sync' variant clocked by a 'super'-clock -flatten -equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -select -assert-count 1 t:DFF -select -assert-count 1 t:DFFN -select -assert-count 2 t:DFFSR -select -assert-count 7 t:LUT4 -select -assert-none t:DFF t:DFFN t:DFFSR t:LUT4 %% t:* %D diff --git a/tests/ecp5/common.v b/tests/ecp5/common.v deleted file mode 100644 index 5446f0817..000000000 --- a/tests/ecp5/common.v +++ /dev/null @@ -1,47 +0,0 @@ -module assert_dff(input clk, input test, input pat); - always @(posedge clk) - begin - #1; - if (test != pat) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time); - $stop; - end - end -endmodule - -module assert_tri(input en, input A, input B); - always @(posedge en) - begin - #1; - if (A !== B) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); - $stop; - end - end -endmodule - -module assert_Z(input clk, input A); - always @(posedge clk) - begin - #1; - if (A === 1'bZ) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A); - $stop; - end - end -endmodule - -module assert_comb(input A, input B); - always @(*) - begin - #1; - if (A !== B) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); - $stop; - end - end -endmodule diff --git a/tests/ecp5/dffs.v b/tests/ecp5/dffs.v deleted file mode 100644 index d97840c43..000000000 --- a/tests/ecp5/dffs.v +++ /dev/null @@ -1,37 +0,0 @@ -module dff - ( input d, clk, output reg q ); - always @( posedge clk ) - q <= d; -endmodule - -module dffe - ( input d, clk, en, output reg q ); - initial begin - q = 0; - end - always @( posedge clk ) - if ( en ) - q <= d; -endmodule - -module top ( -input clk, -input en, -input a, -output b,b1, -); - -dff u_dff ( - .clk (clk ), - .d (a ), - .q (b ) - ); - -dffe u_ndffe ( - .clk (clk ), - .en (en), - .d (a ), - .q (b1 ) - ); - -endmodule diff --git a/tests/ecp5/dffs.ys b/tests/ecp5/dffs.ys deleted file mode 100644 index 07470c5ba..000000000 --- a/tests/ecp5/dffs.ys +++ /dev/null @@ -1,10 +0,0 @@ -read_verilog dffs.v -hierarchy -top top -proc -flatten -equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -select -assert-count 1 t:DFF -select -assert-count 1 t:DFFE -select -assert-none t:DFF t:DFFE %% t:* %D diff --git a/tests/ecp5/div_mod.v b/tests/ecp5/div_mod.v deleted file mode 100644 index 64a36707d..000000000 --- a/tests/ecp5/div_mod.v +++ /dev/null @@ -1,13 +0,0 @@ -module top -( - input [3:0] x, - input [3:0] y, - - output [3:0] A, - output [3:0] B - ); - -assign A = x % y; -assign B = x / y; - -endmodule diff --git a/tests/ecp5/div_mod.ys b/tests/ecp5/div_mod.ys deleted file mode 100644 index 169c5978e..000000000 --- a/tests/ecp5/div_mod.ys +++ /dev/null @@ -1,12 +0,0 @@ -read_verilog div_mod.v -hierarchy -top top -flatten -equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module - -select -assert-count 28 t:CCU2C -select -assert-count 45 t:L6MUX21 -select -assert-count 183 t:LUT4 -select -assert-count 79 t:PFUMX -select -assert-none t:LUT4 t:CCU2C t:L6MUX21 t:PFUMX %% t:* %D diff --git a/tests/ecp5/dpram.v b/tests/ecp5/dpram.v deleted file mode 100644 index 2e69d6b3b..000000000 --- a/tests/ecp5/dpram.v +++ /dev/null @@ -1,20 +0,0 @@ -module top (din, write_en, waddr, wclk, raddr, rclk, dout); -parameter addr_width = 8; -parameter data_width = 8; -input [addr_width-1:0] waddr, raddr; -input [data_width-1:0] din; -input write_en, wclk, rclk; -output [data_width-1:0] dout; -reg [data_width-1:0] dout; -reg [data_width-1:0] mem [(1< 6'h3E) - mem_init <= 1; - end - - always @(posedge clk) begin - //#3; - we_a <= !we_a; - end - - reg [7:0] mem [(1<<8)-1:0]; - - always @(posedge clk) // Write memory. - begin - if (we_a) - mem[addr_a] <= data_a; // Using write address bus. - end - always @(posedge clk) // Read memory. - begin - pq_a <= mem[addr_b]; // Using read address bus. - end - - top uut ( - .din(data_a), - .write_en(we_a), - .waddr(addr_a), - .wclk(clk), - .raddr(addr_b), - .rclk(clk), - .dout(q_a) - ); - - uut_mem_checker port_a_test(.clk(clk), .init(mem_init), .en(!we_a), .A(q_a), .B(pq_a)); - -endmodule - -module uut_mem_checker(input clk, input init, input en, input [7:0] A, input [7:0] B); - always @(posedge clk) - begin - #1; - if (en == 1 & init == 1 & A !== B) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); - $stop; - end - end -endmodule diff --git a/tests/ecp5/latches.v b/tests/ecp5/latches.v deleted file mode 100644 index 9dc43e4c2..000000000 --- a/tests/ecp5/latches.v +++ /dev/null @@ -1,58 +0,0 @@ -module latchp - ( input d, clk, en, output reg q ); - always @* - if ( en ) - q <= d; -endmodule - -module latchn - ( input d, clk, en, output reg q ); - always @* - if ( !en ) - q <= d; -endmodule - -module latchsr - ( input d, clk, en, clr, pre, output reg q ); - always @* - if ( clr ) - q <= 1'b0; - else if ( pre ) - q <= 1'b1; - else if ( en ) - q <= d; -endmodule - - -module top ( -input clk, -input clr, -input pre, -input a, -output b,b1,b2 -); - - -latchp u_latchp ( - .en (clk ), - .d (a ), - .q (b ) - ); - - -latchn u_latchn ( - .en (clk ), - .d (a ), - .q (b1 ) - ); - - -latchsr u_latchsr ( - .en (clk ), - .clr (clr), - .pre (pre), - .d (a ), - .q (b2 ) - ); - -endmodule diff --git a/tests/ecp5/latches.ys b/tests/ecp5/latches.ys deleted file mode 100644 index 2c77304a1..000000000 --- a/tests/ecp5/latches.ys +++ /dev/null @@ -1,7 +0,0 @@ -read_verilog latches.v -synth_ecp5 -cd top -select -assert-count 4 t:LUT4 -select -assert-count 1 t:PFUMX -select -assert-none t:LUT4 t:PFUMX %% t:* %D -write_verilog latches_synth.v diff --git a/tests/ecp5/latches_tb.v b/tests/ecp5/latches_tb.v deleted file mode 100644 index b0585264b..000000000 --- a/tests/ecp5/latches_tb.v +++ /dev/null @@ -1,57 +0,0 @@ -module testbench; - reg clk; - - initial begin - // $dumpfile("testbench.vcd"); - // $dumpvars(0, testbench); - - #5 clk = 0; - repeat (10000) begin - #5 clk = 1; - #5 clk = 0; - end - end - - - reg [2:0] dinA = 0; - wire doutB,doutB1,doutB2; - reg lat,latn,latsr = 0; - - top uut ( - .clk (clk ), - .a (dinA[0] ), - .pre (dinA[1] ), - .clr (dinA[2] ), - .b (doutB ), - .b1 (doutB1 ), - .b2 (doutB2 ) - ); - - always @(posedge clk) begin - #3; - dinA <= dinA + 1; - end - - always @* - if ( clk ) - lat <= dinA[0]; - - - always @* - if ( !clk ) - latn <= dinA[0]; - - - always @* - if ( dinA[2] ) - latsr <= 1'b0; - else if ( dinA[1] ) - latsr <= 1'b1; - else if ( clk ) - latsr <= dinA[0]; - - assert_dff lat_test(.clk(clk), .test(doutB), .pat(lat)); - assert_dff latn_test(.clk(clk), .test(doutB1), .pat(latn)); - assert_dff latsr_test(.clk(clk), .test(doutB2), .pat(latsr)); - -endmodule diff --git a/tests/ecp5/macc.v b/tests/ecp5/macc.v deleted file mode 100644 index 115f8ce42..000000000 --- a/tests/ecp5/macc.v +++ /dev/null @@ -1,22 +0,0 @@ -module top(clk,a,b,c,set); -parameter A_WIDTH = 4; -parameter B_WIDTH = 3; -input set; -input clk; -input signed [(A_WIDTH - 1):0] a; -input signed [(B_WIDTH - 1):0] b; -output signed [(A_WIDTH + B_WIDTH - 1):0] c; -reg [(A_WIDTH + B_WIDTH - 1):0] reg_tmp_c; -assign c = reg_tmp_c; -always @(posedge clk) -begin -if(set) -begin -reg_tmp_c <= 0; -end -else -begin -reg_tmp_c <= a * b + c; -end -end -endmodule diff --git a/tests/ecp5/macc.ys b/tests/ecp5/macc.ys deleted file mode 100644 index 530877727..000000000 --- a/tests/ecp5/macc.ys +++ /dev/null @@ -1,10 +0,0 @@ -read_verilog macc.v -proc -hierarchy -top top -equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -select -assert-count 41 t:LUT4 -select -assert-count 6 t:CARRY -select -assert-count 7 t:DFFSR -select -assert-none t:LUT4 t:CARRY t:DFFSR %% t:* %D diff --git a/tests/ecp5/memory.v b/tests/ecp5/memory.v deleted file mode 100644 index cb7753f7b..000000000 --- a/tests/ecp5/memory.v +++ /dev/null @@ -1,21 +0,0 @@ -module top -( - input [7:0] data_a, - input [6:1] addr_a, - input we_a, clk, - output reg [7:0] q_a -); - // Declare the RAM variable - reg [7:0] ram[63:0]; - - // Port A - always @ (posedge clk) - begin - if (we_a) - begin - ram[addr_a] <= data_a; - q_a <= data_a; - end - q_a <= ram[addr_a]; - end -endmodule diff --git a/tests/ecp5/memory.ys b/tests/ecp5/memory.ys deleted file mode 100644 index 9fdeb0d16..000000000 --- a/tests/ecp5/memory.ys +++ /dev/null @@ -1,22 +0,0 @@ -read_verilog memory.v -hierarchy -top top -proc -memory -nomap -equiv_opt -run :prove -map +/ecp5/cells_sim.v synth_ecp5 -memory -opt -full - -# TODO -#equiv_opt -run prove: -assert null -miter -equiv -flatten -make_assert -make_outputs gold gate miter -#sat -verify -prove-asserts -tempinduct -show-inputs -show-outputs miter - -design -load postopt -cd top -select -assert-count 24 t:L6MUX21 -select -assert-count 71 t:LUT4 -select -assert-count 32 t:PFUMX -select -assert-count 8 t:TRELLIS_DPR16X4 -select -assert-count 35 t:TRELLIS_FF -select -assert-none t:L6MUX21 t:LUT4 t:PFUMX t:TRELLIS_DPR16X4 t:TRELLIS_FF %% t:* %D -write_verilog memory_synth.v diff --git a/tests/ecp5/memory_tb.v b/tests/ecp5/memory_tb.v deleted file mode 100644 index be69374eb..000000000 --- a/tests/ecp5/memory_tb.v +++ /dev/null @@ -1,79 +0,0 @@ -module testbench; - reg clk; - - initial begin - // $dumpfile("testbench.vcd"); - // $dumpvars(0, testbench); - - #5 clk = 0; - repeat (10000) begin - #5 clk = 1; - #5 clk = 0; - end - end - - - reg [7:0] data_a = 0; - reg [5:0] addr_a = 0; - reg we_a = 0; - reg re_a = 1; - wire [7:0] q_a; - reg mem_init = 0; - - reg [7:0] pq_a; - - top uut ( - .data_a(data_a), - .addr_a(addr_a), - .we_a(we_a), - .clk(clk), - .q_a(q_a) - ); - - always @(posedge clk) begin - #3; - data_a <= data_a + 17; - - addr_a <= addr_a + 1; - end - - always @(posedge addr_a) begin - #10; - if(addr_a > 6'h3E) - mem_init <= 1; - end - - always @(posedge clk) begin - //#3; - we_a <= !we_a; - end - - // Declare the RAM variable for check - reg [7:0] ram[63:0]; - - // Port A for check - always @ (posedge clk) - begin - if (we_a) - begin - ram[addr_a] <= data_a; - pq_a <= data_a; - end - pq_a <= ram[addr_a]; - end - - uut_mem_checker port_a_test(.clk(clk), .init(mem_init), .en(!we_a), .A(q_a), .B(pq_a)); - -endmodule - -module uut_mem_checker(input clk, input init, input en, input [7:0] A, input [7:0] B); - always @(posedge clk) - begin - #1; - if (en == 1 & init == 1 & A !== B) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); - $stop; - end - end -endmodule diff --git a/tests/ecp5/mul.v b/tests/ecp5/mul.v deleted file mode 100644 index d5b48b1d7..000000000 --- a/tests/ecp5/mul.v +++ /dev/null @@ -1,11 +0,0 @@ -module top -( - input [5:0] x, - input [5:0] y, - - output [11:0] A, - ); - -assign A = x * y; - -endmodule diff --git a/tests/ecp5/mul.ys b/tests/ecp5/mul.ys deleted file mode 100644 index 0e8d6908f..000000000 --- a/tests/ecp5/mul.ys +++ /dev/null @@ -1,11 +0,0 @@ -read_verilog mul.v -hierarchy -top top -equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -select -assert-count 6 t:CCU2C -select -assert-count 46 t:L6MUX21 -select -assert-count 169 t:LUT4 -select -assert-count 72 t:PFUMX - -select -assert-none t:CCU2C t:L6MUX21 t:LUT4 t:PFUMX %% t:* %D diff --git a/tests/ecp5/mux.v b/tests/ecp5/mux.v deleted file mode 100644 index 0814b733e..000000000 --- a/tests/ecp5/mux.v +++ /dev/null @@ -1,100 +0,0 @@ -module mux2 (S,A,B,Y); - input S; - input A,B; - output reg Y; - - always @(*) - Y = (S)? B : A; -endmodule - -module mux4 ( S, D, Y ); - -input[1:0] S; -input[3:0] D; -output Y; - -reg Y; -wire[1:0] S; -wire[3:0] D; - -always @* -begin - case( S ) - 0 : Y = D[0]; - 1 : Y = D[1]; - 2 : Y = D[2]; - 3 : Y = D[3]; - endcase -end - -endmodule - -module mux8 ( S, D, Y ); - -input[2:0] S; -input[7:0] D; -output Y; - -reg Y; -wire[2:0] S; -wire[7:0] D; - -always @* -begin - case( S ) - 0 : Y = D[0]; - 1 : Y = D[1]; - 2 : Y = D[2]; - 3 : Y = D[3]; - 4 : Y = D[4]; - 5 : Y = D[5]; - 6 : Y = D[6]; - 7 : Y = D[7]; - endcase -end - -endmodule - -module mux16 (D, S, Y); - input [15:0] D; - input [3:0] S; - output Y; - -assign Y = D[S]; - -endmodule - - -module top ( -input [3:0] S, -input [15:0] D, -output M2,M4,M8,M16 -); - -mux2 u_mux2 ( - .S (S[0]), - .A (D[0]), - .B (D[1]), - .Y (M2) - ); - - -mux4 u_mux4 ( - .S (S[1:0]), - .D (D[3:0]), - .Y (M4) - ); - -mux8 u_mux8 ( - .S (S[2:0]), - .D (D[7:0]), - .Y (M8) - ); - -mux16 u_mux16 ( - .S (S[3:0]), - .D (D[15:0]), - .Y (M16) - ); - -endmodule diff --git a/tests/ecp5/mux.ys b/tests/ecp5/mux.ys deleted file mode 100644 index 47a965dd3..000000000 --- a/tests/ecp5/mux.ys +++ /dev/null @@ -1,11 +0,0 @@ -read_verilog mux.v -proc -flatten -equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -select -assert-count 30 t:LUT4 -select -assert-count 7 t:L6MUX21 -select -assert-count 12 t:PFUMX - -select -assert-none t:LUT4 t:L6MUX21 t:PFUMX %% t:* %D diff --git a/tests/ecp5/rom.v b/tests/ecp5/rom.v deleted file mode 100644 index c31ca3b2b..000000000 --- a/tests/ecp5/rom.v +++ /dev/null @@ -1,15 +0,0 @@ -module top(data, addr); -output [3:0] data; -input [4:0] addr; -always @(addr) begin -case (addr) -0 : data = 'h4; -1 : data = 'h9; -2 : data = 'h1; -15 : data = 'h8; -16 : data = 'h1; -17 : data = 'h0; -default : data = 'h0; -endcase -end -endmodule diff --git a/tests/ecp5/rom.ys b/tests/ecp5/rom.ys deleted file mode 100644 index 8a52749a1..000000000 --- a/tests/ecp5/rom.ys +++ /dev/null @@ -1,9 +0,0 @@ -read_verilog rom.v -proc -flatten -equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -select -assert-count 6 t:LUT4 -select -assert-count 3 t:PFUMX -select -assert-none t:LUT4 t:PFUMX %% t:* %D diff --git a/tests/ecp5/run-test.sh b/tests/ecp5/run-test.sh deleted file mode 100755 index 22c495784..000000000 --- a/tests/ecp5/run-test.sh +++ /dev/null @@ -1,33 +0,0 @@ -set -e -if [ -f "../../techlibs/common/simcells.v" ]; then - COMMON_PREFIX=../../techlibs/common - TECHLIBS_PREFIX=../../techlibs -else - COMMON_PREFIX=/usr/local/share/yosys - TECHLIBS_PREFIX=/usr/local/share/yosys -fi -{ -echo "all::" -for x in *.ys; do - echo "all:: run-$x" - echo "run-$x:" - echo " @echo 'Running $x..'" - echo " @../../yosys -ql ${x%.ys}.log $x -w 'Yosys has only limited support for tri-state logic at the moment.'" -done -for t in *_tb.v; do - echo "all:: run-$t" - echo "run-$t: ${t%_tb.v}_synth.v" - echo " @echo 'Running $t..'" - echo " @iverilog -o ${t%_tb.v}_testbench $t ${t%_tb.v}_synth.v common.v $TECHLIBS_PREFIX/ecp5/cells_sim.v" - echo " @vvp -N ${t%_tb.v}_testbench" -done -for s in *.sh; do - if [ "$s" != "run-test.sh" ]; then - echo "all:: run-$s" - echo "run-$s:" - echo " @echo 'Running $s..'" - echo " @bash $s" - fi -done -} > run-test.mk -exec ${MAKE:-make} -f run-test.mk diff --git a/tests/ecp5/tribuf.v b/tests/ecp5/tribuf.v deleted file mode 100644 index 870a02584..000000000 --- a/tests/ecp5/tribuf.v +++ /dev/null @@ -1,23 +0,0 @@ -module tristate (en, i, o); - input en; - input i; - output o; - - assign o = en ? i : 1'bz; - -endmodule - - -module top ( -input en, -input a, -output b -); - -tristate u_tri ( - .en (en ), - .i (a ), - .o (b ) - ); - -endmodule diff --git a/tests/ecp5/tribuf.ys b/tests/ecp5/tribuf.ys deleted file mode 100644 index f454a0c02..000000000 --- a/tests/ecp5/tribuf.ys +++ /dev/null @@ -1,9 +0,0 @@ -read_verilog tribuf.v -hierarchy -top top -proc -flatten -equiv_opt -assert -map +/ecp5/cells_sim.v -map +/simcells.v synth_ecp5 # equivalency check -design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) -cd top # Constrain all select calls below inside the top module -select -assert-count 1 t:$_TBUF_ -select -assert-none t:$_TBUF_ %% t:* %D From 975aaf190f0bbbeacc253397ccada6889c69e8f7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 28 Aug 2019 09:24:19 -0700 Subject: [PATCH 095/130] Add xilinx_srl test --- tests/xilinx/run-test.sh | 20 ++++++++++++ tests/xilinx/xilinx_srl.v | 40 +++++++++++++++++++++++ tests/xilinx/xilinx_srl.ys | 67 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100755 tests/xilinx/run-test.sh create mode 100644 tests/xilinx/xilinx_srl.v create mode 100644 tests/xilinx/xilinx_srl.ys diff --git a/tests/xilinx/run-test.sh b/tests/xilinx/run-test.sh new file mode 100755 index 000000000..ea56b70f0 --- /dev/null +++ b/tests/xilinx/run-test.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -e +{ +echo "all::" +for x in *.ys; do + echo "all:: run-$x" + echo "run-$x:" + echo " @echo 'Running $x..'" + echo " @../../yosys -ql ${x%.ys}.log $x" +done +for s in *.sh; do + if [ "$s" != "run-test.sh" ]; then + echo "all:: run-$s" + echo "run-$s:" + echo " @echo 'Running $s..'" + echo " @bash $s" + fi +done +} > run-test.mk +exec ${MAKE:-make} -f run-test.mk diff --git a/tests/xilinx/xilinx_srl.v b/tests/xilinx/xilinx_srl.v new file mode 100644 index 000000000..bc2a15ab2 --- /dev/null +++ b/tests/xilinx/xilinx_srl.v @@ -0,0 +1,40 @@ +module xilinx_srl_static_test(input i, clk, output [1:0] q); +reg head = 1'b0; +reg [3:0] shift1 = 4'b0000; +reg [3:0] shift2 = 4'b0000; + +always @(posedge clk) begin + head <= i; + shift1 <= {shift1[2:0], head}; + shift2 <= {shift2[2:0], head}; +end + +assign q = {shift2[3], shift1[3]}; +endmodule + +module xilinx_srl_variable_test(input i, clk, input [1:0] l1, l2, output [1:0] q); +reg head = 1'b0; +reg [3:0] shift1 = 4'b0000; +reg [3:0] shift2 = 4'b0000; + +always @(posedge clk) begin + head <= i; + shift1 <= {shift1[2:0], head}; + shift2 <= {shift2[2:0], head}; +end + +assign q = {shift2[l2], shift1[l1]}; +endmodule + +module $__XILINX_SHREG_(input C, D, E, input [1:0] L, output Q); +parameter CLKPOL = 1; +parameter ENPOL = 1; +parameter DEPTH = 1; +parameter [DEPTH-1:0] INIT = {DEPTH{1'b0}}; +reg [DEPTH-1:0] r = INIT; +wire clk = C ^ CLKPOL; +always @(posedge C) + if (E) + r <= { r[DEPTH-2:0], D }; +assign Q = r[L]; +endmodule diff --git a/tests/xilinx/xilinx_srl.ys b/tests/xilinx/xilinx_srl.ys new file mode 100644 index 000000000..4e3c44a98 --- /dev/null +++ b/tests/xilinx/xilinx_srl.ys @@ -0,0 +1,67 @@ +read_verilog xilinx_srl.v +design -save read + +design -copy-to model $__XILINX_SHREG_ +hierarchy -top xilinx_srl_static_test +prep +design -save gold + +techmap +xilinx_srl -fixed +opt + +# stat +# show -width +select -assert-count 1 t:$_DFF_P_ +select -assert-count 2 t:$__XILINX_SHREG_ + +design -stash gate + +design -import gold -as gold +design -import gate -as gate +design -copy-from model -as $__XILINX_SHREG_ \$__XILINX_SHREG_ +prep + +miter -equiv -flatten -make_assert -make_outputs gold gate miter +dump gate +sat -verify -prove-asserts -show-ports -seq 5 miter + +#design -load gold +#stat + +#design -load gate +#stat + +########## + +design -load read +design -copy-to model $__XILINX_SHREG_ +hierarchy -top xilinx_srl_variable_test +prep +design -save gold + +simplemap t:$dff t:$dffe +xilinx_srl -variable +opt + +#stat +# show -width +# write_verilog -noexpr -norename +select -assert-count 1 t:$_DFF_P_ +select -assert-count 2 t:$__XILINX_SHREG_ + +design -stash gate + +design -import gold -as gold +design -import gate -as gate +design -copy-from model -as $__XILINX_SHREG_ \$__XILINX_SHREG_ +prep + +miter -equiv -flatten -make_assert -make_outputs gold gate miter +sat -verify -prove-asserts -show-ports -seq 5 miter + +# design -load gold +# stat + +# design -load gate +# stat From 2e9e745efa03363f9f0d5cc47696401d55a8e5d2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 28 Aug 2019 09:26:08 -0700 Subject: [PATCH 096/130] Do not simplemap for variable test --- tests/xilinx/xilinx_srl.ys | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/xilinx/xilinx_srl.ys b/tests/xilinx/xilinx_srl.ys index 4e3c44a98..b8df0e55a 100644 --- a/tests/xilinx/xilinx_srl.ys +++ b/tests/xilinx/xilinx_srl.ys @@ -40,14 +40,14 @@ hierarchy -top xilinx_srl_variable_test prep design -save gold -simplemap t:$dff t:$dffe xilinx_srl -variable opt #stat # show -width # write_verilog -noexpr -norename -select -assert-count 1 t:$_DFF_P_ +select -assert-count 1 t:$dff +select -assert-count 1 t:$dff r:WIDTH=1 %i select -assert-count 2 t:$__XILINX_SHREG_ design -stash gate From 0ebe2c9831591d4f969139c5ec0776911284a954 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 28 Aug 2019 09:27:03 -0700 Subject: [PATCH 097/130] Rename test_pmgen arg xilinx_srl.{fixed,variable} --- passes/pmgen/test_pmgen.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/pmgen/test_pmgen.cc b/passes/pmgen/test_pmgen.cc index 2695fe802..4f3eec935 100644 --- a/passes/pmgen/test_pmgen.cc +++ b/passes/pmgen/test_pmgen.cc @@ -350,9 +350,9 @@ struct TestPmgenPass : public Pass { if (pattern == "ice40_dsp") return GENERATE_PATTERN(ice40_dsp_pm, ice40_dsp); - if (pattern == "xilinx_srl_fixed") + if (pattern == "xilinx_srl.fixed") return GENERATE_PATTERN(xilinx_srl_pm, fixed); - if (pattern == "xilinx_srl_variable") + if (pattern == "xilinx_srl.variable") return GENERATE_PATTERN(xilinx_srl_pm, variable); if (pattern == "peepopt-muldiv") From c3e9627afeb6b69f244983f2f23fb5473e61ab19 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 28 Aug 2019 09:54:56 -0700 Subject: [PATCH 098/130] Always generate if no match --- passes/pmgen/xilinx_srl.pmg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index e8288c54a..bdb59c2f7 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -142,7 +142,7 @@ match next filter !next->type.in(\FDRE) || !first->hasParam(\IS_D_INVERTED) || (next->hasParam(\IS_D_INVERTED) && param(next, \IS_D_INVERTED).as_bool() == param(first, \IS_D_INVERTED).as_bool()) filter !next->type.in(\FDRE) || !first->hasParam(\IS_R_INVERTED) || (next->hasParam(\IS_R_INVERTED) && param(next, \IS_R_INVERTED).as_bool() == param(first, \IS_R_INVERTED).as_bool()) filter !next->type.in(\FDRE, \FDRE_1) || port(next, \R) == port(first, \R) -generate 10 +generate Cell *cell = module->addCell(NEW_ID, chain.back()->type); cell->setPort(\C, chain.back()->getPort(\C)); cell->setPort(\D, module->addWire(NEW_ID)); From 2f493fb465d398a6fb4f24ffcd4af50d7e158fa9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 28 Aug 2019 09:55:09 -0700 Subject: [PATCH 099/130] Use test_pmgen for xilinx_srl --- tests/xilinx/pmgen_xilinx_srl.ys | 57 ++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tests/xilinx/pmgen_xilinx_srl.ys diff --git a/tests/xilinx/pmgen_xilinx_srl.ys b/tests/xilinx/pmgen_xilinx_srl.ys new file mode 100644 index 000000000..ea2f20487 --- /dev/null +++ b/tests/xilinx/pmgen_xilinx_srl.ys @@ -0,0 +1,57 @@ +read_verilog -icells < Date: Wed, 28 Aug 2019 09:55:34 -0700 Subject: [PATCH 100/130] Add .gitignore --- tests/xilinx/.gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests/xilinx/.gitignore diff --git a/tests/xilinx/.gitignore b/tests/xilinx/.gitignore new file mode 100644 index 000000000..b48f808a1 --- /dev/null +++ b/tests/xilinx/.gitignore @@ -0,0 +1,3 @@ +/*.log +/*.out +/run-test.mk From c4d1bd988b1198f8a656576bd6cf67781aa5b156 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 28 Aug 2019 10:06:40 -0700 Subject: [PATCH 101/130] Do not use default_params dict, hardcode default values, cleanup --- passes/pmgen/xilinx_srl.cc | 29 +++++++++++++---------------- passes/pmgen/xilinx_srl.pmg | 17 ++++++++--------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index b9cdbfaa1..b3bab6021 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -34,11 +34,6 @@ void run_fixed(xilinx_srl_pm &pm) { auto &st = pm.st_fixed; auto &ud = pm.ud_fixed; - auto param_def = [&ud](Cell *cell, IdString param) { - auto def = ud.default_params.at(std::make_pair(cell->type,param)); - return cell->parameters.at(param, def); - }; - log("Found fixed chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type)); auto first_cell = ud.longest_chain.back(); @@ -58,8 +53,12 @@ void run_fixed(xilinx_srl_pm &pm) else initval.append(State::Sx); } - else if (cell->type.in(ID(FDRE), ID(FDRE_1))) - initval.append(param_def(cell, ID(INIT))); + else if (cell->type.in(ID(FDRE), ID(FDRE_1))) { + if (cell->parameters.at(ID(INIT), State::S0).as_bool()) + initval.append(State::S1); + else + initval.append(State::S0); + } else log_abort(); if (cell != first_cell) @@ -77,8 +76,12 @@ void run_fixed(xilinx_srl_pm &pm) c->setParam(ID(CLKPOL), 1); else if (first_cell->type.in(ID($_DFF_N_), ID($DFFE_NN_), ID($_DFFE_NP_), ID(FDRE_1))) c->setParam(ID(CLKPOL), 0); - else if (first_cell->type.in(ID(FDRE))) - c->setParam(ID(CLKPOL), param_def(first_cell, ID(IS_C_INVERTED)).as_bool() ? 0 : 1); + else if (first_cell->type.in(ID(FDRE))) { + if (!first_cell->parameters.at(ID(IS_C_INVERTED), State::S0).as_bool()) + c->setParam(ID(CLKPOL), 1); + else + c->setParam(ID(CLKPOL), 0); + } else log_abort(); if (first_cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_))) @@ -252,14 +255,8 @@ struct XilinxSrlPass : public Pass { pm.ud_fixed.minlen = minlen; pm.ud_variable.minlen = minlen; - if (fixed) { - // TODO: How to get these automatically? - pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(INIT))] = State::S0; - pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_C_INVERTED))] = State::S0; - pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_D_INVERTED))] = State::S0; - pm.ud_fixed.default_params[std::make_pair(ID(FDRE),ID(IS_R_INVERTED))] = State::S0; + if (fixed) pm.run_fixed(run_fixed); - } if (variable) pm.run_variable(run_variable); } diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index bdb59c2f7..8bdcb0bcd 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -4,7 +4,6 @@ state clk_port en_port udata > chain longest_chain udata > non_first_cells udata minlen -udata ,Const>> default_params code non_first_cells.clear(); @@ -111,10 +110,10 @@ match next index port(next, \Q) === port(first, \D) filter port(next, clk_port) == port(first, clk_port) filter en_port == IdString() || port(next, en_port) == port(first, en_port) - filter !next->type.in(\FDRE) || !first->hasParam(\IS_C_INVERTED) || (next->hasParam(\IS_C_INVERTED) && param(next, \IS_C_INVERTED).as_bool() == param(first, \IS_C_INVERTED).as_bool()) - filter !next->type.in(\FDRE) || !first->hasParam(\IS_D_INVERTED) || (next->hasParam(\IS_D_INVERTED) && param(next, \IS_D_INVERTED).as_bool() == param(first, \IS_D_INVERTED).as_bool()) - filter !next->type.in(\FDRE) || !first->hasParam(\IS_R_INVERTED) || (next->hasParam(\IS_R_INVERTED) && param(next, \IS_R_INVERTED).as_bool() == param(first, \IS_R_INVERTED).as_bool()) - filter !next->type.in(\FDRE, \FDRE_1) || port(next, \R) == port(first, \R) + filter !first->type.in(\FDRE) || next->parameters.at(\IS_C_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_C_INVERTED, State::S0).as_bool() + filter !first->type.in(\FDRE) || next->parameters.at(\IS_D_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_D_INVERTED, State::S0).as_bool() + filter !first->type.in(\FDRE) || next->parameters.at(\IS_R_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_R_INVERTED, State::S0).as_bool() + filter !first->type.in(\FDRE, \FDRE_1) || port(next, \R) == port(first, \R) endmatch code @@ -138,10 +137,10 @@ match next index port(next, \Q) === port(chain.back(), \D) filter port(next, clk_port) == port(first, clk_port) filter en_port == IdString() || port(next, en_port) == port(first, en_port) - filter !next->type.in(\FDRE) || !first->hasParam(\IS_C_INVERTED) || (next->hasParam(\IS_C_INVERTED) && param(next, \IS_C_INVERTED).as_bool() == param(first, \IS_C_INVERTED).as_bool()) - filter !next->type.in(\FDRE) || !first->hasParam(\IS_D_INVERTED) || (next->hasParam(\IS_D_INVERTED) && param(next, \IS_D_INVERTED).as_bool() == param(first, \IS_D_INVERTED).as_bool()) - filter !next->type.in(\FDRE) || !first->hasParam(\IS_R_INVERTED) || (next->hasParam(\IS_R_INVERTED) && param(next, \IS_R_INVERTED).as_bool() == param(first, \IS_R_INVERTED).as_bool()) - filter !next->type.in(\FDRE, \FDRE_1) || port(next, \R) == port(first, \R) + filter !first->type.in(\FDRE) || next->parameters.at(\IS_C_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_C_INVERTED, State::S0).as_bool() + filter !first->type.in(\FDRE) || next->parameters.at(\IS_D_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_D_INVERTED, State::S0).as_bool() + filter !first->type.in(\FDRE) || next->parameters.at(\IS_R_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_R_INVERTED, State::S0).as_bool() + filter !first->type.in(\FDRE, \FDRE_1) || port(next, \R) == port(first, \R) generate Cell *cell = module->addCell(NEW_ID, chain.back()->type); cell->setPort(\C, chain.back()->getPort(\C)); From 86b538bd02cb3e4c7e14be2c6d2210eb39463b0f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 28 Aug 2019 10:11:09 -0700 Subject: [PATCH 102/130] More cleanup --- passes/pmgen/xilinx_srl.cc | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index b3bab6021..f66582025 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -36,8 +36,6 @@ void run_fixed(xilinx_srl_pm &pm) auto &ud = pm.ud_fixed; log("Found fixed chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type)); - auto first_cell = ud.longest_chain.back(); - SigSpec initval; for (auto cell : ud.longest_chain) { log_debug(" %s\n", log_id(cell)); @@ -61,10 +59,10 @@ void run_fixed(xilinx_srl_pm &pm) } else log_abort(); - if (cell != first_cell) - pm.autoremove(cell); + pm.autoremove(cell); } + auto first_cell = ud.longest_chain.back(); auto last_cell = ud.longest_chain.front(); Cell *c = pm.module->addCell(NEW_ID, ID($__XILINX_SHREG_)); pm.module->swap_names(c, first_cell); @@ -117,9 +115,6 @@ void run_variable(xilinx_srl_pm &pm) log("Found variable chain of length %d (%s):\n", GetSize(ud.chain), log_id(st.first->type)); - auto first_cell = ud.chain.back().first; - auto first_slice = ud.chain.back().second; - SigSpec initval; for (const auto &i : ud.chain) { auto cell = i.first; @@ -139,11 +134,13 @@ void run_variable(xilinx_srl_pm &pm) } else log_abort(); - if (cell != first_cell) - cell->connections_.at(ID(Q))[slice] = pm.module->addWire(NEW_ID); + cell->connections_.at(ID(Q))[slice] = pm.module->addWire(NEW_ID); } pm.autoremove(st.shiftx); + auto first_cell = ud.chain.back().first; + auto first_slice = ud.chain.back().second; + Cell *c = pm.module->addCell(NEW_ID, ID($__XILINX_SHREG_)); pm.module->swap_names(c, first_cell); From 11e3eb1009360112acff5589cd3771a165278529 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 28 Aug 2019 10:19:35 -0700 Subject: [PATCH 103/130] More cleanup --- passes/pmgen/xilinx_srl.pmg | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 8bdcb0bcd..45d44247a 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -13,9 +13,9 @@ endcode match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !first->has_keep_attr() - select !first->type.in(\FDRE) || !first->hasParam(\IS_R_INVERTED) || !param(first, \IS_R_INVERTED).as_bool() - select !first->type.in(\FDRE) || !first->hasParam(\IS_D_INVERTED) || !param(first, \IS_D_INVERTED).as_bool() - select !first->type.in(\FDRE, \FDRE_1) || port(first, \R) == State::S0 + select !first->type.in(\FDRE) || !first->parameters.at(\IS_R_INVERTED, State::S0).as_bool() + select !first->type.in(\FDRE) || !first->parameters.at(\IS_D_INVERTED, State::S0).as_bool() + select !first->type.in(\FDRE, \FDRE_1) || first->connections_.at(\R, State::S0).is_fully_zero() filter !non_first_cells.count(first) generate SigSpec C = module->addWire(NEW_ID); @@ -34,8 +34,10 @@ generate cell->setPort(\CE, module->addWire(NEW_ID)); if (r & 1) cell->setPort(\R, module->addWire(NEW_ID)); - else - cell->setPort(\R, State::S0); + else { + if (rng(2) == 0) + cell->setPort(\R, State::S0); + } break; case 2: case 3: @@ -82,9 +84,9 @@ arg en_port match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !first->has_keep_attr() - select !first->type.in(\FDRE) || !first->hasParam(\IS_R_INVERTED) || !param(first, \IS_R_INVERTED).as_bool() - select !first->type.in(\FDRE) || !first->hasParam(\IS_D_INVERTED) || !param(first, \IS_D_INVERTED).as_bool() - select !first->type.in(\FDRE, \FDRE_1) || port(first, \R) == State::S0 + select !first->type.in(\FDRE) || !first->parameters.at(\IS_R_INVERTED, State::S0).as_bool() + select !first->type.in(\FDRE) || !first->parameters.at(\IS_D_INVERTED, State::S0).as_bool() + select !first->type.in(\FDRE, \FDRE_1) || first->connections_.at(\R, State::S0).is_fully_zero() endmatch code clk_port en_port @@ -105,7 +107,6 @@ match next select !next->has_keep_attr() select !port(next, \D)[0].wire->get_bool_attribute(\keep) select nusers(port(next, \Q)) == 2 - select !next->type.in(\FDRE, \FDRE_1) || port(next, \R) == State::S0 index next->type === first->type index port(next, \Q) === port(first, \D) filter port(next, clk_port) == port(first, clk_port) @@ -113,7 +114,7 @@ match next filter !first->type.in(\FDRE) || next->parameters.at(\IS_C_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_C_INVERTED, State::S0).as_bool() filter !first->type.in(\FDRE) || next->parameters.at(\IS_D_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_D_INVERTED, State::S0).as_bool() filter !first->type.in(\FDRE) || next->parameters.at(\IS_R_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_R_INVERTED, State::S0).as_bool() - filter !first->type.in(\FDRE, \FDRE_1) || port(next, \R) == port(first, \R) + filter !first->type.in(\FDRE, \FDRE_1) || next->connections_.at(\R, State::S0).is_fully_zero() endmatch code @@ -140,14 +141,15 @@ match next filter !first->type.in(\FDRE) || next->parameters.at(\IS_C_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_C_INVERTED, State::S0).as_bool() filter !first->type.in(\FDRE) || next->parameters.at(\IS_D_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_D_INVERTED, State::S0).as_bool() filter !first->type.in(\FDRE) || next->parameters.at(\IS_R_INVERTED, State::S0).as_bool() == first->parameters.at(\IS_R_INVERTED, State::S0).as_bool() - filter !first->type.in(\FDRE, \FDRE_1) || port(next, \R) == port(first, \R) + filter !first->type.in(\FDRE, \FDRE_1) || next->connections_.at(\R, State::S0).is_fully_zero() generate Cell *cell = module->addCell(NEW_ID, chain.back()->type); cell->setPort(\C, chain.back()->getPort(\C)); cell->setPort(\D, module->addWire(NEW_ID)); cell->setPort(\Q, chain.back()->getPort(\D)); if (cell->type == \FDRE) { - cell->setPort(\R, chain.back()->getPort(\R)); + if (rng(2) == 0) + cell->setPort(\R, chain.back()->connections_.at(\R, State::S0)); cell->setPort(\CE, chain.back()->getPort(\CE)); } else if (cell->type.begins_with("$_DFFE_")) From 52c4655de32c027e0542834d030ac951be10c8eb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 28 Aug 2019 11:06:11 -0700 Subject: [PATCH 104/130] No need to replace Q of slice since $shiftx is autoremove-d --- passes/pmgen/xilinx_srl.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index f66582025..87fcaa15a 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -134,7 +134,6 @@ void run_variable(xilinx_srl_pm &pm) } else log_abort(); - cell->connections_.at(ID(Q))[slice] = pm.module->addWire(NEW_ID); } pm.autoremove(st.shiftx); From ebd0a1875b74460da10d9b114e97c1468d8542db Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 28 Aug 2019 12:21:15 -0700 Subject: [PATCH 105/130] Use equiv_opt for latches --- tests/ice40/latches.ys | 11 +++++++- tests/ice40/latches_tb.v | 57 ---------------------------------------- 2 files changed, 10 insertions(+), 58 deletions(-) delete mode 100644 tests/ice40/latches_tb.v diff --git a/tests/ice40/latches.ys b/tests/ice40/latches.ys index fe0d1f70e..f3562559e 100644 --- a/tests/ice40/latches.ys +++ b/tests/ice40/latches.ys @@ -1,6 +1,15 @@ read_verilog latches.v +design -save read + +proc +async2sync # converts latches to a 'sync' variant clocked by a 'super'-clock +flatten +synth_ice40 +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) + +design -load read synth_ice40 cd top select -assert-count 4 t:SB_LUT4 select -assert-none t:SB_LUT4 %% t:* %D -write_verilog latches_synth.v diff --git a/tests/ice40/latches_tb.v b/tests/ice40/latches_tb.v deleted file mode 100644 index b0585264b..000000000 --- a/tests/ice40/latches_tb.v +++ /dev/null @@ -1,57 +0,0 @@ -module testbench; - reg clk; - - initial begin - // $dumpfile("testbench.vcd"); - // $dumpvars(0, testbench); - - #5 clk = 0; - repeat (10000) begin - #5 clk = 1; - #5 clk = 0; - end - end - - - reg [2:0] dinA = 0; - wire doutB,doutB1,doutB2; - reg lat,latn,latsr = 0; - - top uut ( - .clk (clk ), - .a (dinA[0] ), - .pre (dinA[1] ), - .clr (dinA[2] ), - .b (doutB ), - .b1 (doutB1 ), - .b2 (doutB2 ) - ); - - always @(posedge clk) begin - #3; - dinA <= dinA + 1; - end - - always @* - if ( clk ) - lat <= dinA[0]; - - - always @* - if ( !clk ) - latn <= dinA[0]; - - - always @* - if ( dinA[2] ) - latsr <= 1'b0; - else if ( dinA[1] ) - latsr <= 1'b1; - else if ( clk ) - latsr <= dinA[0]; - - assert_dff lat_test(.clk(clk), .test(doutB), .pat(lat)); - assert_dff latn_test(.clk(clk), .test(doutB1), .pat(latn)); - assert_dff latsr_test(.clk(clk), .test(doutB2), .pat(latsr)); - -endmodule From 87d5d9b8c80df696c836831df9d9eff6f20476fa Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 28 Aug 2019 12:30:35 -0700 Subject: [PATCH 106/130] Use equiv for memory and dpram --- tests/ice40/dpram.ys | 5 +-- tests/ice40/dpram_tb.v | 81 ----------------------------------------- tests/ice40/memory.ys | 5 +-- tests/ice40/memory_tb.v | 79 ---------------------------------------- 4 files changed, 2 insertions(+), 168 deletions(-) delete mode 100644 tests/ice40/dpram_tb.v delete mode 100644 tests/ice40/memory_tb.v diff --git a/tests/ice40/dpram.ys b/tests/ice40/dpram.ys index 77364e5ae..4f6a253ea 100644 --- a/tests/ice40/dpram.ys +++ b/tests/ice40/dpram.ys @@ -6,13 +6,10 @@ equiv_opt -run :prove -map +/ice40/cells_sim.v synth_ice40 memory opt -full -# TODO -#equiv_opt -run prove: -assert null miter -equiv -flatten -make_assert -make_outputs gold gate miter -#sat -verify -prove-asserts -tempinduct -show-inputs -show-outputs miter +sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter design -load postopt cd top select -assert-count 1 t:SB_RAM40_4K select -assert-none t:SB_RAM40_4K %% t:* %D -write_verilog dpram_synth.v diff --git a/tests/ice40/dpram_tb.v b/tests/ice40/dpram_tb.v deleted file mode 100644 index dede64614..000000000 --- a/tests/ice40/dpram_tb.v +++ /dev/null @@ -1,81 +0,0 @@ -module testbench; - reg clk; - - initial begin - // $dumpfile("testbench.vcd"); - // $dumpvars(0, testbench); - - #5 clk = 0; - repeat (10000) begin - #5 clk = 1; - #5 clk = 0; - end - end - - - reg [7:0] data_a = 0; - reg [7:0] addr_a = 0; - reg [7:0] addr_b = 0; - reg we_a = 0; - reg re_a = 1; - wire [7:0] q_a; - reg mem_init = 0; - - reg [7:0] pq_a; - - always @(posedge clk) begin - #3; - data_a <= data_a + 17; - - addr_a <= addr_a + 1; - addr_b <= addr_b + 1; - end - - always @(posedge addr_a) begin - #10; - if(addr_a > 6'h3E) - mem_init <= 1; - end - - always @(posedge clk) begin - //#3; - we_a <= !we_a; - end - - reg [7:0] mem [(1<<8)-1:0]; - - always @(posedge clk) // Write memory. - begin - if (we_a) - mem[addr_a] <= data_a; // Using write address bus. - end - always @(posedge clk) // Read memory. - begin - pq_a <= mem[addr_b]; // Using read address bus. - end - - top uut ( - .din(data_a), - .write_en(we_a), - .waddr(addr_a), - .wclk(clk), - .raddr(addr_b), - .rclk(clk), - .dout(q_a) - ); - - uut_mem_checker port_a_test(.clk(clk), .init(mem_init), .en(!we_a), .A(q_a), .B(pq_a)); - -endmodule - -module uut_mem_checker(input clk, input init, input en, input [7:0] A, input [7:0] B); - always @(posedge clk) - begin - #1; - if (en == 1 & init == 1 & A !== B) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); - $stop; - end - end -endmodule diff --git a/tests/ice40/memory.ys b/tests/ice40/memory.ys index 9b7490cd8..a66afbae6 100644 --- a/tests/ice40/memory.ys +++ b/tests/ice40/memory.ys @@ -6,13 +6,10 @@ equiv_opt -run :prove -map +/ice40/cells_sim.v synth_ice40 memory opt -full -# TODO -#equiv_opt -run prove: -assert null miter -equiv -flatten -make_assert -make_outputs gold gate miter -#sat -verify -prove-asserts -tempinduct -show-inputs -show-outputs miter +sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter design -load postopt cd top select -assert-count 1 t:SB_RAM40_4K select -assert-none t:SB_RAM40_4K %% t:* %D -write_verilog memory_synth.v diff --git a/tests/ice40/memory_tb.v b/tests/ice40/memory_tb.v deleted file mode 100644 index be69374eb..000000000 --- a/tests/ice40/memory_tb.v +++ /dev/null @@ -1,79 +0,0 @@ -module testbench; - reg clk; - - initial begin - // $dumpfile("testbench.vcd"); - // $dumpvars(0, testbench); - - #5 clk = 0; - repeat (10000) begin - #5 clk = 1; - #5 clk = 0; - end - end - - - reg [7:0] data_a = 0; - reg [5:0] addr_a = 0; - reg we_a = 0; - reg re_a = 1; - wire [7:0] q_a; - reg mem_init = 0; - - reg [7:0] pq_a; - - top uut ( - .data_a(data_a), - .addr_a(addr_a), - .we_a(we_a), - .clk(clk), - .q_a(q_a) - ); - - always @(posedge clk) begin - #3; - data_a <= data_a + 17; - - addr_a <= addr_a + 1; - end - - always @(posedge addr_a) begin - #10; - if(addr_a > 6'h3E) - mem_init <= 1; - end - - always @(posedge clk) begin - //#3; - we_a <= !we_a; - end - - // Declare the RAM variable for check - reg [7:0] ram[63:0]; - - // Port A for check - always @ (posedge clk) - begin - if (we_a) - begin - ram[addr_a] <= data_a; - pq_a <= data_a; - end - pq_a <= ram[addr_a]; - end - - uut_mem_checker port_a_test(.clk(clk), .init(mem_init), .en(!we_a), .A(q_a), .B(pq_a)); - -endmodule - -module uut_mem_checker(input clk, input init, input en, input [7:0] A, input [7:0] B); - always @(posedge clk) - begin - #1; - if (en == 1 & init == 1 & A !== B) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); - $stop; - end - end -endmodule From b8a9f73089234ed699a4057b50fd739a90abea43 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 28 Aug 2019 12:36:20 -0700 Subject: [PATCH 107/130] Comment out *.sh used for testbenches as we have no more --- tests/ice40/run-test.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/ice40/run-test.sh b/tests/ice40/run-test.sh index bd9d35314..941dcaecd 100755 --- a/tests/ice40/run-test.sh +++ b/tests/ice40/run-test.sh @@ -21,13 +21,13 @@ for x in *.ys; do fi done -for s in *.sh; do - if [ "$s" != "run-test.sh" ]; then - echo "all:: run-$s" - echo "run-$s:" - echo " @echo 'Running $s..'" - echo " @bash $s" - fi -done +#for s in *.sh; do +# if [ "$s" != "run-test.sh" ]; then +# echo "all:: run-$s" +# echo "run-$s:" +# echo " @echo 'Running $s..'" +# echo " @bash $s" +# fi +#done } > run-test.mk exec ${MAKE:-make} -f run-test.mk From 0af64df10cf817bf7776feda6dffd2a700a20550 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 28 Aug 2019 15:31:55 -0700 Subject: [PATCH 108/130] Account for D port being a constant --- passes/pmgen/xilinx_srl.pmg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/passes/pmgen/xilinx_srl.pmg b/passes/pmgen/xilinx_srl.pmg index 45d44247a..b18119b87 100644 --- a/passes/pmgen/xilinx_srl.pmg +++ b/passes/pmgen/xilinx_srl.pmg @@ -105,7 +105,7 @@ endcode match next select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !next->has_keep_attr() - select !port(next, \D)[0].wire->get_bool_attribute(\keep) + select port(next, \D)[0].wire && !port(next, \D)[0].wire->get_bool_attribute(\keep) select nusers(port(next, \Q)) == 2 index next->type === first->type index port(next, \Q) === port(first, \D) @@ -132,7 +132,7 @@ match next semioptional select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, \FDRE, \FDRE_1) select !next->has_keep_attr() - select !port(next, \D)[0].wire->get_bool_attribute(\keep) + select port(next, \D)[0].wire && !port(next, \D)[0].wire->get_bool_attribute(\keep) select nusers(port(next, \Q)) == 2 index next->type === chain.back()->type index port(next, \Q) === port(chain.back(), \D) @@ -201,7 +201,7 @@ endcode match first select first->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, $dff, $dffe) select !first->has_keep_attr() - select !port(first, \Q)[0].wire->get_bool_attribute(\keep) + select port(first, \Q)[0].wire && !port(first, \Q)[0].wire->get_bool_attribute(\keep) slice idx GetSize(port(first, \Q)) select nusers(port(first, \Q)[idx]) <= 2 index port(first, \Q)[idx] === port(shiftx, \A)[shiftx_width-1] @@ -272,7 +272,7 @@ match next semioptional select next->type.in($_DFF_N_, $_DFF_P_, $_DFFE_NN_, $_DFFE_NP_, $_DFFE_PN_, $_DFFE_PP_, $dff, $dffe) select !next->has_keep_attr() - select !port(next, \D)[0].wire->get_bool_attribute(\keep) + select port(next, \D)[0].wire && !port(next, \D)[0].wire->get_bool_attribute(\keep) slice idx GetSize(port(next, \Q)) select nusers(port(next, \Q)[idx]) <= 3 index next->type === chain.back().first->type From 4eb5847dbdbb4a4efcde20aa81455eed8196db56 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 28 Aug 2019 18:10:33 -0700 Subject: [PATCH 109/130] Cleanup --- passes/pmgen/xilinx_srl.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc index 87fcaa15a..3d264e8d4 100644 --- a/passes/pmgen/xilinx_srl.cc +++ b/passes/pmgen/xilinx_srl.cc @@ -24,11 +24,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -// for peepopt_pm -bool did_something; - #include "passes/pmgen/xilinx_srl_pm.h" -#include "passes/pmgen/peepopt_pm.h" void run_fixed(xilinx_srl_pm &pm) { From d588c6898fb7cfebe52a71a48d6fb21d1623e61b Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Thu, 29 Aug 2019 10:49:46 +0300 Subject: [PATCH 110/130] Add comments for examples from Lattice user guide --- tests/ice40/dpram.v | 3 +++ tests/ice40/macc.v | 3 +++ tests/ice40/rom.v | 3 +++ 3 files changed, 9 insertions(+) diff --git a/tests/ice40/dpram.v b/tests/ice40/dpram.v index 2e69d6b3b..3ea4c1f27 100644 --- a/tests/ice40/dpram.v +++ b/tests/ice40/dpram.v @@ -1,3 +1,6 @@ +/* +Example from: https://www.latticesemi.com/-/media/LatticeSemi/Documents/UserManuals/EI/iCEcube201701UserGuide.ashx?document_id=52071 [p. 72]. +*/ module top (din, write_en, waddr, wclk, raddr, rclk, dout); parameter addr_width = 8; parameter data_width = 8; diff --git a/tests/ice40/macc.v b/tests/ice40/macc.v index 115f8ce42..63a3d3a74 100644 --- a/tests/ice40/macc.v +++ b/tests/ice40/macc.v @@ -1,3 +1,6 @@ +/* +Example from: https://www.latticesemi.com/-/media/LatticeSemi/Documents/UserManuals/EI/iCEcube201701UserGuide.ashx?document_id=52071 [p. 77]. +*/ module top(clk,a,b,c,set); parameter A_WIDTH = 4; parameter B_WIDTH = 3; diff --git a/tests/ice40/rom.v b/tests/ice40/rom.v index c31ca3b2b..0a0f41f37 100644 --- a/tests/ice40/rom.v +++ b/tests/ice40/rom.v @@ -1,3 +1,6 @@ +/* +Example from: https://www.latticesemi.com/-/media/LatticeSemi/Documents/UserManuals/EI/iCEcube201701UserGuide.ashx?document_id=52071 [p. 74]. +*/ module top(data, addr); output [3:0] data; input [4:0] addr; From 3e0f73c3df3119a839b326464a8399ce4256edc7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 29 Aug 2019 12:12:59 -0700 Subject: [PATCH 111/130] abc9 to not call "clean" at end of run (often called outside) --- passes/techmap/abc9.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 84cb2c04f..f2662e0cb 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -1300,9 +1300,6 @@ struct Abc9Pass : public Pass { assign_map.clear(); - // The "clean" pass also contains a design->check() call - Pass::call(design, "clean"); - log_pop(); } } Abc9Pass; From c52db44f9ab19194dbdefd35bd697ab99650f510 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 29 Aug 2019 12:13:52 -0700 Subject: [PATCH 112/130] Group abc_* attribute doc with other attributes --- README.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 38ca77862..95dc01aa8 100644 --- a/README.md +++ b/README.md @@ -347,6 +347,23 @@ Verilog Attributes and non-standard features it as the external-facing pin of an I/O pad, and prevents ``iopadmap`` from inserting another pad cell on it. +- The module attribute ``abc_box_id`` specifies a positive integer linking a + blackbox or whitebox definition to a corresponding entry in a `abc9` + box-file. + +- The port attribute ``abc_scc_break`` indicates a module input port that will + be treated as a primary output during `abc9` techmapping. Doing so eliminates + the possibility of a strongly-connected component (i.e. a combinatorial loop) + existing. Typically, this is specified for sequential inputs on otherwise + combinatorial boxes -- for example, applying ``abc_scc_break`` onto the `D` + port of a LUTRAM cell prevents `abc9` from interpreting any `Q` -> `D` paths + as a combinatorial loop. + +- The port attribute ``abc_carry`` marks the carry-in (if an input port) and + carry-out (if output port) ports of a box. This information is necessary for + `abc9` to preserve the integrity of carry-chains. Specifying this attribute + onto a bus port will affect only its most significant bit. + - In addition to the ``(* ... *)`` attribute syntax, Yosys supports the non-standard ``{* ... *}`` attribute syntax to set default attributes for everything that comes after the ``{* ... *}`` statement. (Reset @@ -423,23 +440,6 @@ Verilog Attributes and non-standard features blackboxes and whiteboxes. Use ``read_verilog -specify`` to enable this functionality. (By default specify .. endspecify blocks are ignored.) -- The module attribute ``abc_box_id`` specifies a positive integer linking a - blackbox or whitebox definition to a corresponding entry in a `abc9` - box-file. - -- The port attribute ``abc_scc_break`` indicates a module input port that will - be treated as a primary output during `abc9` techmapping. Doing so eliminates - the possibility of a strongly-connected component (i.e. a combinatorial loop) - existing. Typically, this is specified for sequential inputs on otherwise - combinatorial boxes -- for example, applying ``abc_scc_break`` onto the `D` - port of a LUTRAM cell prevents `abc9` from interpreting any `Q` -> `D` paths - as a combinatorial loop. - -- The port attribute ``abc_carry`` marks the carry-in (if an input port) and - carry-out (if output port) ports of a box. This information is necessary for - `abc9` to preserve the integrity of carry-chains. Specifying this attribute - onto a bus port will affect only its most significant bit. - Non-standard or SystemVerilog features for formal verification ============================================================== From 18cabe9370c46b72e9fb52eb9be5a7c7fb873274 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 29 Aug 2019 17:24:03 -0700 Subject: [PATCH 113/130] Output has priority over input when stitching in abc9 --- passes/techmap/abc9.cc | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index f2662e0cb..6fdf987f0 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -694,30 +694,27 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri int in_wires = 0, out_wires = 0; // Stitch in mapped_mod's inputs/outputs into module - for (auto &it : mapped_mod->wires_) { - RTLIL::Wire *w = it.second; - if (!w->port_input && !w->port_output) - continue; - RTLIL::Wire *wire = module->wire(w->name); + for (auto port : mapped_mod->ports) { + RTLIL::Wire *w = mapped_mod->wire(port); + RTLIL::Wire *wire = module->wire(port); log_assert(wire); - RTLIL::Wire *remap_wire = module->wire(remap_name(w->name)); + RTLIL::Wire *remap_wire = module->wire(remap_name(port)); RTLIL::SigSpec signal = RTLIL::SigSpec(wire, 0, GetSize(remap_wire)); log_assert(GetSize(signal) >= GetSize(remap_wire)); - log_assert(w->port_input || w->port_output); RTLIL::SigSig conn; - if (w->port_input) { - conn.first = remap_wire; - conn.second = signal; - in_wires++; - module->connect(conn); - } if (w->port_output) { conn.first = signal; conn.second = remap_wire; out_wires++; module->connect(conn); } + else if (w->port_input) { + conn.first = remap_wire; + conn.second = signal; + in_wires++; + module->connect(conn); + } } for (auto &it : bit_users) From 5d16bf831688ff665b0ec2abd6835b71320b2db5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 29 Aug 2019 17:24:25 -0700 Subject: [PATCH 114/130] parse_xaiger() to do "clean -purge" --- frontends/aiger/aigerparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 06522939f..2e1fb8fad 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -974,7 +974,7 @@ void AigerReader::post_process() // operate (and run checks on) this one module RTLIL::Design *mapped_design = new RTLIL::Design; mapped_design->add(module); - Pass::call(mapped_design, "clean"); + Pass::call(mapped_design, "clean -purge"); mapped_design->modules_.erase(module->name); delete mapped_design; From 6a111ad32487fb49c5d30db5697c794814ffa511 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 29 Aug 2019 17:24:48 -0700 Subject: [PATCH 115/130] Nicer formatting --- tests/simple_abc9/run-test.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/simple_abc9/run-test.sh b/tests/simple_abc9/run-test.sh index 49ae23338..8df6994e3 100755 --- a/tests/simple_abc9/run-test.sh +++ b/tests/simple_abc9/run-test.sh @@ -20,4 +20,10 @@ fi cp ../simple/*.v . cp ../simple/*.sv . DOLLAR='?' -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-n 300 -p 'hierarchy; synth -run coarse; opt -full; techmap; abc9 -lut 4 -box ../abc.box; stat; check -assert; select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%'" +exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-n 300 -p '\ + hierarchy; \ + synth -run coarse; \ + opt -full; \ + techmap; abc9 -lut 4 -box ../abc.box; \ + check -assert; \ + select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%'" From 20f4aea480e259272360f4c77667a9e1828986e8 Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Fri, 30 Aug 2019 08:53:35 +0300 Subject: [PATCH 116/130] Remove simulation from run-test.sh --- tests/ice40/run-test.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/ice40/run-test.sh b/tests/ice40/run-test.sh index 941dcaecd..acfd582d2 100755 --- a/tests/ice40/run-test.sh +++ b/tests/ice40/run-test.sh @@ -13,12 +13,6 @@ for x in *.ys; do echo "run-$x:" echo " @echo 'Running $x..'" echo " @../../yosys -ql ${x%.ys}.log $x -w 'Yosys has only limited support for tri-state logic at the moment.'" - - if [ -f "${x%.ys}_tb.v" ]; then - echo " @echo 'Running ${x%.ys}_tb.v..'" - echo " @iverilog -o ${x%.ys}_testbench $t ${x%.ys}_synth.v common.v $TECHLIBS_PREFIX/ice40/cells_sim.v" - echo " @vvp -N ${x%.ys}_testbench" - fi done #for s in *.sh; do From 8e3abda19308bd4ac7e03d38f899831e853f4794 Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Fri, 30 Aug 2019 09:11:03 +0300 Subject: [PATCH 117/130] Remove simulation from run-test.sh (unnecessary paths) --- tests/ice40/run-test.sh | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/tests/ice40/run-test.sh b/tests/ice40/run-test.sh index acfd582d2..2c72ca3a9 100755 --- a/tests/ice40/run-test.sh +++ b/tests/ice40/run-test.sh @@ -1,11 +1,5 @@ +#!/usr/bin/env bash set -e -if [ -f "../../techlibs/common/simcells.v" ]; then - COMMON_PREFIX=../../techlibs/common - TECHLIBS_PREFIX=../../techlibs -else - COMMON_PREFIX=/usr/local/share/yosys - TECHLIBS_PREFIX=/usr/local/share/yosys -fi { echo "all::" for x in *.ys; do @@ -14,14 +8,13 @@ for x in *.ys; do echo " @echo 'Running $x..'" echo " @../../yosys -ql ${x%.ys}.log $x -w 'Yosys has only limited support for tri-state logic at the moment.'" done - -#for s in *.sh; do -# if [ "$s" != "run-test.sh" ]; then -# echo "all:: run-$s" -# echo "run-$s:" -# echo " @echo 'Running $s..'" -# echo " @bash $s" -# fi -#done +for s in *.sh; do + if [ "$s" != "run-test.sh" ]; then + echo "all:: run-$s" + echo "run-$s:" + echo " @echo 'Running $s..'" + echo " @bash $s" + fi +done } > run-test.mk exec ${MAKE:-make} -f run-test.mk From eb0a5b2293d005d3a6a2d680b40f1449a489204d Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Fri, 30 Aug 2019 09:17:32 +0300 Subject: [PATCH 118/130] Remove unnecessary common.v(assertions for testbenches). --- tests/ice40/common.v | 47 -------------------------------------------- 1 file changed, 47 deletions(-) delete mode 100644 tests/ice40/common.v diff --git a/tests/ice40/common.v b/tests/ice40/common.v deleted file mode 100644 index 5446f0817..000000000 --- a/tests/ice40/common.v +++ /dev/null @@ -1,47 +0,0 @@ -module assert_dff(input clk, input test, input pat); - always @(posedge clk) - begin - #1; - if (test != pat) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time); - $stop; - end - end -endmodule - -module assert_tri(input en, input A, input B); - always @(posedge en) - begin - #1; - if (A !== B) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); - $stop; - end - end -endmodule - -module assert_Z(input clk, input A); - always @(posedge clk) - begin - #1; - if (A === 1'bZ) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A); - $stop; - end - end -endmodule - -module assert_comb(input A, input B); - always @(*) - begin - #1; - if (A !== B) - begin - $display("ERROR: ASSERTION FAILED in %m:",$time," ",A," ",B); - $stop; - end - end -endmodule From d144748401df3f6d527771e6d30cc1eb1e08734e Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Fri, 30 Aug 2019 09:45:33 +0300 Subject: [PATCH 119/130] Add new tests. --- tests/ice40/alu.v | 19 +++++++++++ tests/ice40/alu.ys | 11 +++++++ tests/ice40/counter.v | 17 ++++++++++ tests/ice40/counter.ys | 11 +++++++ tests/ice40/fsm.v | 73 ++++++++++++++++++++++++++++++++++++++++++ tests/ice40/fsm.ys | 13 ++++++++ tests/ice40/logic.v | 18 +++++++++++ tests/ice40/logic.ys | 7 ++++ tests/ice40/shifter.v | 22 +++++++++++++ tests/ice40/shifter.ys | 9 ++++++ 10 files changed, 200 insertions(+) create mode 100644 tests/ice40/alu.v create mode 100644 tests/ice40/alu.ys create mode 100644 tests/ice40/counter.v create mode 100644 tests/ice40/counter.ys create mode 100644 tests/ice40/fsm.v create mode 100644 tests/ice40/fsm.ys create mode 100644 tests/ice40/logic.v create mode 100644 tests/ice40/logic.ys create mode 100644 tests/ice40/shifter.v create mode 100644 tests/ice40/shifter.ys diff --git a/tests/ice40/alu.v b/tests/ice40/alu.v new file mode 100644 index 000000000..f82cc2e21 --- /dev/null +++ b/tests/ice40/alu.v @@ -0,0 +1,19 @@ +module top ( + input clock, + input [31:0] dinA, dinB, + input [2:0] opcode, + output reg [31:0] dout +); + always @(posedge clock) begin + case (opcode) + 0: dout <= dinA + dinB; + 1: dout <= dinA - dinB; + 2: dout <= dinA >> dinB; + 3: dout <= $signed(dinA) >>> dinB; + 4: dout <= dinA << dinB; + 5: dout <= dinA & dinB; + 6: dout <= dinA | dinB; + 7: dout <= dinA ^ dinB; + endcase + end +endmodule diff --git a/tests/ice40/alu.ys b/tests/ice40/alu.ys new file mode 100644 index 000000000..bd859efc4 --- /dev/null +++ b/tests/ice40/alu.ys @@ -0,0 +1,11 @@ +read_verilog alu.v +hierarchy -top top +proc +flatten +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 62 t:SB_CARRY +select -assert-count 32 t:SB_DFF +select -assert-count 655 t:SB_LUT4 +select -assert-none t:SB_CARRY t:SB_DFF t:SB_LUT4 %% t:* %D diff --git a/tests/ice40/counter.v b/tests/ice40/counter.v new file mode 100644 index 000000000..52852f8ac --- /dev/null +++ b/tests/ice40/counter.v @@ -0,0 +1,17 @@ +module top ( +out, +clk, +reset +); + output [7:0] out; + input clk, reset; + reg [7:0] out; + + always @(posedge clk, posedge reset) + if (reset) begin + out <= 8'b0 ; + end else + out <= out + 1; + + +endmodule diff --git a/tests/ice40/counter.ys b/tests/ice40/counter.ys new file mode 100644 index 000000000..fb32e67a5 --- /dev/null +++ b/tests/ice40/counter.ys @@ -0,0 +1,11 @@ +read_verilog counter.v +hierarchy -top top +proc +flatten +equiv_opt -map +/ice40/cells_sim.v synth_ice40 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 7 t:SB_CARRY +select -assert-count 8 t:SB_DFFR +select -assert-count 8 t:SB_LUT4 +select -assert-none t:SB_CARRY t:SB_DFFR t:SB_LUT4 %% t:* %D diff --git a/tests/ice40/fsm.v b/tests/ice40/fsm.v new file mode 100644 index 000000000..0605bd102 --- /dev/null +++ b/tests/ice40/fsm.v @@ -0,0 +1,73 @@ + module fsm ( + clock, + reset, + req_0, + req_1, + gnt_0, + gnt_1 + ); + input clock,reset,req_0,req_1; + output gnt_0,gnt_1; + wire clock,reset,req_0,req_1; + reg gnt_0,gnt_1; + + parameter SIZE = 3 ; + parameter IDLE = 3'b001,GNT0 = 3'b010,GNT1 = 3'b100,GNT2 = 3'b101 ; + + reg [SIZE-1:0] state; + reg [SIZE-1:0] next_state; + + always @ (posedge clock) + begin : FSM + if (reset == 1'b1) begin + state <= #1 IDLE; + gnt_0 <= 0; + gnt_1 <= 0; + end else + case(state) + IDLE : if (req_0 == 1'b1) begin + state <= #1 GNT0; + gnt_0 <= 1; + end else if (req_1 == 1'b1) begin + gnt_1 <= 1; + state <= #1 GNT0; + end else begin + state <= #1 IDLE; + end + GNT0 : if (req_0 == 1'b1) begin + state <= #1 GNT0; + end else begin + gnt_0 <= 0; + state <= #1 IDLE; + end + GNT1 : if (req_1 == 1'b1) begin + state <= #1 GNT2; + gnt_1 <= req_0; + end + GNT2 : if (req_0 == 1'b1) begin + state <= #1 GNT1; + gnt_1 <= req_1; + end + default : state <= #1 IDLE; + endcase + end + + endmodule + + module top ( +input clk, +input rst, +input a, +input b, +output g0, +output g1 +); + +fsm u_fsm ( .clock(clk), + .reset(rst), + .req_0(a), + .req_1(b), + .gnt_0(g0), + .gnt_1(g1)); + +endmodule diff --git a/tests/ice40/fsm.ys b/tests/ice40/fsm.ys new file mode 100644 index 000000000..4cc8629d6 --- /dev/null +++ b/tests/ice40/fsm.ys @@ -0,0 +1,13 @@ +read_verilog fsm.v +hierarchy -top top +proc +flatten +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 2 t:SB_DFFESR +select -assert-count 2 t:SB_DFFSR +select -assert-count 1 t:SB_DFFSS +select -assert-count 13 t:SB_LUT4 +select -assert-none t:SB_DFFESR t:SB_DFFSR t:SB_DFFSS t:SB_LUT4 %% t:* %D diff --git a/tests/ice40/logic.v b/tests/ice40/logic.v new file mode 100644 index 000000000..e5343cae0 --- /dev/null +++ b/tests/ice40/logic.v @@ -0,0 +1,18 @@ +module top +( + input [0:7] in, + output B1,B2,B3,B4,B5,B6,B7,B8,B9,B10 + ); + + assign B1 = in[0] & in[1]; + assign B2 = in[0] | in[1]; + assign B3 = in[0] ~& in[1]; + assign B4 = in[0] ~| in[1]; + assign B5 = in[0] ^ in[1]; + assign B6 = in[0] ~^ in[1]; + assign B7 = ~in[0]; + assign B8 = in[0]; + assign B9 = in[0:1] && in [2:3]; + assign B10 = in[0:1] || in [2:3]; + +endmodule diff --git a/tests/ice40/logic.ys b/tests/ice40/logic.ys new file mode 100644 index 000000000..fc5e5b1d8 --- /dev/null +++ b/tests/ice40/logic.ys @@ -0,0 +1,7 @@ +read_verilog logic.v +hierarchy -top top +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 9 t:SB_LUT4 +select -assert-none t:SB_LUT4 %% t:* %D diff --git a/tests/ice40/shifter.v b/tests/ice40/shifter.v new file mode 100644 index 000000000..c55632552 --- /dev/null +++ b/tests/ice40/shifter.v @@ -0,0 +1,22 @@ +module top ( +out, +clk, +in +); + output [7:0] out; + input signed clk, in; + reg signed [7:0] out = 0; + + always @(posedge clk) + begin +`ifndef BUG + out <= out >> 1; + out[7] <= in; +`else + + out <= out << 1; + out[7] <= in; +`endif + end + +endmodule diff --git a/tests/ice40/shifter.ys b/tests/ice40/shifter.ys new file mode 100644 index 000000000..47d95d298 --- /dev/null +++ b/tests/ice40/shifter.ys @@ -0,0 +1,9 @@ +read_verilog shifter.v +hierarchy -top top +proc +flatten +equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 8 t:SB_DFF +select -assert-none t:SB_DFF %% t:* %D From 86f1375ecd3e6721a0e5da469672db890926914e Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Fri, 30 Aug 2019 12:38:28 +0300 Subject: [PATCH 120/130] Fix test for counter --- tests/ice40/counter.ys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ice40/counter.ys b/tests/ice40/counter.ys index fb32e67a5..c65c21622 100644 --- a/tests/ice40/counter.ys +++ b/tests/ice40/counter.ys @@ -5,7 +5,7 @@ flatten equiv_opt -map +/ice40/cells_sim.v synth_ice40 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module -select -assert-count 7 t:SB_CARRY +select -assert-count 6 t:SB_CARRY select -assert-count 8 t:SB_DFFR select -assert-count 8 t:SB_LUT4 select -assert-none t:SB_CARRY t:SB_DFFR t:SB_LUT4 %% t:* %D From 7e2825a2a4ad9c44fc7c0e7b45c1f926bc896ee5 Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 30 Aug 2019 09:42:33 +0000 Subject: [PATCH 121/130] ecp5: fix CEMUX on IFS/OFS primitives. --- techlibs/ecp5/cells_map.v | 16 ++++++++-------- techlibs/ecp5/cells_sim.v | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v index 0a92d906d..3fc874d94 100644 --- a/techlibs/ecp5/cells_map.v +++ b/techlibs/ecp5/cells_map.v @@ -85,15 +85,15 @@ module ILVDS(input A, AN, output Z); TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLA module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(Z), .I(A)); endmodule // Diamond I/O registers -module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule // TODO: Diamond I/O latches // module IFS1S1B(input PD, D, SCLK, output Q); endmodule diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index dc8334acb..16697c2f7 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -731,15 +731,15 @@ module ILVDS(input A, AN, output Z); TRELLIS_IO #(.DIR("INPUT")) tio (.B(A), .O module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(Z), .I(A)); endmodule // Diamond I/O registers -module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule // TODO: Diamond I/O latches // module IFS1S1B(input PD, D, SCLK, output Q); endmodule From 6fa8ce93e673177b50888aa94d7f1c8b221d9b10 Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 30 Aug 2019 09:54:48 +0000 Subject: [PATCH 122/130] ecp5: add missing FD primitives. --- techlibs/ecp5/cells_map.v | 74 ++++++++++++++++++++------------------- techlibs/ecp5/cells_sim.v | 74 ++++++++++++++++++++------------------- 2 files changed, 76 insertions(+), 72 deletions(-) diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v index 3fc874d94..100a3e377 100644 --- a/techlibs/ecp5/cells_map.v +++ b/techlibs/ecp5/cells_map.v @@ -47,19 +47,21 @@ module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), . module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -// TODO: Diamond flip-flops -// module FD1P3AX(); endmodule -// module FD1P3AY(); endmodule -// module FD1P3BX(); endmodule -// module FD1P3DX(); endmodule -// module FD1P3IX(); endmodule -// module FD1P3JX(); endmodule -// module FD1S3AX(); endmodule -// module FD1S3AY(); endmodule -module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule -module FD1S3DX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule -module FD1S3IX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule -module FD1S3JX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule +// Diamond flip-flops +module FD1P3AX(input D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3AY(input D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3BX(input PD, D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3DX(input CD, D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3IX(input CD, D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3JX(input PD, D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1S3AX(input D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule +module FD1S3AY(input D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule +module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule +module FD1S3DX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule +module FD1S3IX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule +module FD1S3JX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule + +// TODO: Diamond latches // module FL1P3AY(); endmodule // module FL1P3AZ(); endmodule // module FL1P3BX(); endmodule @@ -69,31 +71,16 @@ module FD1S3JX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX // module FL1S3AX(); endmodule // module FL1S3AY(); endmodule -// Diamond I/O buffers -module IB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule -module IBPU (input I, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule -module IBPD (input I, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule -module OB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I)); endmodule -module OBZ (input I, T, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule -module OBZPU(input I, T, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule -module OBZPD(input I, T, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule -module OBCO (input I, output OT, OC); OLVDS _TECHMAP_REPLACE_ (.A(I), .Z(OT), .ZN(OC)); endmodule -module BB (input I, T, output O, inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule -module BBPU (input I, T, output O, inout B); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule -module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule -module ILVDS(input A, AN, output Z); TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(A), .O(Z)); endmodule -module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(Z), .I(A)); endmodule - // Diamond I/O registers -module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule // TODO: Diamond I/O latches // module IFS1S1B(input PD, D, SCLK, output Q); endmodule @@ -101,6 +88,21 @@ module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), // module IFS1S1I(input PD, D, SCLK, output Q); endmodule // module IFS1S1J(input CD, D, SCLK, output Q); endmodule +// Diamond I/O buffers +module IB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule +module IBPU (input I, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule +module IBPD (input I, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule +module OB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I)); endmodule +module OBZ (input I, T, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule +module OBZPU(input I, T, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule +module OBZPD(input I, T, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule +module OBCO (input I, output OT, OC); OLVDS olvds (.A(I), .Z(OT), .ZN(OC)); endmodule +module BB (input I, T, output O, inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule +module BBPU (input I, T, output O, inout B); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule +module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule +module ILVDS(input A, AN, output Z ); TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(A), .O(Z)); endmodule +module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(Z), .I(A)); endmodule + `ifndef NO_LUT module \$lut (A, Y); parameter WIDTH = 0; diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 16697c2f7..50b6012e9 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -693,19 +693,21 @@ module DP16KD( parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; endmodule -// TODO: Diamond flip-flops -// module FD1P3AX(); endmodule -// module FD1P3AY(); endmodule -// module FD1P3BX(); endmodule -// module FD1P3DX(); endmodule -// module FD1P3IX(); endmodule -// module FD1P3JX(); endmodule -// module FD1S3AX(); endmodule -// module FD1S3AY(); endmodule -module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) tff (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule -module FD1S3DX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) tff (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule -module FD1S3IX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule -module FD1S3JX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule +// Diamond flip-flops +module FD1P3AX(input D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3AY(input D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3BX(input PD, D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3DX(input CD, D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3IX(input CD, D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3JX(input PD, D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1S3AX(input D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule +module FD1S3AY(input D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule +module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule +module FD1S3DX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule +module FD1S3IX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule +module FD1S3JX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule + +// TODO: Diamond latches // module FL1P3AY(); endmodule // module FL1P3AZ(); endmodule // module FL1P3BX(); endmodule @@ -715,34 +717,34 @@ module FD1S3JX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX // module FL1S3AX(); endmodule // module FL1S3AY(); endmodule -// Diamond I/O buffers -module IB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT")) tio (.B(I), .O(O)); endmodule -module IBPU (input I, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("INPUT")) tio (.B(I), .O(O)); endmodule -module IBPD (input I, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT")) tio (.B(I), .O(O)); endmodule -module OB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I)); endmodule -module OBZ (input I, T, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I), .T(T)); endmodule -module OBZPU(input I, T, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I), .T(T)); endmodule -module OBZPD(input I, T, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I), .T(T)); endmodule -module OBCO (input I, output OT, OC); OLVDS olvds (.A(I), .Z(OT), .ZN(OC)); endmodule -module BB (input I, T, output O, inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) tio (.B(B), .I(I), .O(O), .T(T)); endmodule -module BBPU (input I, T, output O, inout B); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("BIDIR")) tio (.B(B), .I(I), .O(O), .T(T)); endmodule -module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) tio (.B(B), .I(I), .O(O), .T(T)); endmodule -module ILVDS(input A, AN, output Z); TRELLIS_IO #(.DIR("INPUT")) tio (.B(A), .O(Z)); endmodule -module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(Z), .I(A)); endmodule - // Diamond I/O registers -module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule // TODO: Diamond I/O latches // module IFS1S1B(input PD, D, SCLK, output Q); endmodule // module IFS1S1D(input CD, D, SCLK, output Q); endmodule // module IFS1S1I(input PD, D, SCLK, output Q); endmodule // module IFS1S1J(input CD, D, SCLK, output Q); endmodule + +// Diamond I/O buffers +module IB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule +module IBPU (input I, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule +module IBPD (input I, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule +module OB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I)); endmodule +module OBZ (input I, T, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule +module OBZPU(input I, T, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule +module OBZPD(input I, T, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule +module OBCO (input I, output OT, OC); OLVDS olvds (.A(I), .Z(OT), .ZN(OC)); endmodule +module BB (input I, T, output O, inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule +module BBPU (input I, T, output O, inout B); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule +module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule +module ILVDS(input A, AN, output Z ); TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(A), .O(Z)); endmodule +module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(Z), .I(A)); endmodule From 1e6b60d563f8e51c521cae81de5d66bff40b943f Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 30 Aug 2019 09:56:19 +0000 Subject: [PATCH 123/130] ecp5: allow (and enable by default) GSR on FD/IFS/OFS primitives. --- techlibs/ecp5/cells_map.v | 55 ++++++++++++++------------------------- 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v index 100a3e377..7c5f140c6 100644 --- a/techlibs/ecp5/cells_map.v +++ b/techlibs/ecp5/cells_map.v @@ -48,18 +48,18 @@ module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), . module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule // Diamond flip-flops -module FD1P3AX(input D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3AY(input D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3BX(input PD, D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3DX(input CD, D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3IX(input CD, D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3JX(input PD, D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1S3AX(input D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule -module FD1S3AY(input D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule -module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule -module FD1S3DX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule -module FD1S3IX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule -module FD1S3JX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule +module FD1P3AX(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3AY(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3BX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3DX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3IX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3JX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1S3AX(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule +module FD1S3AY(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule +module FD1S3BX(input PD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule +module FD1S3DX(input CD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule +module FD1S3IX(input CD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule +module FD1S3JX(input PD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule // TODO: Diamond latches // module FL1P3AY(); endmodule @@ -72,15 +72,15 @@ module FD1S3JX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .C // module FL1S3AY(); endmodule // Diamond I/O registers -module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule // TODO: Diamond I/O latches // module IFS1S1B(input PD, D, SCLK, output Q); endmodule @@ -88,21 +88,6 @@ module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), // module IFS1S1I(input PD, D, SCLK, output Q); endmodule // module IFS1S1J(input CD, D, SCLK, output Q); endmodule -// Diamond I/O buffers -module IB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule -module IBPU (input I, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule -module IBPD (input I, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule -module OB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I)); endmodule -module OBZ (input I, T, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule -module OBZPU(input I, T, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule -module OBZPD(input I, T, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule -module OBCO (input I, output OT, OC); OLVDS olvds (.A(I), .Z(OT), .ZN(OC)); endmodule -module BB (input I, T, output O, inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule -module BBPU (input I, T, output O, inout B); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule -module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule -module ILVDS(input A, AN, output Z ); TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(A), .O(Z)); endmodule -module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(Z), .I(A)); endmodule - `ifndef NO_LUT module \$lut (A, Y); parameter WIDTH = 0; From d9c621f9d1e1f8e38fc38e78ab8c1bf48282fd01 Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 30 Aug 2019 10:05:09 +0000 Subject: [PATCH 124/130] ecp5: deduplicate Diamond FD/IFS/OFS/IO primitives. --- techlibs/ecp5/Makefile.inc | 2 ++ techlibs/ecp5/cells_ff.vh | 40 ++++++++++++++++++++++++++ techlibs/ecp5/cells_io.vh | 14 ++++++++++ techlibs/ecp5/cells_map.v | 42 ++-------------------------- techlibs/ecp5/cells_sim.v | 57 ++------------------------------------ 5 files changed, 60 insertions(+), 95 deletions(-) create mode 100644 techlibs/ecp5/cells_ff.vh create mode 100644 techlibs/ecp5/cells_io.vh diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc index c41d16076..2143acae6 100644 --- a/techlibs/ecp5/Makefile.inc +++ b/techlibs/ecp5/Makefile.inc @@ -2,6 +2,8 @@ OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o \ techlibs/ecp5/ecp5_gsr.o +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_ff.vh)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_io.vh)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_bb.v)) diff --git a/techlibs/ecp5/cells_ff.vh b/techlibs/ecp5/cells_ff.vh new file mode 100644 index 000000000..0c9689ebd --- /dev/null +++ b/techlibs/ecp5/cells_ff.vh @@ -0,0 +1,40 @@ +// Diamond flip-flops +module FD1P3AX(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3AY(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3BX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3DX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3IX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1P3JX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module FD1S3AX(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule +module FD1S3AY(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule +module FD1S3BX(input PD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule +module FD1S3DX(input CD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule +module FD1S3IX(input CD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule +module FD1S3JX(input PD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule + +// TODO: Diamond latches +// module FL1P3AY(); endmodule +// module FL1P3AZ(); endmodule +// module FL1P3BX(); endmodule +// module FL1P3DX(); endmodule +// module FL1P3IY(); endmodule +// module FL1P3JY(); endmodule +// module FL1S3AX(); endmodule +// module FL1S3AY(); endmodule + +// Diamond I/O registers +module IFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule + +module OFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule + +// TODO: Diamond I/O latches +// module IFS1S1B(input PD, D, SCLK, output Q); endmodule +// module IFS1S1D(input CD, D, SCLK, output Q); endmodule +// module IFS1S1I(input PD, D, SCLK, output Q); endmodule +// module IFS1S1J(input CD, D, SCLK, output Q); endmodule diff --git a/techlibs/ecp5/cells_io.vh b/techlibs/ecp5/cells_io.vh new file mode 100644 index 000000000..02e66e8a5 --- /dev/null +++ b/techlibs/ecp5/cells_io.vh @@ -0,0 +1,14 @@ +// Diamond I/O buffers +module IB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule +module IBPU (input I, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule +module IBPD (input I, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule +module OB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I)); endmodule +module OBZ (input I, T, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule +module OBZPU(input I, T, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule +module OBZPD(input I, T, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule +module OBCO (input I, output OT, OC); OLVDS olvds (.A(I), .Z(OT), .ZN(OC)); endmodule +module BB (input I, T, output O, inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule +module BBPU (input I, T, output O, inout B); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule +module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule +module ILVDS(input A, AN, output Z ); TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(A), .O(Z)); endmodule +module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(Z), .I(A)); endmodule diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v index 7c5f140c6..71ae9237b 100644 --- a/techlibs/ecp5/cells_map.v +++ b/techlibs/ecp5/cells_map.v @@ -47,46 +47,8 @@ module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), . module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -// Diamond flip-flops -module FD1P3AX(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3AY(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3BX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3DX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3IX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3JX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1S3AX(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule -module FD1S3AY(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule -module FD1S3BX(input PD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule -module FD1S3DX(input CD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule -module FD1S3IX(input CD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule -module FD1S3JX(input PD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule - -// TODO: Diamond latches -// module FL1P3AY(); endmodule -// module FL1P3AZ(); endmodule -// module FL1P3BX(); endmodule -// module FL1P3DX(); endmodule -// module FL1P3IY(); endmodule -// module FL1P3JY(); endmodule -// module FL1S3AX(); endmodule -// module FL1S3AY(); endmodule - -// Diamond I/O registers -module IFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule - -module OFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule - -// TODO: Diamond I/O latches -// module IFS1S1B(input PD, D, SCLK, output Q); endmodule -// module IFS1S1D(input CD, D, SCLK, output Q); endmodule -// module IFS1S1I(input PD, D, SCLK, output Q); endmodule -// module IFS1S1J(input CD, D, SCLK, output Q); endmodule +`include "cells_ff.vh" +`include "cells_io.vh" `ifndef NO_LUT module \$lut (A, Y); diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 50b6012e9..ba5b9c715 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -693,58 +693,5 @@ module DP16KD( parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; endmodule -// Diamond flip-flops -module FD1P3AX(input D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3AY(input D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3BX(input PD, D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3DX(input CD, D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3IX(input CD, D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1P3JX(input PD, D, SP, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module FD1S3AX(input D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule -module FD1S3AY(input D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(0), .DI(D), .Q(Q)); endmodule -module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule -module FD1S3DX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule -module FD1S3IX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule -module FD1S3JX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule - -// TODO: Diamond latches -// module FL1P3AY(); endmodule -// module FL1P3AZ(); endmodule -// module FL1P3BX(); endmodule -// module FL1P3DX(); endmodule -// module FL1P3IY(); endmodule -// module FL1P3JY(); endmodule -// module FL1S3AX(); endmodule -// module FL1S3AY(); endmodule - -// Diamond I/O registers -module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule - -module OFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule - -// TODO: Diamond I/O latches -// module IFS1S1B(input PD, D, SCLK, output Q); endmodule -// module IFS1S1D(input CD, D, SCLK, output Q); endmodule -// module IFS1S1I(input PD, D, SCLK, output Q); endmodule -// module IFS1S1J(input CD, D, SCLK, output Q); endmodule - -// Diamond I/O buffers -module IB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule -module IBPU (input I, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule -module IBPD (input I, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule -module OB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I)); endmodule -module OBZ (input I, T, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule -module OBZPU(input I, T, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule -module OBZPD(input I, T, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule -module OBCO (input I, output OT, OC); OLVDS olvds (.A(I), .Z(OT), .ZN(OC)); endmodule -module BB (input I, T, output O, inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule -module BBPU (input I, T, output O, inout B); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule -module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule -module ILVDS(input A, AN, output Z ); TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(A), .O(Z)); endmodule -module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(Z), .I(A)); endmodule +`include "cells_ff.vh" +`include "cells_io.vh" From f4a48ce8e6785fe9828b8896b9a60a74580dc2eb Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Fri, 30 Aug 2019 13:22:11 +0300 Subject: [PATCH 125/130] fix div_mod test --- tests/ice40/div_mod.ys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ice40/div_mod.ys b/tests/ice40/div_mod.ys index 96753b4ef..f55490572 100644 --- a/tests/ice40/div_mod.ys +++ b/tests/ice40/div_mod.ys @@ -4,6 +4,6 @@ flatten equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module -select -assert-count 88 t:SB_LUT4 +select -assert-count 62 t:SB_LUT4 select -assert-count 65 t:SB_CARRY select -assert-none t:SB_LUT4 t:SB_CARRY %% t:* %D From 94a56c14b78a2872d65bb30371151e934a259275 Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Fri, 30 Aug 2019 14:17:03 +0300 Subject: [PATCH 126/130] div_mod test fix --- tests/ice40/div_mod.ys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ice40/div_mod.ys b/tests/ice40/div_mod.ys index f55490572..21cac7144 100644 --- a/tests/ice40/div_mod.ys +++ b/tests/ice40/div_mod.ys @@ -5,5 +5,5 @@ equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 62 t:SB_LUT4 -select -assert-count 65 t:SB_CARRY +select -assert-count 41 t:SB_CARRY select -assert-none t:SB_LUT4 t:SB_CARRY %% t:* %D From 17c92dc679458a9ffabd76e2ce8e2491bd249110 Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Fri, 30 Aug 2019 15:22:46 +0300 Subject: [PATCH 127/130] Fix macc test --- tests/ice40/macc.ys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ice40/macc.ys b/tests/ice40/macc.ys index 233e7e890..d65c31b73 100644 --- a/tests/ice40/macc.ys +++ b/tests/ice40/macc.ys @@ -4,7 +4,7 @@ hierarchy -top top equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -dsp # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module -select -assert-count 41 t:SB_LUT4 +select -assert-count 38 t:SB_LUT4 select -assert-count 6 t:SB_CARRY select -assert-count 7 t:SB_DFFSR select -assert-none t:SB_LUT4 t:SB_CARRY t:SB_DFFSR %% t:* %D From 91b46ed81670de621af2d88a4da32005a17a2f16 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 30 Aug 2019 13:25:55 +0100 Subject: [PATCH 128/130] ecp5: Add simulation equivalence check for Diamond FF implementations Signed-off-by: David Shah --- techlibs/ecp5/cells_sim.v | 4 ++ techlibs/ecp5/tests/.gitignore | 1 + techlibs/ecp5/tests/test_diamond_ffs.py | 82 +++++++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 techlibs/ecp5/tests/.gitignore create mode 100644 techlibs/ecp5/tests/test_diamond_ffs.py diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index ba5b9c715..75a1aad1f 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -693,5 +693,9 @@ module DP16KD( parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; endmodule +`ifndef NO_INCLUDES + `include "cells_ff.vh" `include "cells_io.vh" + +`endif diff --git a/techlibs/ecp5/tests/.gitignore b/techlibs/ecp5/tests/.gitignore new file mode 100644 index 000000000..0e18132cc --- /dev/null +++ b/techlibs/ecp5/tests/.gitignore @@ -0,0 +1 @@ +work_* diff --git a/techlibs/ecp5/tests/test_diamond_ffs.py b/techlibs/ecp5/tests/test_diamond_ffs.py new file mode 100644 index 000000000..1ed85ce8b --- /dev/null +++ b/techlibs/ecp5/tests/test_diamond_ffs.py @@ -0,0 +1,82 @@ +import os +import subprocess + +if not os.path.exists("work_ff"): + os.mkdir("work_ff") + +modules = [] + +with open("../cells_ff.vh", "r") as f: + with open("work_ff/cells_ff_gate.v", "w") as g: + for line in f: + if not line.startswith("module"): + g.write(line) + continue + else: + spidx = line.find(" ") + bridx = line.find("(") + modname = line[spidx+1 : bridx] + g.write("module %s_gate" % modname) + g.write(line[bridx:]) + inpidx = line.find("input ") + outpidx = line.find(", output") + modules.append((modname, [x.strip() for x in line[inpidx+6:outpidx].split(",")])) + +with open("work_ff/testbench.v", "w") as f: + print(""" +`timescale 1ns/ 1ps + +module testbench; +reg pur = 0, clk, rst, cen, d; + +// Needed for Diamond sim models +GSR GSR_INST (.GSR(1'b1)); +PUR PUR_INST (.PUR(pur)); + + +initial begin + $dumpfile("work_ff/ffs.vcd"); + $dumpvars(0, testbench); + #5; + pur = 1; + #95; + repeat (2500) begin + {clk, rst, cen, d} = $random; + #10; + check_outputs; + #1; + end + $finish; +end + """, file=f) + + for modname, inputs in modules: + print(" wire %s_gold_q, %s_gate_q;" % (modname, modname), file=f) + portconns = [] + for inp in inputs: + if inp in ("SCLK", "CK"): + portconns.append(".%s(clk)" % inp) + elif inp in ("CD", "PD"): + portconns.append(".%s(rst)" % inp) + elif inp == "SP": + portconns.append(".%s(cen)" % inp) + elif inp == "D": + portconns.append(".%s(d)" % inp) + else: + assert False + portconns.append(".Q(%s_gold_q)" % modname) + print(" %s %s_gold_i (%s);" % (modname, modname, ", ".join(portconns)), file=f) + portconns[-1] = (".Q(%s_gate_q)" % modname) + print(" %s_gate %s_gate_i (%s);" % (modname, modname, ", ".join(portconns)), file=f) + print("", file=f) + print(" task check_outputs;", file=f) + print(" begin", file=f) + print(" if (%s_gold_q != %s_gate_q) $display(\"MISMATCH at %%1t: %s_gold_q=%%b, %s_gate_q=%%b\", $time, %s_gold_q, %s_gate_q);" % + (modname, modname, modname, modname, modname, modname), file=f) + print(" end", file=f) + print(" endtask", file=f) + print("endmodule", file=f) + +diamond_models = "/usr/local/diamond/3.10_x64/cae_library/simulation/verilog/ecp5u" +subprocess.call(["iverilog", "-s", "testbench", "-o", "work_ff/testbench", "-Dmixed_hdl", "-DNO_INCLUDES", "-y", diamond_models, "work_ff/cells_ff_gate.v", "../cells_sim.v", "work_ff/testbench.v"]) +subprocess.call(["vvp", "work_ff/testbench"]) From 53912ad649d6e9f447b9e4037255606783a0cf51 Mon Sep 17 00:00:00 2001 From: SergeyDegtyar Date: Fri, 30 Aug 2019 16:01:36 +0300 Subject: [PATCH 129/130] macc test fix --- tests/ice40/macc.ys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ice40/macc.ys b/tests/ice40/macc.ys index d65c31b73..fe5b5f662 100644 --- a/tests/ice40/macc.ys +++ b/tests/ice40/macc.ys @@ -5,6 +5,6 @@ equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 -dsp # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 38 t:SB_LUT4 -select -assert-count 6 t:SB_CARRY +select -assert-count 3 t:SB_CARRY select -assert-count 7 t:SB_DFFSR select -assert-none t:SB_LUT4 t:SB_CARRY t:SB_DFFSR %% t:* %D From 9c4e1c6a8fc47f44011f1f75e9493a1bc2de520d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 30 Aug 2019 10:27:07 -0700 Subject: [PATCH 130/130] Format `-pwires` --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 38ca77862..0195248a0 100644 --- a/README.md +++ b/README.md @@ -330,7 +330,7 @@ Verilog Attributes and non-standard features - The ``parameter`` and ``localparam`` attributes are used to mark wires that represent module parameters or localparams (when the HDL front-end - is run in -pwires mode). + is run in ``-pwires`` mode). - The ``clkbuf_driver`` attribute can be set on an output port of a blackbox module to mark it as a clock buffer output, and thus prevent ``clkbufmap``