From c29f0c5048fce87258eb4a4b204b6584efe0170c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 28 Feb 2019 09:31:24 -0800 Subject: [PATCH 01/64] Add techmap rule for $__SHREG_DFF_P_ to SRL16/32 --- techlibs/xilinx/cells_map.v | 71 +++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 0771be0b9..bd115e305 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -84,3 +84,74 @@ module \$lut (A, Y); endgenerate endmodule `endif + +module \$__SHREG_DFF_P_ (input C, input D, output Q); + parameter DEPTH = 0; + parameter [DEPTH-1:0] INIT = 0; + generate + if (DEPTH == 1) begin + if (INIT == 0) + (* init=0 *) \$_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); + else if (INIT == 1) + (* init=1 *) \$_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); + else + \$_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); + end else + if (DEPTH <= 16) begin + SRL16E #(.INIT(INIT), .IS_CLK_INVERTED(|0)) _TECHMAP_REPLACE_ (.A0(DEPTH[0]), .A1(DEPTH[1]), .A2(DEPTH[2]), .A3(DEPTH[3]), .CE(1'b1), .CLK(C), .D(D), .Q(Q)); + end else + if (DEPTH == 17) begin + wire T0; + \$__SHREG_DFF_P_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0])) fpga_srl_0 (.C(C), .D(D), .Q(T0)); + \$__SHREG_DFF_P_ #(.DEPTH(1), .INIT(INIT[DEPTH-1])) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); + end else + if (DEPTH <= 32) begin + SRLC32E #(.INIT(INIT), .IS_CLK_INVERTED(|0)) _TECHMAP_REPLACE_ (.A(DEPTH), .CE(1'b1), .CLK(C), .D(D), .Q(Q)); + end else + if (DEPTH == 33 || DEPTH == 49) begin + wire T0; + \$__SHREG_DFF_P_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0])) fpga_srl_0 (.C(C), .D(D), .Q(T0)); + \$__SHREG_DFF_P_ #(.DEPTH(1), .INIT(INIT[DEPTH-1])) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); + end else + if (DEPTH <= 64) begin + wire T0, T1, T2; + SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(|0)) fpga_srl_0 (.A(DEPTH), .CE(1'b1), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + \$__SHREG_DFF_P_ #(.DEPTH(DEPTH-32), .INIT(INIT[DEPTH-1:32])) fpga_srl_1 (.C(C), .D(T1), .Q(T2)); + MUXF7 fpga_mux_0 (.O(Q), .I0(T0), .I1(T2), .S(DEPTH[5])); + end else + if (DEPTH == 65 || DEPTH == 81) begin + wire T0; + \$__SHREG_DFF_P_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0])) fpga_srl_0 (.C(C), .D(D), .Q(T0)); + \$__SHREG_DFF_P_ #(.DEPTH(1), .INIT(INIT[DEPTH-1])) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); + end else + if (DEPTH <= 96) begin + wire T0, T1, T2, T3, T4, T5, T6; + SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(|0)) fpga_srl_0 (.A(DEPTH[4:0]), .CE(1'b1), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(|0)) fpga_srl_1 (.A(DEPTH[4:0]), .CE(1'b1), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + \$__SHREG_DFF_P_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-1:64])) fpga_srl_2 (.C(C), .D(T3), .Q(T4)); + MUXF7 fpga_mux_0 (.O(T5), .I0(T0), .I1(T2), .S(DEPTH[5])); + MUXF7 fpga_mux_1 (.O(T6), .I0(T4), .I1(1'b0 /* unused */), .S(DEPTH[5])); + MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(DEPTH[6])); + end else + if (DEPTH == 97 || DEPTH == 113) begin + wire T0; + \$__SHREG_DFF_P_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0])) fpga_srl_0 (.C(C), .D(D), .Q(T0)); + \$__SHREG_DFF_P_ #(.DEPTH(1), .INIT(INIT[DEPTH-1])) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); + end else + if (DEPTH <= 128) begin + wire T0, T1, T2, T3, T4, T5, T6, T7, T8; + SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(|0)) fpga_srl_0 (.A(DEPTH[4:0]), .CE(1'b1), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(|0)) fpga_srl_1 (.A(DEPTH[4:0]), .CE(1'b1), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + SRLC32E #(.INIT(INIT[96-1:64]), .IS_CLK_INVERTED(|0)) fpga_srl_2 (.A(DEPTH[4:0]), .CE(1'b1), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); + \$__SHREG_DFF_P_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-1:96])) fpga_srl_3 (.C(C), .D(T5), .Q(T6)); + MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(DEPTH[5])); + MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(DEPTH[5])); + MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(DEPTH[6])); + end else + begin + wire T0, T1; + \$__SHREG_DFF_P_ #(.DEPTH(128), .INIT(INIT[128-1:0])) fpga_srl_0 (.C(C), .D(D), .Q(T0)); + \$__SHREG_DFF_P_ #(.DEPTH(DEPTH-128), .INIT(INIT[DEPTH-1:128])) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); + end + endgenerate +endmodule From c9ab18889a63f74534c6fe9184ccb32e3661ab90 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 28 Feb 2019 09:32:29 -0800 Subject: [PATCH 02/64] synth_xilinx to now have shregmap call after dff2dffe --- techlibs/xilinx/synth_xilinx.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 6c11d885d..afd868743 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -103,6 +103,7 @@ struct SynthXilinxPass : public Pass log(" memory_map\n"); log(" dffsr2dff\n"); log(" dff2dffe\n"); + log(" shregmap -init\n"); log(" opt -full\n"); log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v\n"); log(" opt -fast\n"); @@ -222,6 +223,7 @@ struct SynthXilinxPass : public Pass Pass::call(design, "memory_map"); Pass::call(design, "dffsr2dff"); Pass::call(design, "dff2dffe"); + Pass::call(design, "shregmap -init"); Pass::call(design, "opt -full"); Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v"); Pass::call(design, "opt -fast"); From 68f38f2ee0e82ac7250e8c4b257e33fd62d21544 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 28 Feb 2019 10:21:05 -0800 Subject: [PATCH 03/64] synth_xilinx to use shregmap with -params too --- techlibs/xilinx/cells_map.v | 39 +++++++++++++++------------------ techlibs/xilinx/synth_xilinx.cc | 2 +- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index bd115e305..3b0a69898 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -85,73 +85,70 @@ module \$lut (A, Y); endmodule `endif -module \$__SHREG_DFF_P_ (input C, input D, output Q); - parameter DEPTH = 0; +module \$__SHREG_ (input C, input D, output Q); + parameter DEPTH = 0; parameter [DEPTH-1:0] INIT = 0; + parameter CLKPOL = 0; + parameter ENPOL = 2; generate if (DEPTH == 1) begin - if (INIT == 0) - (* init=0 *) \$_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); - else if (INIT == 1) - (* init=1 *) \$_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); - else - \$_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); + FDRE #(.INIT(INIT), .IS_C_INVERTED(CLKPOL), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); end else if (DEPTH <= 16) begin SRL16E #(.INIT(INIT), .IS_CLK_INVERTED(|0)) _TECHMAP_REPLACE_ (.A0(DEPTH[0]), .A1(DEPTH[1]), .A2(DEPTH[2]), .A3(DEPTH[3]), .CE(1'b1), .CLK(C), .D(D), .Q(Q)); end else if (DEPTH == 17) begin wire T0; - \$__SHREG_DFF_P_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0])) fpga_srl_0 (.C(C), .D(D), .Q(T0)); - \$__SHREG_DFF_P_ #(.DEPTH(1), .INIT(INIT[DEPTH-1])) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); + \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .Q(T0)); + \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); end else if (DEPTH <= 32) begin SRLC32E #(.INIT(INIT), .IS_CLK_INVERTED(|0)) _TECHMAP_REPLACE_ (.A(DEPTH), .CE(1'b1), .CLK(C), .D(D), .Q(Q)); end else if (DEPTH == 33 || DEPTH == 49) begin wire T0; - \$__SHREG_DFF_P_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0])) fpga_srl_0 (.C(C), .D(D), .Q(T0)); - \$__SHREG_DFF_P_ #(.DEPTH(1), .INIT(INIT[DEPTH-1])) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); + \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .Q(T0)); + \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); end else if (DEPTH <= 64) begin wire T0, T1, T2; SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(|0)) fpga_srl_0 (.A(DEPTH), .CE(1'b1), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - \$__SHREG_DFF_P_ #(.DEPTH(DEPTH-32), .INIT(INIT[DEPTH-1:32])) fpga_srl_1 (.C(C), .D(T1), .Q(T2)); + \$__SHREG_ #(.DEPTH(DEPTH-32), .INIT(INIT[DEPTH-1:32]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .Q(T2)); MUXF7 fpga_mux_0 (.O(Q), .I0(T0), .I1(T2), .S(DEPTH[5])); end else if (DEPTH == 65 || DEPTH == 81) begin wire T0; - \$__SHREG_DFF_P_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0])) fpga_srl_0 (.C(C), .D(D), .Q(T0)); - \$__SHREG_DFF_P_ #(.DEPTH(1), .INIT(INIT[DEPTH-1])) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); + \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .Q(T0)); + \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); end else if (DEPTH <= 96) begin wire T0, T1, T2, T3, T4, T5, T6; SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(|0)) fpga_srl_0 (.A(DEPTH[4:0]), .CE(1'b1), .CLK(C), .D(D), .Q(T0), .Q31(T1)); SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(|0)) fpga_srl_1 (.A(DEPTH[4:0]), .CE(1'b1), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); - \$__SHREG_DFF_P_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-1:64])) fpga_srl_2 (.C(C), .D(T3), .Q(T4)); + \$__SHREG_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-1:64]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_2 (.C(C), .D(T3), .Q(T4)); MUXF7 fpga_mux_0 (.O(T5), .I0(T0), .I1(T2), .S(DEPTH[5])); MUXF7 fpga_mux_1 (.O(T6), .I0(T4), .I1(1'b0 /* unused */), .S(DEPTH[5])); MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(DEPTH[6])); end else if (DEPTH == 97 || DEPTH == 113) begin wire T0; - \$__SHREG_DFF_P_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0])) fpga_srl_0 (.C(C), .D(D), .Q(T0)); - \$__SHREG_DFF_P_ #(.DEPTH(1), .INIT(INIT[DEPTH-1])) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); + \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .Q(T0)); + \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); end else if (DEPTH <= 128) begin wire T0, T1, T2, T3, T4, T5, T6, T7, T8; SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(|0)) fpga_srl_0 (.A(DEPTH[4:0]), .CE(1'b1), .CLK(C), .D(D), .Q(T0), .Q31(T1)); SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(|0)) fpga_srl_1 (.A(DEPTH[4:0]), .CE(1'b1), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); SRLC32E #(.INIT(INIT[96-1:64]), .IS_CLK_INVERTED(|0)) fpga_srl_2 (.A(DEPTH[4:0]), .CE(1'b1), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); - \$__SHREG_DFF_P_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-1:96])) fpga_srl_3 (.C(C), .D(T5), .Q(T6)); + \$__SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-1:96]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .Q(T6)); MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(DEPTH[5])); MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(DEPTH[5])); MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(DEPTH[6])); end else begin wire T0, T1; - \$__SHREG_DFF_P_ #(.DEPTH(128), .INIT(INIT[128-1:0])) fpga_srl_0 (.C(C), .D(D), .Q(T0)); - \$__SHREG_DFF_P_ #(.DEPTH(DEPTH-128), .INIT(INIT[DEPTH-1:128])) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); + \$__SHREG_ #(.DEPTH(128), .INIT(INIT[128-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .Q(T0)); + \$__SHREG_ #(.DEPTH(DEPTH-128), .INIT(INIT[DEPTH-1:128]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); end endgenerate endmodule diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index afd868743..4e4139154 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -223,7 +223,7 @@ struct SynthXilinxPass : public Pass Pass::call(design, "memory_map"); Pass::call(design, "dffsr2dff"); Pass::call(design, "dff2dffe"); - Pass::call(design, "shregmap -init"); + Pass::call(design, "shregmap -init -params"); Pass::call(design, "opt -full"); Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v"); Pass::call(design, "opt -fast"); From fe4d6898de378260c659dca08398fa434d71f7f0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 28 Feb 2019 11:17:13 -0800 Subject: [PATCH 04/64] synth_xilinx to call shregmap with enable support --- techlibs/xilinx/cells_map.v | 51 ++++++++++++++++++--------------- techlibs/xilinx/synth_xilinx.cc | 2 +- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 3b0a69898..168cbfa04 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -85,70 +85,75 @@ module \$lut (A, Y); endmodule `endif -module \$__SHREG_ (input C, input D, output Q); +module \$__SHREG_ (input C, input D, input E, output Q); parameter DEPTH = 0; parameter [DEPTH-1:0] INIT = 0; parameter CLKPOL = 0; parameter ENPOL = 2; + wire CE; generate + if (ENPOL != 0) + assign CE = E; + else + assign CE = ~E; if (DEPTH == 1) begin - FDRE #(.INIT(INIT), .IS_C_INVERTED(CLKPOL), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); + FDRE #(.INIT(INIT), .IS_C_INVERTED(~CLKPOL[0]), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); end else if (DEPTH <= 16) begin - SRL16E #(.INIT(INIT), .IS_CLK_INVERTED(|0)) _TECHMAP_REPLACE_ (.A0(DEPTH[0]), .A1(DEPTH[1]), .A2(DEPTH[2]), .A3(DEPTH[3]), .CE(1'b1), .CLK(C), .D(D), .Q(Q)); + SRL16E #(.INIT(INIT), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A0(DEPTH[0]), .A1(DEPTH[1]), .A2(DEPTH[2]), .A3(DEPTH[3]), .CE(CE), .CLK(C), .D(D), .Q(Q)); end else if (DEPTH == 17) begin wire T0; - \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .Q(T0)); - \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); + \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); + \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); end else if (DEPTH <= 32) begin - SRLC32E #(.INIT(INIT), .IS_CLK_INVERTED(|0)) _TECHMAP_REPLACE_ (.A(DEPTH), .CE(1'b1), .CLK(C), .D(D), .Q(Q)); + SRLC32E #(.INIT(INIT), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A(DEPTH), .CE(CE), .CLK(C), .D(D), .Q(Q)); end else if (DEPTH == 33 || DEPTH == 49) begin wire T0; - \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .Q(T0)); - \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); + \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); + \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); end else if (DEPTH <= 64) begin wire T0, T1, T2; - SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(|0)) fpga_srl_0 (.A(DEPTH), .CE(1'b1), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - \$__SHREG_ #(.DEPTH(DEPTH-32), .INIT(INIT[DEPTH-1:32]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .Q(T2)); + SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(DEPTH), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + \$__SHREG_ #(.DEPTH(DEPTH-32), .INIT(INIT[DEPTH-1:32]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .E(E), .Q(T2)); MUXF7 fpga_mux_0 (.O(Q), .I0(T0), .I1(T2), .S(DEPTH[5])); end else if (DEPTH == 65 || DEPTH == 81) begin wire T0; - \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .Q(T0)); - \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); + \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); + \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); end else if (DEPTH <= 96) begin wire T0, T1, T2, T3, T4, T5, T6; - SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(|0)) fpga_srl_0 (.A(DEPTH[4:0]), .CE(1'b1), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(|0)) fpga_srl_1 (.A(DEPTH[4:0]), .CE(1'b1), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); - \$__SHREG_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-1:64]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_2 (.C(C), .D(T3), .Q(T4)); + SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(DEPTH[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(DEPTH[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + \$__SHREG_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-1:64]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_2 (.C(C), .D(T3), .E(E), .Q(T4)); MUXF7 fpga_mux_0 (.O(T5), .I0(T0), .I1(T2), .S(DEPTH[5])); MUXF7 fpga_mux_1 (.O(T6), .I0(T4), .I1(1'b0 /* unused */), .S(DEPTH[5])); MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(DEPTH[6])); end else if (DEPTH == 97 || DEPTH == 113) begin wire T0; - \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .Q(T0)); - \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); + \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); + \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); end else if (DEPTH <= 128) begin wire T0, T1, T2, T3, T4, T5, T6, T7, T8; - SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(|0)) fpga_srl_0 (.A(DEPTH[4:0]), .CE(1'b1), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(|0)) fpga_srl_1 (.A(DEPTH[4:0]), .CE(1'b1), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); - SRLC32E #(.INIT(INIT[96-1:64]), .IS_CLK_INVERTED(|0)) fpga_srl_2 (.A(DEPTH[4:0]), .CE(1'b1), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); - \$__SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-1:96]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .Q(T6)); + SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(DEPTH[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(DEPTH[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + SRLC32E #(.INIT(INIT[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(DEPTH[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); + \$__SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-1:96]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .E(E), .Q(T6)); MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(DEPTH[5])); MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(DEPTH[5])); MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(DEPTH[6])); end else begin wire T0, T1; - \$__SHREG_ #(.DEPTH(128), .INIT(INIT[128-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .Q(T0)); - \$__SHREG_ #(.DEPTH(DEPTH-128), .INIT(INIT[DEPTH-1:128]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .Q(Q)); + \$__SHREG_ #(.DEPTH(128), .INIT(INIT[128-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); + \$__SHREG_ #(.DEPTH(DEPTH-128), .INIT(INIT[DEPTH-1:128]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); end endgenerate endmodule diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 4e4139154..280c6b729 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -223,7 +223,7 @@ struct SynthXilinxPass : public Pass Pass::call(design, "memory_map"); Pass::call(design, "dffsr2dff"); Pass::call(design, "dff2dffe"); - Pass::call(design, "shregmap -init -params"); + Pass::call(design, "shregmap -init -params -enpol any_or_none"); Pass::call(design, "opt -full"); Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v"); Pass::call(design, "opt -fast"); From 8aab7fe7e64b1c213d924126e30994ab7b6d4625 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 28 Feb 2019 13:56:00 -0800 Subject: [PATCH 05/64] Fix SRL16/32 techmap off-by-one --- techlibs/xilinx/cells_map.v | 42 +++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 168cbfa04..d2cc96969 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -88,19 +88,22 @@ endmodule module \$__SHREG_ (input C, input D, input E, output Q); parameter DEPTH = 0; parameter [DEPTH-1:0] INIT = 0; - parameter CLKPOL = 0; + parameter CLKPOL = 1; parameter ENPOL = 2; wire CE; generate - if (ENPOL != 0) + if (ENPOL == 0) + assign CE = ~E; + else if (ENPOL == 1) assign CE = E; else - assign CE = ~E; + assign CE = 1'b1; if (DEPTH == 1) begin FDRE #(.INIT(INIT), .IS_C_INVERTED(~CLKPOL[0]), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); end else if (DEPTH <= 16) begin - SRL16E #(.INIT(INIT), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A0(DEPTH[0]), .A1(DEPTH[1]), .A2(DEPTH[2]), .A3(DEPTH[3]), .CE(CE), .CLK(C), .D(D), .Q(Q)); + localparam [3:0] A = DEPTH - 1; + SRL16E #(.INIT(INIT), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A0(A[0]), .A1(A[1]), .A2(A[2]), .A3(A[3]), .CE(CE), .CLK(C), .D(D), .Q(Q)); end else if (DEPTH == 17) begin wire T0; @@ -108,7 +111,7 @@ module \$__SHREG_ (input C, input D, input E, output Q); \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); end else if (DEPTH <= 32) begin - SRLC32E #(.INIT(INIT), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A(DEPTH), .CE(CE), .CLK(C), .D(D), .Q(Q)); + SRLC32E #(.INIT(INIT), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A(DEPTH-1), .CE(CE), .CLK(C), .D(D), .Q(Q)); end else if (DEPTH == 33 || DEPTH == 49) begin wire T0; @@ -117,9 +120,10 @@ module \$__SHREG_ (input C, input D, input E, output Q); end else if (DEPTH <= 64) begin wire T0, T1, T2; - SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(DEPTH), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + localparam [5:0] A = DEPTH-1; + SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); \$__SHREG_ #(.DEPTH(DEPTH-32), .INIT(INIT[DEPTH-1:32]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .E(E), .Q(T2)); - MUXF7 fpga_mux_0 (.O(Q), .I0(T0), .I1(T2), .S(DEPTH[5])); + MUXF7 fpga_mux_0 (.O(Q), .I0(T0), .I1(T2), .S(A[5])); end else if (DEPTH == 65 || DEPTH == 81) begin wire T0; @@ -127,13 +131,14 @@ module \$__SHREG_ (input C, input D, input E, output Q); \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); end else if (DEPTH <= 96) begin + localparam [6:0] A = DEPTH-1; wire T0, T1, T2, T3, T4, T5, T6; - SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(DEPTH[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(DEPTH[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); \$__SHREG_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-1:64]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_2 (.C(C), .D(T3), .E(E), .Q(T4)); - MUXF7 fpga_mux_0 (.O(T5), .I0(T0), .I1(T2), .S(DEPTH[5])); - MUXF7 fpga_mux_1 (.O(T6), .I0(T4), .I1(1'b0 /* unused */), .S(DEPTH[5])); - MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(DEPTH[6])); + MUXF7 fpga_mux_0 (.O(T5), .I0(T0), .I1(T2), .S(A[5])); + MUXF7 fpga_mux_1 (.O(T6), .I0(T4), .I1(1'b0 /* unused */), .S(A[5])); + MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(A[6])); end else if (DEPTH == 97 || DEPTH == 113) begin wire T0; @@ -141,14 +146,15 @@ module \$__SHREG_ (input C, input D, input E, output Q); \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); end else if (DEPTH <= 128) begin + localparam [6:0] A = DEPTH-1; wire T0, T1, T2, T3, T4, T5, T6, T7, T8; - SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(DEPTH[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(DEPTH[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); - SRLC32E #(.INIT(INIT[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(DEPTH[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); + SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + SRLC32E #(.INIT(INIT[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); \$__SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-1:96]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .E(E), .Q(T6)); - MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(DEPTH[5])); - MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(DEPTH[5])); - MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(DEPTH[6])); + MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(A[5])); + MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(A[5])); + MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(A[6])); end else begin wire T0, T1; From 73ddab6960a02aef0c5f9ccee8cee2e666778c06 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 28 Feb 2019 13:56:22 -0800 Subject: [PATCH 06/64] Add SRL16 and SRL32 sim models --- techlibs/xilinx/cells_sim.v | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index eba17ac9c..68f678385 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -186,3 +186,42 @@ module RAM128X1D ( wire clk = WCLK ^ IS_WCLK_INVERTED; always @(posedge clk) if (WE) mem[A] <= D; endmodule + +module SRL16E ( + output Q, + input A0, A1, A2, A3, CE, CLK, D +); + parameter [15:0] INIT = 16'h0000; + parameter [0:0] IS_CLK_INVERTED = 1'b0; + + reg [15:0] r = INIT; + assign Q = r[{A3,A2,A1,A0}]; + generate + if (IS_CLK_INVERTED) begin + always @(negedge CLK) if (CE) r <= { r[14:0], D }; + end + else + always @(posedge CLK) if (CE) r <= { r[14:0], D }; + endgenerate +endmodule + +module SRLC32E ( + output Q, + output Q31, + input [4:0] A, + input CE, CLK, D +); + parameter [31:0] INIT = 32'h00000000; + parameter [0:0] IS_CLK_INVERTED = 1'b0; + + reg [31:0] r = INIT; + assign Q31 = r[31]; + assign Q = r[A]; + generate + if (IS_CLK_INVERTED) begin + always @(negedge CLK) if (CE) r <= { r[30:0], D }; + end + else + always @(posedge CLK) if (CE) r <= { r[30:0], D }; + endgenerate +endmodule From 1da090966263318c46dd1d91d2f1f4d11238c2c1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 28 Feb 2019 13:56:45 -0800 Subject: [PATCH 07/64] Remove SRL16/32 from cells_xtra --- techlibs/xilinx/cells_xtra.sh | 4 ++-- techlibs/xilinx/cells_xtra.v | 16 ---------------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/techlibs/xilinx/cells_xtra.sh b/techlibs/xilinx/cells_xtra.sh index 0480410f5..8cc90d1f2 100644 --- a/techlibs/xilinx/cells_xtra.sh +++ b/techlibs/xilinx/cells_xtra.sh @@ -134,8 +134,8 @@ function xtract_cell_decl() xtract_cell_decl ROM256X1 xtract_cell_decl ROM32X1 xtract_cell_decl ROM64X1 - xtract_cell_decl SRL16E - xtract_cell_decl SRLC32E + #xtract_cell_decl SRL16E + #xtract_cell_decl SRLC32E xtract_cell_decl STARTUPE2 xtract_cell_decl USR_ACCESSE2 xtract_cell_decl XADC diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v index 8d8b91ddc..21db6a6bd 100644 --- a/techlibs/xilinx/cells_xtra.v +++ b/techlibs/xilinx/cells_xtra.v @@ -3824,22 +3824,6 @@ module ROM64X1 (...); input A0, A1, A2, A3, A4, A5; endmodule -module SRL16E (...); - parameter [15:0] INIT = 16'h0000; - parameter [0:0] IS_CLK_INVERTED = 1'b0; - output Q; - input A0, A1, A2, A3, CE, CLK, D; -endmodule - -module SRLC32E (...); - parameter [31:0] INIT = 32'h00000000; - parameter [0:0] IS_CLK_INVERTED = 1'b0; - output Q; - output Q31; - input [4:0] A; - input CE, CLK, D; -endmodule - module STARTUPE2 (...); parameter PROG_USR = "FALSE"; parameter real SIM_CCLK_FREQ = 0.0; From 24f129ddfb6496226801861a15e4e9518217dd76 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Mar 2019 16:17:54 -0700 Subject: [PATCH 08/64] Refactor $__SHREG__ in cells_map.v --- techlibs/xilinx/cells_map.v | 56 ++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index d2cc96969..92358620e 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -105,32 +105,17 @@ module \$__SHREG_ (input C, input D, input E, output Q); localparam [3:0] A = DEPTH - 1; SRL16E #(.INIT(INIT), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A0(A[0]), .A1(A[1]), .A2(A[2]), .A3(A[3]), .CE(CE), .CLK(C), .D(D), .Q(Q)); end else - if (DEPTH == 17) begin - wire T0; - \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); - \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); - end else - if (DEPTH <= 32) begin + if (DEPTH > 17 && DEPTH <= 32) begin SRLC32E #(.INIT(INIT), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A(DEPTH-1), .CE(CE), .CLK(C), .D(D), .Q(Q)); end else - if (DEPTH == 33 || DEPTH == 49) begin - wire T0; - \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); - \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); - end else - if (DEPTH <= 64) begin + if (DEPTH > 33 && DEPTH <= 64) begin wire T0, T1, T2; localparam [5:0] A = DEPTH-1; SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); \$__SHREG_ #(.DEPTH(DEPTH-32), .INIT(INIT[DEPTH-1:32]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .E(E), .Q(T2)); MUXF7 fpga_mux_0 (.O(Q), .I0(T0), .I1(T2), .S(A[5])); end else - if (DEPTH == 65 || DEPTH == 81) begin - wire T0; - \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); - \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); - end else - if (DEPTH <= 96) begin + if (DEPTH > 65 && DEPTH <= 96) begin localparam [6:0] A = DEPTH-1; wire T0, T1, T2, T3, T4, T5, T6; SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); @@ -140,23 +125,30 @@ module \$__SHREG_ (input C, input D, input E, output Q); MUXF7 fpga_mux_1 (.O(T6), .I0(T4), .I1(1'b0 /* unused */), .S(A[5])); MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(A[6])); end else - if (DEPTH == 97 || DEPTH == 113) begin - wire T0; - \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); - \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); - end else if (DEPTH <= 128) begin - localparam [6:0] A = DEPTH-1; - wire T0, T1, T2, T3, T4, T5, T6, T7, T8; - SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); - SRLC32E #(.INIT(INIT[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); - \$__SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-1:96]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .E(E), .Q(T6)); - MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(A[5])); - MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(A[5])); - MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(A[6])); + if (DEPTH > 97) begin + localparam [6:0] A = DEPTH-1; + wire T0, T1, T2, T3, T4, T5, T6, T7, T8; + SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + SRLC32E #(.INIT(INIT[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); + \$__SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-1:96]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .E(E), .Q(T6)); + MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(A[5])); + MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(A[5])); + MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(A[6])); + end + // Handle case where depth is just 1 over a convenient value, + // in which case use the flop + else begin + wire T0; + \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); + \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); + end end else begin + // UG474 (v1.8, p34) states that: + // "There are no direct connections between slices to form longer shift + // registers, nor is the MC31 output at LUT B/C/D available." wire T0, T1; \$__SHREG_ #(.DEPTH(128), .INIT(INIT[128-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); \$__SHREG_ #(.DEPTH(DEPTH-128), .INIT(INIT[DEPTH-1:128]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); From edca2f116373df7819ec68906ce74f15456168c2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Mar 2019 17:13:52 -0700 Subject: [PATCH 09/64] Move shregmap until after first techmap --- techlibs/xilinx/synth_xilinx.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 280c6b729..ce597ea4a 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -103,9 +103,9 @@ struct SynthXilinxPass : public Pass log(" memory_map\n"); log(" dffsr2dff\n"); log(" dff2dffe\n"); - log(" shregmap -init\n"); log(" opt -full\n"); log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v\n"); + log(" shregmap -init -params -enpol any_or_none\n"); log(" opt -fast\n"); log("\n"); log(" map_luts:\n"); @@ -223,9 +223,9 @@ struct SynthXilinxPass : public Pass Pass::call(design, "memory_map"); Pass::call(design, "dffsr2dff"); Pass::call(design, "dff2dffe"); - Pass::call(design, "shregmap -init -params -enpol any_or_none"); Pass::call(design, "opt -full"); Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v"); + Pass::call(design, "shregmap -init -params -enpol any_or_none"); Pass::call(design, "opt -fast"); } From 79b4a275ce85d231186105b6e73a596ff3326e1f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Mar 2019 08:09:48 -0700 Subject: [PATCH 10/64] Fix cells_map for SRL --- techlibs/xilinx/cells_map.v | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 92358620e..0ace369d1 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -125,31 +125,29 @@ module \$__SHREG_ (input C, input D, input E, output Q); MUXF7 fpga_mux_1 (.O(T6), .I0(T4), .I1(1'b0 /* unused */), .S(A[5])); MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(A[6])); end else - if (DEPTH <= 128) begin - if (DEPTH > 97) begin - localparam [6:0] A = DEPTH-1; - wire T0, T1, T2, T3, T4, T5, T6, T7, T8; - SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); - SRLC32E #(.INIT(INIT[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); - \$__SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-1:96]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .E(E), .Q(T6)); - MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(A[5])); - MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(A[5])); - MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(A[6])); - end - // Handle case where depth is just 1 over a convenient value, + if (DEPTH > 97 && DEPTH <= 128) begin + localparam [6:0] A = DEPTH-1; + wire T0, T1, T2, T3, T4, T5, T6, T7, T8; + SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + SRLC32E #(.INIT(INIT[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); + \$__SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-1:96]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .E(E), .Q(T6)); + MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(A[5])); + MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(A[5])); + MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(A[6])); + end + else if (DEPTH <= 129) begin + // Handle cases where depth is just 1 over a convenient value, // in which case use the flop - else begin - wire T0; - \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); - \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); - end + wire T0; + \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); + \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); end else begin // UG474 (v1.8, p34) states that: // "There are no direct connections between slices to form longer shift // registers, nor is the MC31 output at LUT B/C/D available." - wire T0, T1; + wire T0; \$__SHREG_ #(.DEPTH(128), .INIT(INIT[128-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); \$__SHREG_ #(.DEPTH(DEPTH-128), .INIT(INIT[DEPTH-1:128]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); end From 26ecbc1aee1dca1c186ab2b51835d74f67bc3e75 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Mar 2019 08:10:02 -0700 Subject: [PATCH 11/64] Add shregmap -init_msb_first and use in synth_xilinx --- passes/techmap/shregmap.cc | 16 ++++++++++++++-- techlibs/xilinx/synth_xilinx.cc | 4 ++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index f20863ba0..6cd9082dc 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -34,7 +34,7 @@ struct ShregmapOptions { int minlen, maxlen; int keep_before, keep_after; - bool zinit, init, params, ffe; + bool zinit, init, params, ffe, init_msb_first; dict> ffcells; ShregmapTech *tech; @@ -48,6 +48,7 @@ struct ShregmapOptions init = false; params = false; ffe = false; + init_msb_first = false; tech = nullptr; } }; @@ -307,6 +308,8 @@ struct ShregmapWorker initval.push_back(State::S0); remove_init.insert(bit); } + if (opts.init_msb_first) + std::reverse(initval.begin(), initval.end()); first_cell->setParam("\\INIT", initval); } @@ -442,9 +445,13 @@ struct ShregmapPass : public Pass { log("\n"); log(" -init\n"); log(" map initialized registers to the shift reg, add an INIT parameter to\n"); - log(" generated cells with the initialization value. (first bit to shift out\n"); + log(" generated cells with the initialization value. (First bit to shift out\n"); log(" in LSB position)\n"); log("\n"); + log(" -init_msb_first\n"); + log(" same as -init, but INIT parameter to have first bit to shift out\n"); + log(" in MSB position.\n"); + log("\n"); log(" -tech greenpak4\n"); log(" map to greenpak4 shift registers.\n"); log("\n"); @@ -515,6 +522,11 @@ struct ShregmapPass : public Pass { opts.init = true; continue; } + if (args[argidx] == "-init_msb_first") { + opts.init = true; + opts.init_msb_first = true; + continue; + } if (args[argidx] == "-params") { opts.params = true; continue; diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index ce597ea4a..71b468e38 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -105,7 +105,7 @@ struct SynthXilinxPass : public Pass log(" dff2dffe\n"); log(" opt -full\n"); log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v\n"); - log(" shregmap -init -params -enpol any_or_none\n"); + log(" shregmap -init_msb_first -params -enpol any_or_none\n"); log(" opt -fast\n"); log("\n"); log(" map_luts:\n"); @@ -225,7 +225,7 @@ struct SynthXilinxPass : public Pass Pass::call(design, "dff2dffe"); Pass::call(design, "opt -full"); Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v"); - Pass::call(design, "shregmap -init -params -enpol any_or_none"); + Pass::call(design, "shregmap -init_msb_first -params -enpol any_or_none"); Pass::call(design, "opt -fast"); } From 8af9979aab5f1434ee7d0e56a85324d78e2fd9f9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Mar 2019 09:01:48 -0700 Subject: [PATCH 12/64] Revert "Add shregmap -init_msb_first and use in synth_xilinx" This reverts commit 26ecbc1aee1dca1c186ab2b51835d74f67bc3e75. --- passes/techmap/shregmap.cc | 16 ++-------------- techlibs/xilinx/synth_xilinx.cc | 5 ++--- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 6cd9082dc..f20863ba0 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -34,7 +34,7 @@ struct ShregmapOptions { int minlen, maxlen; int keep_before, keep_after; - bool zinit, init, params, ffe, init_msb_first; + bool zinit, init, params, ffe; dict> ffcells; ShregmapTech *tech; @@ -48,7 +48,6 @@ struct ShregmapOptions init = false; params = false; ffe = false; - init_msb_first = false; tech = nullptr; } }; @@ -308,8 +307,6 @@ struct ShregmapWorker initval.push_back(State::S0); remove_init.insert(bit); } - if (opts.init_msb_first) - std::reverse(initval.begin(), initval.end()); first_cell->setParam("\\INIT", initval); } @@ -445,13 +442,9 @@ struct ShregmapPass : public Pass { log("\n"); log(" -init\n"); log(" map initialized registers to the shift reg, add an INIT parameter to\n"); - log(" generated cells with the initialization value. (First bit to shift out\n"); + log(" generated cells with the initialization value. (first bit to shift out\n"); log(" in LSB position)\n"); log("\n"); - log(" -init_msb_first\n"); - log(" same as -init, but INIT parameter to have first bit to shift out\n"); - log(" in MSB position.\n"); - log("\n"); log(" -tech greenpak4\n"); log(" map to greenpak4 shift registers.\n"); log("\n"); @@ -522,11 +515,6 @@ struct ShregmapPass : public Pass { opts.init = true; continue; } - if (args[argidx] == "-init_msb_first") { - opts.init = true; - opts.init_msb_first = true; - continue; - } if (args[argidx] == "-params") { opts.params = true; continue; diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 169f3b7ce..1978ccf21 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -111,7 +111,7 @@ struct SynthXilinxPass : public Pass log(" dff2dffe\n"); log(" opt -full\n"); log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v\n"); - log(" shregmap -init_msb_first -params -enpol any_or_none\n"); + log(" shregmap -init -params -enpol any_or_none\n"); log(" techmap -map +/xilinx/ff_map.v\n"); log(" opt -fast\n"); log("\n"); @@ -262,9 +262,8 @@ struct SynthXilinxPass : public Pass Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v"); } - Pass::call(design, "shregmap -init_msb_first -params -enpol any_or_none"); + Pass::call(design, "shregmap -initt -params -enpol any_or_none"); Pass::call(design, "techmap -map +/xilinx/ff_map.v"); - Pass::call(design, "hierarchy -check"); Pass::call(design, "opt -fast"); } From af5706c2a38c010e6c7343aeb1c5d6e26a6b7799 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Mar 2019 09:06:56 -0700 Subject: [PATCH 13/64] Misspell --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 1978ccf21..f2c3833a4 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -262,7 +262,7 @@ struct SynthXilinxPass : public Pass Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v"); } - Pass::call(design, "shregmap -initt -params -enpol any_or_none"); + Pass::call(design, "shregmap -init -params -enpol any_or_none"); Pass::call(design, "techmap -map +/xilinx/ff_map.v"); Pass::call(design, "opt -fast"); } From e7ef7fa443c0b7c7ec9e4bbb15893053aed8c3ce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Mar 2019 09:38:42 -0700 Subject: [PATCH 14/64] Reverse bits in INIT parameter for Xilinx, since MSB is shifted first --- techlibs/xilinx/cells_map.v | 48 ++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 0c5c5a26f..69f8b85f4 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -23,6 +23,19 @@ module \$__SHREG_ (input C, input D, input E, output Q); parameter CLKPOL = 1; parameter ENPOL = 2; wire CE; + + // shregmap's INIT parameter shifts out LSB first; + // however Xilinx expects MSB first + function [DEPTH-1:0] brev; + input [DEPTH-1:0] din; + integer i; + begin + for (i = 0; i < DEPTH; i=i+1) + brev[i] = din[DEPTH-1-i]; + end + endfunction + localparam [DEPTH-1:0] INIT_R = brev(INIT); + generate if (ENPOL == 0) assign CE = ~E; @@ -31,28 +44,31 @@ module \$__SHREG_ (input C, input D, input E, output Q); else assign CE = 1'b1; if (DEPTH == 1) begin - FDRE #(.INIT(INIT), .IS_C_INVERTED(~CLKPOL[0]), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); + if (CLKPOL) + FDRE #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); + else + FDRE_1 #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); end else if (DEPTH <= 16) begin localparam [3:0] A = DEPTH - 1; - SRL16E #(.INIT(INIT), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A0(A[0]), .A1(A[1]), .A2(A[2]), .A3(A[3]), .CE(CE), .CLK(C), .D(D), .Q(Q)); + SRL16E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A0(A[0]), .A1(A[1]), .A2(A[2]), .A3(A[3]), .CE(CE), .CLK(C), .D(D), .Q(Q)); end else if (DEPTH > 17 && DEPTH <= 32) begin - SRLC32E #(.INIT(INIT), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A(DEPTH-1), .CE(CE), .CLK(C), .D(D), .Q(Q)); + SRLC32E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A(DEPTH-1), .CE(CE), .CLK(C), .D(D), .Q(Q)); end else if (DEPTH > 33 && DEPTH <= 64) begin wire T0, T1, T2; localparam [5:0] A = DEPTH-1; - SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - \$__SHREG_ #(.DEPTH(DEPTH-32), .INIT(INIT[DEPTH-1:32]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .E(E), .Q(T2)); + SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + \$__SHREG_ #(.DEPTH(DEPTH-32), .INIT(INIT[DEPTH-32-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .E(E), .Q(T2)); MUXF7 fpga_mux_0 (.O(Q), .I0(T0), .I1(T2), .S(A[5])); end else if (DEPTH > 65 && DEPTH <= 96) begin localparam [6:0] A = DEPTH-1; wire T0, T1, T2, T3, T4, T5, T6; - SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); - \$__SHREG_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-1:64]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_2 (.C(C), .D(T3), .E(E), .Q(T4)); + SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + \$__SHREG_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-64-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_2 (.C(C), .D(T3), .E(E), .Q(T4)); MUXF7 fpga_mux_0 (.O(T5), .I0(T0), .I1(T2), .S(A[5])); MUXF7 fpga_mux_1 (.O(T6), .I0(T4), .I1(1'b0 /* unused */), .S(A[5])); MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(A[6])); @@ -60,10 +76,10 @@ module \$__SHREG_ (input C, input D, input E, output Q); if (DEPTH > 97 && DEPTH <= 128) begin localparam [6:0] A = DEPTH-1; wire T0, T1, T2, T3, T4, T5, T6, T7, T8; - SRLC32E #(.INIT(INIT[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - SRLC32E #(.INIT(INIT[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); - SRLC32E #(.INIT(INIT[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); - \$__SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-1:96]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .E(E), .Q(T6)); + SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + SRLC32E #(.INIT(INIT_R[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); + \$__SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-96-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .E(E), .Q(T6)); MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(A[5])); MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(A[5])); MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(A[6])); @@ -72,16 +88,16 @@ module \$__SHREG_ (input C, input D, input E, output Q); // Handle cases where depth is just 1 over a convenient value, // in which case use the flop wire T0; - \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-2:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); - \$__SHREG_ #(.DEPTH(1), .INIT(INIT[DEPTH-1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); + \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-1:1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); + \$__SHREG_ #(.DEPTH(1), .INIT(INIT[0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); end else begin // UG474 (v1.8, p34) states that: // "There are no direct connections between slices to form longer shift // registers, nor is the MC31 output at LUT B/C/D available." wire T0; - \$__SHREG_ #(.DEPTH(128), .INIT(INIT[128-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); - \$__SHREG_ #(.DEPTH(DEPTH-128), .INIT(INIT[DEPTH-1:128]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); + \$__SHREG_ #(.DEPTH(128), .INIT(INIT[DEPTH-1:DEPTH-128]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); + \$__SHREG_ #(.DEPTH(DEPTH-128), .INIT(INIT[DEPTH-128-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); end endgenerate endmodule From 06f8f2654abdef8684bfe4f373ac42cb8c62ee2a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 15 Mar 2019 19:13:40 -0700 Subject: [PATCH 15/64] Working --- passes/techmap/shregmap.cc | 655 +++++++++++++++++++------------- techlibs/xilinx/cells_map.v | 109 ++++-- techlibs/xilinx/synth_xilinx.cc | 16 +- 3 files changed, 470 insertions(+), 310 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index f20863ba0..4b8f8a828 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -26,7 +26,9 @@ PRIVATE_NAMESPACE_BEGIN struct ShregmapTech { virtual ~ShregmapTech() { } - virtual bool analyze(vector &taps) = 0; + 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 fixup(Cell *cell, dict &taps) = 0; }; @@ -54,7 +56,7 @@ struct ShregmapOptions struct ShregmapTechGreenpak4 : ShregmapTech { - bool analyze(vector &taps) + bool analyze(vector &taps, const vector &/*qbits*/) { if (GetSize(taps) > 2 && taps[0] == 0 && taps[2] < 17) { taps.clear(); @@ -91,302 +93,423 @@ struct ShregmapTechGreenpak4 : ShregmapTech } }; +struct ShregmapTechXilinx7 : ShregmapTech +{ + dict sigbit_to_shiftx; + const ShregmapOptions &opts; + + ShregmapTechXilinx7(const ShregmapOptions &opts) : opts(opts) {} + + virtual void init(const Module* module, const SigMap &sigmap) override + { + for (auto i : module->cells_) { + auto cell = i.second; + if (cell->type != "$shiftx") continue; + if (cell->getParam("\\Y_WIDTH") != 1) continue; + for (auto bit : sigmap(cell->getPort("\\A"))) + sigbit_to_shiftx[bit] = cell; + } + } + + virtual void non_chain_user(const SigBit &bit, const Cell *cell, IdString port) override + { + auto it = sigbit_to_shiftx.find(bit); + if (it == sigbit_to_shiftx.end()) + return; + if (cell->type == "$shiftx" && port == "\\A") + return; + it->second = nullptr; + } + + virtual bool analyze(vector &taps, const vector &qbits) override + { + if (GetSize(taps) == 1) + return taps[0] >= opts.minlen-1; + + if (taps.back() < opts.minlen-1) + return false; + + Cell *shiftx = nullptr; + int offset = 0; + for (int i = 0; i < GetSize(taps); ++i) { + // 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 + auto it = sigbit_to_shiftx.find(qbits[i]); + if (i == 0) { + if (it != sigbit_to_shiftx.end()) { + shiftx = it->second; + // NULL indicates there are non-shiftx users + if (shiftx == nullptr) + return false; + offset = qbits[i].offset; + } + } + else { + if (it == sigbit_to_shiftx.end()) { + if (shiftx != nullptr) + return false; + } + else { + if (shiftx != it->second) + return false; + if (qbits[i].offset != offset + i) + return false; + } + } + } + + return true; + } + + virtual bool fixup(Cell *cell, dict &taps) override + { + const auto &tap = *taps.begin(); + auto bit = tap.second; + auto it = sigbit_to_shiftx.find(bit); + if (it == sigbit_to_shiftx.end()) + return true; + + Cell* shiftx = it->second; + + auto module = cell->module; + + auto cell_q = cell->getPort("\\Q").as_bit(); + + auto shiftx_a = shiftx->getPort("\\A").bits(); + int offset = 0; + for (auto bit : shiftx_a) { + if (bit == cell_q) + break; + ++offset; + } + offset -= taps.size() - 1; + log_assert(offset >= 0); + for (size_t i = offset; i < offset + taps.size(); ++i) + shiftx_a[i] = cell_q; + // FIXME: Hack to ensure that $shiftx gets optimised away + // Without this, Yosys will refuse to optimise away a $shiftx + // where \\A 's width is not perfectly \\B_WIDTH ** 2 + auto shiftx_bwidth = shiftx->getParam("\\B_WIDTH").as_int(); + shiftx_a.resize(1 << shiftx_bwidth, shiftx_a.back()); + shiftx->setPort("\\A", shiftx_a); + shiftx->setParam("\\A_WIDTH", shiftx_a.size()); + + auto length = module->addWire(NEW_ID, ceil(log2(taps.size()))); + module->addSub(NEW_ID, shiftx->getPort("\\B"), RTLIL::Const(offset, ceil(log2(offset))), length); + cell->setPort("\\L", length); + + + return true; + } +}; + + struct ShregmapWorker { - Module *module; - SigMap sigmap; + Module *module; + SigMap sigmap; - const ShregmapOptions &opts; - int dff_count, shreg_count; + const ShregmapOptions &opts; + int dff_count, shreg_count; - pool remove_cells; - pool remove_init; + pool remove_cells; + pool remove_init; - dict sigbit_init; - dict sigbit_chain_next; - dict sigbit_chain_prev; - pool sigbit_with_non_chain_users; - pool chain_start_cells; + dict sigbit_init; + dict sigbit_chain_next; + dict sigbit_chain_prev; + pool sigbit_with_non_chain_users; + pool chain_start_cells; - void make_sigbit_chain_next_prev() + void make_sigbit_chain_next_prev() + { + for (auto wire : module->wires()) { - for (auto wire : module->wires()) - { - if (wire->port_output || wire->get_bool_attribute("\\keep")) { - for (auto bit : sigmap(wire)) - sigbit_with_non_chain_users.insert(bit); - } + if (wire->port_output || wire->get_bool_attribute("\\keep")) { + for (auto bit : sigmap(wire)) + sigbit_with_non_chain_users.insert(bit); + } - if (wire->attributes.count("\\init")) { - SigSpec initsig = sigmap(wire); - Const initval = wire->attributes.at("\\init"); - for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) - if (initval[i] == State::S0 && !opts.zinit) - sigbit_init[initsig[i]] = false; - else if (initval[i] == State::S1) - sigbit_init[initsig[i]] = true; - } - } - - for (auto cell : module->cells()) - { - if (opts.ffcells.count(cell->type) && !cell->get_bool_attribute("\\keep")) - { - IdString d_port = opts.ffcells.at(cell->type).first; - IdString q_port = opts.ffcells.at(cell->type).second; - - SigBit d_bit = sigmap(cell->getPort(d_port).as_bit()); - SigBit q_bit = sigmap(cell->getPort(q_port).as_bit()); - - if (opts.init || sigbit_init.count(q_bit) == 0) - { - if (sigbit_chain_next.count(d_bit)) { - sigbit_with_non_chain_users.insert(d_bit); - } else - sigbit_chain_next[d_bit] = cell; - - sigbit_chain_prev[q_bit] = cell; - continue; - } - } - - for (auto conn : cell->connections()) - if (cell->input(conn.first)) - for (auto bit : sigmap(conn.second)) - sigbit_with_non_chain_users.insert(bit); - } + if (wire->attributes.count("\\init")) { + SigSpec initsig = sigmap(wire); + Const initval = wire->attributes.at("\\init"); + for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) + if (initval[i] == State::S0 && !opts.zinit) + sigbit_init[initsig[i]] = false; + else if (initval[i] == State::S1) + sigbit_init[initsig[i]] = true; + } } - void find_chain_start_cells() + for (auto cell : module->cells()) { - for (auto it : sigbit_chain_next) + if (opts.ffcells.count(cell->type) && !cell->get_bool_attribute("\\keep")) + { + IdString d_port = opts.ffcells.at(cell->type).first; + IdString q_port = opts.ffcells.at(cell->type).second; + + SigBit d_bit = sigmap(cell->getPort(d_port).as_bit()); + SigBit q_bit = sigmap(cell->getPort(q_port).as_bit()); + + if (opts.init || sigbit_init.count(q_bit) == 0) { - if (opts.tech == nullptr && sigbit_with_non_chain_users.count(it.first)) - goto start_cell; + if (sigbit_chain_next.count(d_bit)) { + sigbit_with_non_chain_users.insert(d_bit); + } else + sigbit_chain_next[d_bit] = cell; - 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; - - if (c1->parameters != c2->parameters) - goto start_cell; - - IdString d_port = opts.ffcells.at(c1->type).first; - IdString q_port = opts.ffcells.at(c1->type).second; - - auto c1_conn = c1->connections(); - auto c2_conn = c1->connections(); - - c1_conn.erase(d_port); - c1_conn.erase(q_port); - - c2_conn.erase(d_port); - c2_conn.erase(q_port); - - if (c1_conn != c2_conn) - goto start_cell; - - continue; - } - - start_cell: - chain_start_cells.insert(it.second); + sigbit_chain_prev[q_bit] = cell; + continue; } + } + + for (auto conn : cell->connections()) + if (cell->input(conn.first)) + 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); + } + } + } + + void find_chain_start_cells() + { + for (auto it : sigbit_chain_next) + { + if (opts.tech == nullptr && sigbit_with_non_chain_users.count(it.first)) + goto start_cell; + + 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; + + if (c1->parameters != c2->parameters) + goto start_cell; + + IdString d_port = opts.ffcells.at(c1->type).first; + IdString q_port = opts.ffcells.at(c1->type).second; + + auto c1_conn = c1->connections(); + auto c2_conn = c1->connections(); + + c1_conn.erase(d_port); + c1_conn.erase(q_port); + + c2_conn.erase(d_port); + c2_conn.erase(q_port); + + if (c1_conn != c2_conn) + goto start_cell; + + continue; + } + +start_cell: + chain_start_cells.insert(it.second); + } + } + + vector create_chain(Cell *start_cell) + { + vector chain; + + Cell *c = start_cell; + while (c != nullptr) + { + chain.push_back(c); + + IdString q_port = opts.ffcells.at(c->type).second; + SigBit q_bit = sigmap(c->getPort(q_port).as_bit()); + + if (sigbit_chain_next.count(q_bit) == 0) + break; + + c = sigbit_chain_next.at(q_bit); + if (chain_start_cells.count(c) != 0) + break; } - vector create_chain(Cell *start_cell) - { - vector chain; + return chain; + } - Cell *c = start_cell; - while (c != nullptr) + void process_chain(vector &chain) + { + if (GetSize(chain) < opts.keep_before + opts.minlen + opts.keep_after) + return; + + int cursor = opts.keep_before; + while (cursor < GetSize(chain) - opts.keep_after) + { + int depth = GetSize(chain) - opts.keep_after - cursor; + + if (opts.maxlen > 0) + depth = std::min(opts.maxlen, depth); + + Cell *first_cell = chain[cursor]; + IdString q_port = opts.ffcells.at(first_cell->type).second; + dict taps_dict; + + if (opts.tech) + { + vector qbits; + vector taps; + + for (int i = 0; i < depth; i++) { - chain.push_back(c); + Cell *cell = chain[cursor+i]; + auto qbit = sigmap(cell->getPort(q_port)); + qbits.push_back(qbit); - IdString q_port = opts.ffcells.at(c->type).second; - SigBit q_bit = sigmap(c->getPort(q_port).as_bit()); - - if (sigbit_chain_next.count(q_bit) == 0) - break; - - c = sigbit_chain_next.at(q_bit); - if (chain_start_cells.count(c) != 0) - break; + if (sigbit_with_non_chain_users.count(qbit)) + taps.push_back(i); } - return chain; - } - - void process_chain(vector &chain) - { - if (GetSize(chain) < opts.keep_before + opts.minlen + opts.keep_after) - return; - - int cursor = opts.keep_before; - while (cursor < GetSize(chain) - opts.keep_after) + while (depth > 0) { - int depth = GetSize(chain) - opts.keep_after - cursor; + if (taps.empty() || taps.back() < depth-1) + taps.push_back(depth-1); - if (opts.maxlen > 0) - depth = std::min(opts.maxlen, depth); + if (opts.tech->analyze(taps, qbits)) + break; - Cell *first_cell = chain[cursor]; - IdString q_port = opts.ffcells.at(first_cell->type).second; - dict taps_dict; - - if (opts.tech) - { - vector qbits; - vector taps; - - for (int i = 0; i < depth; i++) - { - Cell *cell = chain[cursor+i]; - auto qbit = sigmap(cell->getPort(q_port)); - qbits.push_back(qbit); - - if (sigbit_with_non_chain_users.count(qbit)) - taps.push_back(i); - } - - while (depth > 0) - { - if (taps.empty() || taps.back() < depth-1) - taps.push_back(depth-1); - - if (opts.tech->analyze(taps)) - break; - - taps.pop_back(); - depth--; - } - - depth = 0; - for (auto tap : taps) { - taps_dict[tap] = qbits.at(tap); - log_assert(depth < tap+1); - depth = tap+1; - } - } - - if (depth < 2) { - cursor++; - continue; - } - - Cell *last_cell = chain[cursor+depth-1]; - - log("Converting %s.%s ... %s.%s to a shift register with depth %d.\n", - log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), depth); - - dff_count += depth; - shreg_count += 1; - - string shreg_cell_type_str = "$__SHREG"; - if (opts.params) { - shreg_cell_type_str += "_"; - } else { - if (first_cell->type[1] != '_') - shreg_cell_type_str += "_"; - shreg_cell_type_str += first_cell->type.substr(1); - } - - if (opts.init) { - vector initval; - for (int i = depth-1; i >= 0; i--) { - SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit()); - if (sigbit_init.count(bit) == 0) - initval.push_back(State::Sx); - else if (sigbit_init.at(bit)) - initval.push_back(State::S1); - else - initval.push_back(State::S0); - remove_init.insert(bit); - } - first_cell->setParam("\\INIT", initval); - } - - if (opts.zinit) - for (int i = depth-1; i >= 0; i--) { - SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit()); - remove_init.insert(bit); - } - - if (opts.params) - { - int param_clkpol = -1; - int param_enpol = 2; - - if (first_cell->type == "$_DFF_N_") param_clkpol = 0; - if (first_cell->type == "$_DFF_P_") param_clkpol = 1; - - if (first_cell->type == "$_DFFE_NN_") param_clkpol = 0, param_enpol = 0; - if (first_cell->type == "$_DFFE_NP_") param_clkpol = 0, param_enpol = 1; - if (first_cell->type == "$_DFFE_PN_") param_clkpol = 1, param_enpol = 0; - if (first_cell->type == "$_DFFE_PP_") param_clkpol = 1, param_enpol = 1; - - log_assert(param_clkpol >= 0); - first_cell->setParam("\\CLKPOL", param_clkpol); - if (opts.ffe) first_cell->setParam("\\ENPOL", param_enpol); - } - - first_cell->type = shreg_cell_type_str; - first_cell->setPort(q_port, last_cell->getPort(q_port)); - first_cell->setParam("\\DEPTH", depth); - - if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict)) - remove_cells.insert(first_cell); - - for (int i = 1; i < depth; i++) - remove_cells.insert(chain[cursor+i]); - cursor += depth; + taps.pop_back(); + depth--; } - } - void cleanup() + depth = 0; + for (auto tap : taps) { + taps_dict[tap] = qbits.at(tap); + log_assert(depth < tap+1); + depth = tap+1; + } + } + + if (depth < 2) { + cursor++; + continue; + } + + Cell *last_cell = chain[cursor+depth-1]; + + log("Converting %s.%s ... %s.%s to a shift register with depth %d.\n", + log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), depth); + + dff_count += depth; + shreg_count += 1; + + string shreg_cell_type_str = "$__SHREG"; + if (opts.params) { + shreg_cell_type_str += "_"; + } else { + if (first_cell->type[1] != '_') + shreg_cell_type_str += "_"; + shreg_cell_type_str += first_cell->type.substr(1); + } + + if (opts.init) { + vector initval; + for (int i = depth-1; i >= 0; i--) { + SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit()); + if (sigbit_init.count(bit) == 0) + initval.push_back(State::Sx); + else if (sigbit_init.at(bit)) + initval.push_back(State::S1); + else + initval.push_back(State::S0); + remove_init.insert(bit); + } + first_cell->setParam("\\INIT", initval); + } + + if (opts.zinit) + for (int i = depth-1; i >= 0; i--) { + SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit()); + remove_init.insert(bit); + } + + if (opts.params) + { + int param_clkpol = -1; + int param_enpol = 2; + + if (first_cell->type == "$_DFF_N_") param_clkpol = 0; + if (first_cell->type == "$_DFF_P_") param_clkpol = 1; + + if (first_cell->type == "$_DFFE_NN_") param_clkpol = 0, param_enpol = 0; + if (first_cell->type == "$_DFFE_NP_") param_clkpol = 0, param_enpol = 1; + if (first_cell->type == "$_DFFE_PN_") param_clkpol = 1, param_enpol = 0; + if (first_cell->type == "$_DFFE_PP_") param_clkpol = 1, param_enpol = 1; + + log_assert(param_clkpol >= 0); + first_cell->setParam("\\CLKPOL", param_clkpol); + if (opts.ffe) first_cell->setParam("\\ENPOL", param_enpol); + } + + first_cell->type = shreg_cell_type_str; + first_cell->setPort(q_port, last_cell->getPort(q_port)); + if (!first_cell->hasPort("\\L")) + first_cell->setPort("\\L", depth-1); + first_cell->setParam("\\DEPTH", depth); + + if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict)) + remove_cells.insert(first_cell); + + for (int i = 1; i < depth; i++) + remove_cells.insert(chain[cursor+i]); + cursor += depth; + } + } + + void cleanup() + { + for (auto cell : remove_cells) + module->remove(cell); + + for (auto wire : module->wires()) { - for (auto cell : remove_cells) - module->remove(cell); + if (wire->attributes.count("\\init") == 0) + continue; - for (auto wire : module->wires()) - { - if (wire->attributes.count("\\init") == 0) - continue; + SigSpec initsig = sigmap(wire); + Const &initval = wire->attributes.at("\\init"); - SigSpec initsig = sigmap(wire); - Const &initval = wire->attributes.at("\\init"); + for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) + if (remove_init.count(initsig[i])) + initval[i] = State::Sx; - for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) - if (remove_init.count(initsig[i])) - initval[i] = State::Sx; - - if (SigSpec(initval).is_fully_undef()) - wire->attributes.erase("\\init"); - } - - remove_cells.clear(); - sigbit_chain_next.clear(); - sigbit_chain_prev.clear(); - chain_start_cells.clear(); + if (SigSpec(initval).is_fully_undef()) + wire->attributes.erase("\\init"); } - ShregmapWorker(Module *module, const ShregmapOptions &opts) : - module(module), sigmap(module), opts(opts), dff_count(0), shreg_count(0) - { - make_sigbit_chain_next_prev(); - find_chain_start_cells(); + remove_cells.clear(); + sigbit_chain_next.clear(); + sigbit_chain_prev.clear(); + chain_start_cells.clear(); + } - for (auto c : chain_start_cells) { - vector chain = create_chain(c); - process_chain(chain); - } + 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); - cleanup(); + make_sigbit_chain_next_prev(); + find_chain_start_cells(); + + for (auto c : chain_start_cells) { + vector chain = create_chain(c); + process_chain(chain); } + + cleanup(); + } }; struct ShregmapPass : public Pass { @@ -501,6 +624,12 @@ 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; diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 69f8b85f4..e7fb269e9 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -17,7 +17,7 @@ * */ -module \$__SHREG_ (input C, input D, input E, output Q); +module \$__SHREG_ (input C, input D, input [31:0] L, input E, output Q); parameter DEPTH = 0; parameter [DEPTH-1:0] INIT = 0; parameter CLKPOL = 1; @@ -36,6 +36,9 @@ module \$__SHREG_ (input C, input D, input E, output Q); endfunction localparam [DEPTH-1:0] INIT_R = brev(INIT); + parameter _TECHMAP_CONSTMSK_L_ = 0; + parameter _TECHMAP_CONSTVAL_L_ = 0; + generate if (ENPOL == 0) assign CE = ~E; @@ -44,60 +47,86 @@ module \$__SHREG_ (input C, input D, input E, output Q); else assign CE = 1'b1; if (DEPTH == 1) begin - if (CLKPOL) - FDRE #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); - else - FDRE_1 #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); + wire _TECHMAP_FAIL_ = ~&_TECHMAP_CONSTMSK_L_ || _TECHMAP_CONSTVAL_L_ != 0; + if (CLKPOL) + FDRE #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); + else + FDRE_1 #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); end else if (DEPTH <= 16) begin - localparam [3:0] A = DEPTH - 1; - SRL16E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A0(A[0]), .A1(A[1]), .A2(A[2]), .A3(A[3]), .CE(CE), .CLK(C), .D(D), .Q(Q)); + SRL16E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A0(L[0]), .A1(L[1]), .A2(L[2]), .A3(L[3]), .CE(CE), .CLK(C), .D(D), .Q(Q)); end else if (DEPTH > 17 && DEPTH <= 32) begin - SRLC32E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A(DEPTH-1), .CE(CE), .CLK(C), .D(D), .Q(Q)); + SRLC32E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(Q)); end else if (DEPTH > 33 && DEPTH <= 64) begin wire T0, T1, T2; - localparam [5:0] A = DEPTH-1; - SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - \$__SHREG_ #(.DEPTH(DEPTH-32), .INIT(INIT[DEPTH-32-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .E(E), .Q(T2)); - MUXF7 fpga_mux_0 (.O(Q), .I0(T0), .I1(T2), .S(A[5])); + SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + \$__SHREG_ #(.DEPTH(DEPTH-32), .INIT(INIT[DEPTH-32-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L), .E(E), .Q(T2)); + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T2; + else + MUXF7 fpga_mux_0 (.O(Q), .I0(T0), .I1(T2), .S(L[5])); end else if (DEPTH > 65 && DEPTH <= 96) begin - localparam [6:0] A = DEPTH-1; wire T0, T1, T2, T3, T4, T5, T6; - SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); - \$__SHREG_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-64-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_2 (.C(C), .D(T3), .E(E), .Q(T4)); - MUXF7 fpga_mux_0 (.O(T5), .I0(T0), .I1(T2), .S(A[5])); - MUXF7 fpga_mux_1 (.O(T6), .I0(T4), .I1(1'b0 /* unused */), .S(A[5])); - MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(A[6])); + SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + \$__SHREG_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-64-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_2 (.C(C), .D(T3), .L(L[4:0]), .E(E), .Q(T4)); + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T4; + else begin + MUXF7 fpga_mux_0 (.O(T5), .I0(T0), .I1(T2), .S(L[5])); + MUXF7 fpga_mux_1 (.O(T6), .I0(T4), .I1(1'b0 /* unused */), .S(L[5])); + MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(L[6])); + end end else if (DEPTH > 97 && DEPTH <= 128) begin - localparam [6:0] A = DEPTH-1; wire T0, T1, T2, T3, T4, T5, T6, T7, T8; - SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(A[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); - SRLC32E #(.INIT(INIT_R[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(A[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); - \$__SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-96-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .E(E), .Q(T6)); - MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(A[5])); - MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(A[5])); - MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(A[6])); + SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + SRLC32E #(.INIT(INIT_R[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); + \$__SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-96-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .L(L[4:0]), .E(E), .Q(T6)); + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T6; + else begin + MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(L[5])); + MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(L[5])); + MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(L[6])); + end end - else if (DEPTH <= 129) begin + else if (DEPTH < 129 || (DEPTH <= 129 && &_TECHMAP_CONSTMSK_L_)) begin // Handle cases where depth is just 1 over a convenient value, - // in which case use the flop - wire T0; - \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-1:1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); - \$__SHREG_ #(.DEPTH(1), .INIT(INIT[0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); - end else - begin - // UG474 (v1.8, p34) states that: - // "There are no direct connections between slices to form longer shift - // registers, nor is the MC31 output at LUT B/C/D available." - wire T0; - \$__SHREG_ #(.DEPTH(128), .INIT(INIT[DEPTH-1:DEPTH-128]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .E(E), .Q(T0)); - \$__SHREG_ #(.DEPTH(DEPTH-128), .INIT(INIT[DEPTH-128-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .E(E), .Q(Q)); + if (&_TECHMAP_CONSTMSK_L_) begin + // For constant length, use the flop + wire T0; + \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-1:1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(DEPTH-1-1), .E(E), .Q(T0)); + \$__SHREG_ #(.DEPTH(1), .INIT(INIT[0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .L(0), .E(E), .Q(Q)); + end + else begin + // For variable length, bump up to the next length + // because we can't access Q31 + \$__SHREG_ #(.DEPTH(DEPTH+1), .INIT(INIT), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); + end + end + else begin + if (&_TECHMAP_CONSTMSK_L_) begin + // UG474 (v1.8, p34) states that: + // "There are no direct connections between slices to form longer shift + // registers, nor is the MC31 output at LUT B/C/D available." + wire T0; + \$__SHREG_ #(.DEPTH(128), .INIT(INIT[DEPTH-1:DEPTH-128]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(127), .E(E), .Q(T0)); + \$__SHREG_ #(.DEPTH(DEPTH-128), .INIT(INIT[DEPTH-128-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .L(DEPTH-1-128), .E(E), .Q(Q)); + end + else begin + // No way to create variable length shift registers >128 bits as Q31 + // cannot be output to the fabric... + wire [DEPTH-1:-1] c; + genvar i; + for (i = 0; i < DEPTH; i=i+1) + \$__SHREG_ #(.DEPTH(1), .INIT(INIT_R[i]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl (.C(C), .D(c[i-1]), .L(0), .E(E), .Q(c[i])); + assign { c[-1], Q } = { D, c[L] }; + end end endgenerate endmodule diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index f2c3833a4..443ac4eed 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -110,9 +110,8 @@ struct SynthXilinxPass : public Pass log(" dffsr2dff\n"); log(" dff2dffe\n"); log(" opt -full\n"); - log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v\n"); - log(" shregmap -init -params -enpol any_or_none\n"); - log(" techmap -map +/xilinx/ff_map.v\n"); + log(" shregmap -tech xilinx\n"); + log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v +/xilinx/ff_map.v\n"); log(" opt -fast\n"); log("\n"); log(" map_luts:\n"); @@ -256,14 +255,17 @@ struct SynthXilinxPass : public Pass Pass::call(design, "dff2dffe"); Pass::call(design, "opt -full"); + Pass::call(design, "simplemap t:$dff*"); + Pass::call(design, "shregmap -tech xilinx"); + Pass::call(design, "techmap -map +/xilinx/cells_map.v t:$__SHREG_"); + Pass::call(design, "opt -fast"); + if (vpr) { - Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); + Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v -D _EXPLICIT_CARRY"); } else { - Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v"); + Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v"); } - Pass::call(design, "shregmap -init -params -enpol any_or_none"); - Pass::call(design, "techmap -map +/xilinx/ff_map.v"); Pass::call(design, "opt -fast"); } From 29a8d4745eb4ecd2947694d02f51c9333bf3ac21 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 15 Mar 2019 23:01:40 -0700 Subject: [PATCH 16/64] Cleanup synth_xilinx --- techlibs/xilinx/cells_map.v | 2 +- techlibs/xilinx/synth_xilinx.cc | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index e7fb269e9..a35b0742b 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -95,7 +95,7 @@ module \$__SHREG_ (input C, input D, input [31:0] L, input E, output Q); MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(L[6])); end end - else if (DEPTH < 129 || (DEPTH <= 129 && &_TECHMAP_CONSTMSK_L_)) begin + else if (DEPTH <= 128 || (DEPTH == 129 && &_TECHMAP_CONSTMSK_L_)) begin // Handle cases where depth is just 1 over a convenient value, if (&_TECHMAP_CONSTMSK_L_) begin // For constant length, use the flop diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 443ac4eed..763732fe5 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -110,6 +110,7 @@ struct SynthXilinxPass : public Pass log(" dffsr2dff\n"); log(" dff2dffe\n"); log(" opt -full\n"); + log(" simplemap t:$dff*\n"); log(" shregmap -tech xilinx\n"); log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v +/xilinx/ff_map.v\n"); log(" opt -fast\n"); @@ -257,8 +258,6 @@ struct SynthXilinxPass : public Pass Pass::call(design, "simplemap t:$dff*"); Pass::call(design, "shregmap -tech xilinx"); - Pass::call(design, "techmap -map +/xilinx/cells_map.v t:$__SHREG_"); - Pass::call(design, "opt -fast"); if (vpr) { Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v -D _EXPLICIT_CARRY"); From fadeadb8c87670b1cfe8f92ac9c5ac3beadcb312 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Mar 2019 08:51:13 -0700 Subject: [PATCH 17/64] Only accept <128 for variable length, only if $shiftx exclusive --- passes/techmap/shregmap.cc | 25 +++++++++++++++++-------- techlibs/xilinx/cells_map.v | 6 +----- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 4b8f8a828..f893461a0 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -161,6 +161,16 @@ struct ShregmapTechXilinx7 : ShregmapTech } } + // Cannot implement variable-length shift registers + // greater than 128 since Q31 cannot be output onto + // fabric + if (shiftx && GetSize(taps) > 128) + return false; + + // Only map if $shiftx exclusively covers the shift register + if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) + return false; + return true; } @@ -173,34 +183,33 @@ struct ShregmapTechXilinx7 : ShregmapTech return true; Cell* shiftx = it->second; - - auto module = cell->module; + auto shiftx_a = shiftx->getPort("\\A").bits(); auto cell_q = cell->getPort("\\Q").as_bit(); - auto shiftx_a = shiftx->getPort("\\A").bits(); int offset = 0; +#ifndef NDEBUG for (auto bit : shiftx_a) { if (bit == cell_q) break; ++offset; } offset -= taps.size() - 1; - log_assert(offset >= 0); + log_assert(offset == 0); +#endif for (size_t i = offset; i < offset + taps.size(); ++i) shiftx_a[i] = cell_q; + // FIXME: Hack to ensure that $shiftx gets optimised away // Without this, Yosys will refuse to optimise away a $shiftx // where \\A 's width is not perfectly \\B_WIDTH ** 2 + // See YosysHQ/yosys#878 auto shiftx_bwidth = shiftx->getParam("\\B_WIDTH").as_int(); shiftx_a.resize(1 << shiftx_bwidth, shiftx_a.back()); shiftx->setPort("\\A", shiftx_a); shiftx->setParam("\\A_WIDTH", shiftx_a.size()); - auto length = module->addWire(NEW_ID, ceil(log2(taps.size()))); - module->addSub(NEW_ID, shiftx->getPort("\\B"), RTLIL::Const(offset, ceil(log2(offset))), length); - cell->setPort("\\L", length); - + cell->setPort("\\L", shiftx->getPort("\\B")); return true; } diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index a35b0742b..1d538e262 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -121,11 +121,7 @@ module \$__SHREG_ (input C, input D, input [31:0] L, input E, output Q); else begin // No way to create variable length shift registers >128 bits as Q31 // cannot be output to the fabric... - wire [DEPTH-1:-1] c; - genvar i; - for (i = 0; i < DEPTH; i=i+1) - \$__SHREG_ #(.DEPTH(1), .INIT(INIT_R[i]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl (.C(C), .D(c[i-1]), .L(0), .E(E), .Q(c[i])); - assign { c[-1], Q } = { D, c[L] }; + wire _TECHMAP_FAIL_ = 1; end end endgenerate From d6d9ef0fee3a187b884cbfd0b9a97da935666189 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Mar 2019 12:49:46 -0700 Subject: [PATCH 18/64] Cleanup --- passes/techmap/shregmap.cc | 60 ++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index f893461a0..179a331fd 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -95,7 +95,7 @@ struct ShregmapTechGreenpak4 : ShregmapTech struct ShregmapTechXilinx7 : ShregmapTech { - dict sigbit_to_shiftx; + dict> sigbit_to_shiftx_offset; const ShregmapOptions &opts; ShregmapTechXilinx7(const ShregmapOptions &opts) : opts(opts) {} @@ -106,19 +106,21 @@ struct ShregmapTechXilinx7 : ShregmapTech auto cell = i.second; if (cell->type != "$shiftx") continue; if (cell->getParam("\\Y_WIDTH") != 1) continue; + int j = 0; for (auto bit : sigmap(cell->getPort("\\A"))) - sigbit_to_shiftx[bit] = cell; + sigbit_to_shiftx_offset[bit] = std::make_pair(cell, j++); + log_assert(j == cell->getParam("\\A_WIDTH").as_int()); } } virtual void non_chain_user(const SigBit &bit, const Cell *cell, IdString port) override { - auto it = sigbit_to_shiftx.find(bit); - if (it == sigbit_to_shiftx.end()) + auto it = sigbit_to_shiftx_offset.find(bit); + if (it == sigbit_to_shiftx_offset.end()) return; if (cell->type == "$shiftx" && port == "\\A") return; - it->second = nullptr; + it->second = std::make_pair(nullptr, 0); } virtual bool analyze(vector &taps, const vector &qbits) override @@ -130,32 +132,34 @@ struct ShregmapTechXilinx7 : ShregmapTech return false; Cell *shiftx = nullptr; - int offset = 0; for (int i = 0; i < GetSize(taps); ++i) { // 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 - auto it = sigbit_to_shiftx.find(qbits[i]); + auto it = sigbit_to_shiftx_offset.find(qbits[i]); if (i == 0) { - if (it != sigbit_to_shiftx.end()) { - shiftx = it->second; + if (it != sigbit_to_shiftx_offset.end()) { + shiftx = it->second.first; // NULL indicates there are non-shiftx users if (shiftx == nullptr) return false; - offset = qbits[i].offset; + int offset = it->second.second; + if (offset != i) + return false; } } else { - if (it == sigbit_to_shiftx.end()) { + if (it == sigbit_to_shiftx_offset.end()) { if (shiftx != nullptr) return false; } else { - if (shiftx != it->second) + if (shiftx != it->second.first) return false; - if (qbits[i].offset != offset + i) + int offset = it->second.second; + if (offset != i) return false; } } @@ -178,36 +182,22 @@ struct ShregmapTechXilinx7 : ShregmapTech { const auto &tap = *taps.begin(); auto bit = tap.second; - auto it = sigbit_to_shiftx.find(bit); - if (it == sigbit_to_shiftx.end()) + auto it = sigbit_to_shiftx_offset.find(bit); + // If fixed-length, no fixup necessary + if (it == sigbit_to_shiftx_offset.end()) return true; - Cell* shiftx = it->second; - auto shiftx_a = shiftx->getPort("\\A").bits(); - - auto cell_q = cell->getPort("\\Q").as_bit(); - - int offset = 0; -#ifndef NDEBUG - for (auto bit : shiftx_a) { - if (bit == cell_q) - break; - ++offset; - } - offset -= taps.size() - 1; - log_assert(offset == 0); -#endif - for (size_t i = offset; i < offset + taps.size(); ++i) - shiftx_a[i] = cell_q; + auto cell_q = cell->getPort("\\Q"); + log_assert(cell_q.is_bit()); + Cell* shiftx = it->second.first; // FIXME: Hack to ensure that $shiftx gets optimised away // Without this, Yosys will refuse to optimise away a $shiftx // where \\A 's width is not perfectly \\B_WIDTH ** 2 // See YosysHQ/yosys#878 auto shiftx_bwidth = shiftx->getParam("\\B_WIDTH").as_int(); - shiftx_a.resize(1 << shiftx_bwidth, shiftx_a.back()); - shiftx->setPort("\\A", shiftx_a); - shiftx->setParam("\\A_WIDTH", shiftx_a.size()); + shiftx->setPort("\\A", cell_q.repeat(1 << shiftx_bwidth)); + shiftx->setParam("\\A_WIDTH", 1 << shiftx_bwidth); cell->setPort("\\L", shiftx->getPort("\\B")); From b94db546645e624b752203a4c4d2395dc84dff0c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 18 Mar 2019 13:35:54 -0700 Subject: [PATCH 19/64] shiftx NULL pointer check --- passes/techmap/shregmap.cc | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 179a331fd..f3153b400 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -165,15 +165,17 @@ struct ShregmapTechXilinx7 : ShregmapTech } } - // Cannot implement variable-length shift registers - // greater than 128 since Q31 cannot be output onto - // fabric - if (shiftx && GetSize(taps) > 128) - return false; + if (shiftx) { + // Cannot implement variable-length shift registers + // greater than 128 since Q31 cannot be output onto + // fabric + if (GetSize(taps) > 128) + return false; - // Only map if $shiftx exclusively covers the shift register - if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) - return false; + // Only map if $shiftx exclusively covers the shift register + if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) + return false; + } return true; } From ed32119d133166c78870137c6ce3db781b92c2e4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 18 Mar 2019 16:12:19 -0700 Subject: [PATCH 20/64] Fix shregmap to correctly recognise non chain users; cleanup --- passes/techmap/shregmap.cc | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index f3153b400..d95cadde5 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -120,7 +120,7 @@ struct ShregmapTechXilinx7 : ShregmapTech return; if (cell->type == "$shiftx" && port == "\\A") return; - it->second = std::make_pair(nullptr, 0); + sigbit_to_shiftx_offset.erase(it); } virtual bool analyze(vector &taps, const vector &qbits) override @@ -140,11 +140,11 @@ struct ShregmapTechXilinx7 : ShregmapTech // or sequential to the same shift register auto it = sigbit_to_shiftx_offset.find(qbits[i]); if (i == 0) { - if (it != sigbit_to_shiftx_offset.end()) { + if (it == sigbit_to_shiftx_offset.end()) { + return false; + } + else { shiftx = it->second.first; - // NULL indicates there are non-shiftx users - if (shiftx == nullptr) - return false; int offset = it->second.second; if (offset != i) return false; @@ -152,8 +152,7 @@ struct ShregmapTechXilinx7 : ShregmapTech } else { if (it == sigbit_to_shiftx_offset.end()) { - if (shiftx != nullptr) - return false; + return false; } else { if (shiftx != it->second.first) @@ -164,18 +163,17 @@ struct ShregmapTechXilinx7 : ShregmapTech } } } + log_assert(shiftx); - if (shiftx) { - // Cannot implement variable-length shift registers - // greater than 128 since Q31 cannot be output onto - // fabric - if (GetSize(taps) > 128) - return false; + // Cannot implement variable-length shift registers + // greater than 128 since Q31 cannot be output onto + // fabric + if (GetSize(taps) > 128) + return false; - // Only map if $shiftx exclusively covers the shift register - if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) - return false; - } + // Only map if $shiftx exclusively covers the shift register + if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) + return false; return true; } From 0ea7eba5f13b20de28181a66181ee821820027db Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 13:08:43 -0700 Subject: [PATCH 21/64] Make output port a non chain user --- passes/techmap/shregmap.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index d95cadde5..3b3170e04 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -118,7 +118,7 @@ struct ShregmapTechXilinx7 : ShregmapTech auto it = sigbit_to_shiftx_offset.find(bit); if (it == sigbit_to_shiftx_offset.end()) return; - if (cell->type == "$shiftx" && port == "\\A") + if (cell && cell->type == "$shiftx" && port == "\\A") return; sigbit_to_shiftx_offset.erase(it); } @@ -228,8 +228,10 @@ struct ShregmapWorker for (auto wire : module->wires()) { if (wire->port_output || wire->get_bool_attribute("\\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("\\init")) { From f239cb821edb86c3ec48782139e982819f073a7c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 14:54:43 -0700 Subject: [PATCH 22/64] Fix INIT for variable length SRs that have been bumped up one --- techlibs/xilinx/cells_map.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 1d538e262..94a48dbc2 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -106,7 +106,7 @@ module \$__SHREG_ (input C, input D, input [31:0] L, input E, output Q); else begin // For variable length, bump up to the next length // because we can't access Q31 - \$__SHREG_ #(.DEPTH(DEPTH+1), .INIT(INIT), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); + \$__SHREG_ #(.DEPTH(DEPTH+1), .INIT({INIT,1'b0}), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); end end else begin From 4cd8f0297381c5fb9fe3b8cbb22d4240f2aaae63 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 15:05:08 -0700 Subject: [PATCH 23/64] shregmap -tech xilinx to delete $shiftx for var length SRL --- passes/techmap/shregmap.cc | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 3b3170e04..bd537e7c2 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -187,19 +187,12 @@ struct ShregmapTechXilinx7 : ShregmapTech if (it == sigbit_to_shiftx_offset.end()) return true; - auto cell_q = cell->getPort("\\Q"); - log_assert(cell_q.is_bit()); - Cell* shiftx = it->second.first; - // FIXME: Hack to ensure that $shiftx gets optimised away - // Without this, Yosys will refuse to optimise away a $shiftx - // where \\A 's width is not perfectly \\B_WIDTH ** 2 - // See YosysHQ/yosys#878 - auto shiftx_bwidth = shiftx->getParam("\\B_WIDTH").as_int(); - shiftx->setPort("\\A", cell_q.repeat(1 << shiftx_bwidth)); - shiftx->setParam("\\A_WIDTH", 1 << shiftx_bwidth); cell->setPort("\\L", shiftx->getPort("\\B")); + cell->setPort("\\Q", shiftx->getPort("\\Y")); + + cell->module->remove(shiftx); return true; } From 9156e18f9215f7e8e5a36e068b137b01810769b1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 16:12:32 -0700 Subject: [PATCH 24/64] Fix spacing --- techlibs/xilinx/cells_map.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 94a48dbc2..00a0b494b 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -76,7 +76,7 @@ module \$__SHREG_ (input C, input D, input [31:0] L, input E, output Q); if (&_TECHMAP_CONSTMSK_L_) assign Q = T4; else begin - MUXF7 fpga_mux_0 (.O(T5), .I0(T0), .I1(T2), .S(L[5])); + MUXF7 fpga_mux_0 (.O(T5), .I0(T0), .I1(T2), .S(L[5])); MUXF7 fpga_mux_1 (.O(T6), .I0(T4), .I1(1'b0 /* unused */), .S(L[5])); MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(L[6])); end From ae2a625d0507c9e7476497e0064ffa003aa761f1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 16:14:08 -0700 Subject: [PATCH 25/64] Restore original synth_xilinx commands --- techlibs/xilinx/synth_xilinx.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 61895e032..0eccb97f2 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -112,7 +112,7 @@ struct SynthXilinxPass : public Pass log(" opt -full\n"); log(" simplemap t:$dff*\n"); log(" shregmap -tech xilinx\n"); - log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v +/xilinx/ff_map.v\n"); + log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v\n"); log(" opt -fast\n"); log("\n"); log(" map_luts:\n"); @@ -266,6 +266,7 @@ struct SynthXilinxPass : public Pass Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v"); } + Pass::call(design, "hierarchy -check"); Pass::call(design, "opt -fast"); } From 5445cd4d00349f9d04f9e78c7c2804306fac6b65 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 17:44:33 -0700 Subject: [PATCH 26/64] Add support for variable length Xilinx SRL > 128 --- passes/techmap/shregmap.cc | 6 --- techlibs/xilinx/cells_map.v | 80 +++++++++++++++++++++++++++++++------ 2 files changed, 68 insertions(+), 18 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index bd537e7c2..a060b55df 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -165,12 +165,6 @@ struct ShregmapTechXilinx7 : ShregmapTech } log_assert(shiftx); - // Cannot implement variable-length shift registers - // greater than 128 since Q31 cannot be output onto - // fabric - if (GetSize(taps) > 128) - return false; - // Only map if $shiftx exclusively covers the shift register if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) return false; diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 00a0b494b..24383d626 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -105,23 +105,79 @@ module \$__SHREG_ (input C, input D, input [31:0] L, input E, output Q); end else begin // For variable length, bump up to the next length - // because we can't access Q31 \$__SHREG_ #(.DEPTH(DEPTH+1), .INIT({INIT,1'b0}), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); end end else begin - if (&_TECHMAP_CONSTMSK_L_) begin - // UG474 (v1.8, p34) states that: - // "There are no direct connections between slices to form longer shift - // registers, nor is the MC31 output at LUT B/C/D available." - wire T0; - \$__SHREG_ #(.DEPTH(128), .INIT(INIT[DEPTH-1:DEPTH-128]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(127), .E(E), .Q(T0)); - \$__SHREG_ #(.DEPTH(DEPTH-128), .INIT(INIT[DEPTH-128-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .L(DEPTH-1-128), .E(E), .Q(Q)); - end + \$__XILINX_SHREG_ #(.DEPTH(DEPTH), .INIT(INIT), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); + end + endgenerate +endmodule + +module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, output SO); + parameter DEPTH = 0; + parameter [DEPTH-1:0] INIT = 0; + parameter CLKPOL = 1; + parameter ENPOL = 2; + + // shregmap's INIT parameter shifts out LSB first; + // however Xilinx expects MSB first + function [DEPTH-1:0] brev; + input [DEPTH-1:0] din; + integer i; + begin + for (i = 0; i < DEPTH; i=i+1) + brev[i] = din[DEPTH-1-i]; + end + endfunction + localparam [DEPTH-1:0] INIT_R = brev(INIT); + + parameter _TECHMAP_CONSTMSK_L_ = 0; + parameter _TECHMAP_CONSTVAL_L_ = 0; + + generate + if (DEPTH == 1) begin + \$__SHREG_ #(.DEPTH(DEPTH), .INIT(INIT), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(0), .E(E), .Q(Q)); + end + else if (DEPTH < 128) begin + \$__SHREG_ #(.DEPTH(DEPTH), .INIT(INIT), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); + end + else if (DEPTH == 128) begin + wire CE; + if (ENPOL == 0) + assign CE = ~E; + else if (ENPOL == 1) + assign CE = E; + else + assign CE = 1'b1; + + wire T0, T1, T2, T3, T4, T5, T6; + SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + SRLC32E #(.INIT(INIT_R[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); + SRLC32E #(.INIT(INIT_R[128-1:96]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_3 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T5), .Q(T6), .Q31(SO)); + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T6; else begin - // No way to create variable length shift registers >128 bits as Q31 - // cannot be output to the fabric... - wire _TECHMAP_FAIL_ = 1; + wire T7, T8; + MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(L[5])); + MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(L[5])); + MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(L[6])); + end + end + else if (DEPTH > 128) begin + localparam lower_clog2 = $clog2((DEPTH+1)/2); + localparam lower_depth = 2 ** lower_clog2; + wire T0, T1, T2; + \$__XILINX_SHREG_ #(.DEPTH(lower_depth), .INIT(INIT[DEPTH-1:DEPTH-lower_depth]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(L[lower_clog2-1:0]), .E(E), .Q(T0), .SO(T1)); + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-lower_depth), .INIT(INIT[DEPTH-lower_depth-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L[lower_clog2-1:0]), .E(E), .Q(T2)); + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T2; + else begin + //assign Q = L[lower_clog2-1] ? T2 : T0; + // FIXME: Need to instantiate 2:1 MUX here since + // techmap with this file is run AFTER abc + LUT3 #(.INIT(8'b10101100)) fpga_mux (.I0(T2), .I1(T0), .I2(L[lower_clog2]), .O(Q)); end end endgenerate From 505e4c2d59ed81a1779644b7aaf61aee799c8f67 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 21:58:05 -0700 Subject: [PATCH 27/64] Revert $__SHREG_ to orig; use $__XILINX_SHREG for variable length --- passes/techmap/shregmap.cc | 19 ++-- techlibs/xilinx/cells_map.v | 173 +++++++++++++++--------------------- 2 files changed, 84 insertions(+), 108 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index a060b55df..1729418e6 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -176,19 +176,30 @@ struct ShregmapTechXilinx7 : ShregmapTech { const auto &tap = *taps.begin(); auto bit = tap.second; + auto it = sigbit_to_shiftx_offset.find(bit); // If fixed-length, no fixup necessary if (it == sigbit_to_shiftx_offset.end()) return true; + auto newcell = cell->module->addCell(NEW_ID, "$__XILINX_SHREG_"); + newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH")); + newcell->setParam("\\INIT", cell->getParam("\\INIT")); + newcell->setParam("\\CLKPOL", cell->getParam("\\CLKPOL")); + newcell->setParam("\\ENPOL", cell->getParam("\\ENPOL")); + + newcell->setPort("\\C", cell->getPort("\\C")); + newcell->setPort("\\D", cell->getPort("\\D")); + newcell->setPort("\\E", cell->getPort("\\E")); + Cell* shiftx = it->second.first; - cell->setPort("\\L", shiftx->getPort("\\B")); - cell->setPort("\\Q", shiftx->getPort("\\Y")); + newcell->setPort("\\L", shiftx->getPort("\\B")); + newcell->setPort("\\Q", shiftx->getPort("\\Y")); cell->module->remove(shiftx); - return true; + return false; } }; @@ -442,8 +453,6 @@ start_cell: first_cell->type = shreg_cell_type_str; first_cell->setPort(q_port, last_cell->getPort(q_port)); - if (!first_cell->hasPort("\\L")) - first_cell->setPort("\\L", depth-1); first_cell->setParam("\\DEPTH", depth); if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict)) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 24383d626..71ef45085 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -17,101 +17,13 @@ * */ -module \$__SHREG_ (input C, input D, input [31:0] L, input E, output Q); +module \$__SHREG_ (input C, input D, input E, output Q); parameter DEPTH = 0; parameter [DEPTH-1:0] INIT = 0; parameter CLKPOL = 1; parameter ENPOL = 2; - wire CE; - // shregmap's INIT parameter shifts out LSB first; - // however Xilinx expects MSB first - function [DEPTH-1:0] brev; - input [DEPTH-1:0] din; - integer i; - begin - for (i = 0; i < DEPTH; i=i+1) - brev[i] = din[DEPTH-1-i]; - end - endfunction - localparam [DEPTH-1:0] INIT_R = brev(INIT); - - parameter _TECHMAP_CONSTMSK_L_ = 0; - parameter _TECHMAP_CONSTVAL_L_ = 0; - - generate - if (ENPOL == 0) - assign CE = ~E; - else if (ENPOL == 1) - assign CE = E; - else - assign CE = 1'b1; - if (DEPTH == 1) begin - wire _TECHMAP_FAIL_ = ~&_TECHMAP_CONSTMSK_L_ || _TECHMAP_CONSTVAL_L_ != 0; - if (CLKPOL) - FDRE #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); - else - FDRE_1 #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); - end else - if (DEPTH <= 16) begin - SRL16E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A0(L[0]), .A1(L[1]), .A2(L[2]), .A3(L[3]), .CE(CE), .CLK(C), .D(D), .Q(Q)); - end else - if (DEPTH > 17 && DEPTH <= 32) begin - SRLC32E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(Q)); - end else - if (DEPTH > 33 && DEPTH <= 64) begin - wire T0, T1, T2; - SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - \$__SHREG_ #(.DEPTH(DEPTH-32), .INIT(INIT[DEPTH-32-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L), .E(E), .Q(T2)); - if (&_TECHMAP_CONSTMSK_L_) - assign Q = T2; - else - MUXF7 fpga_mux_0 (.O(Q), .I0(T0), .I1(T2), .S(L[5])); - end else - if (DEPTH > 65 && DEPTH <= 96) begin - wire T0, T1, T2, T3, T4, T5, T6; - SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); - \$__SHREG_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-64-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_2 (.C(C), .D(T3), .L(L[4:0]), .E(E), .Q(T4)); - if (&_TECHMAP_CONSTMSK_L_) - assign Q = T4; - else begin - MUXF7 fpga_mux_0 (.O(T5), .I0(T0), .I1(T2), .S(L[5])); - MUXF7 fpga_mux_1 (.O(T6), .I0(T4), .I1(1'b0 /* unused */), .S(L[5])); - MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(L[6])); - end - end else - if (DEPTH > 97 && DEPTH <= 128) begin - wire T0, T1, T2, T3, T4, T5, T6, T7, T8; - SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); - SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); - SRLC32E #(.INIT(INIT_R[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); - \$__SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-96-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .L(L[4:0]), .E(E), .Q(T6)); - if (&_TECHMAP_CONSTMSK_L_) - assign Q = T6; - else begin - MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(L[5])); - MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(L[5])); - MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(L[6])); - end - end - else if (DEPTH <= 128 || (DEPTH == 129 && &_TECHMAP_CONSTMSK_L_)) begin - // Handle cases where depth is just 1 over a convenient value, - if (&_TECHMAP_CONSTMSK_L_) begin - // For constant length, use the flop - wire T0; - \$__SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-1:1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(DEPTH-1-1), .E(E), .Q(T0)); - \$__SHREG_ #(.DEPTH(1), .INIT(INIT[0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .L(0), .E(E), .Q(Q)); - end - else begin - // For variable length, bump up to the next length - \$__SHREG_ #(.DEPTH(DEPTH+1), .INIT({INIT,1'b0}), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); - end - end - else begin - \$__XILINX_SHREG_ #(.DEPTH(DEPTH), .INIT(INIT), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); - end - endgenerate + \$__XILINX_SHREG_ #(.DEPTH(DEPTH), .INIT(INIT), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(DEPTH-1), .E(E), .Q(Q)); endmodule module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, output SO); @@ -135,22 +47,77 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o parameter _TECHMAP_CONSTMSK_L_ = 0; parameter _TECHMAP_CONSTVAL_L_ = 0; + wire CE; generate + if (ENPOL == 0) + assign CE = ~E; + else if (ENPOL == 1) + assign CE = E; + else + assign CE = 1'b1; if (DEPTH == 1) begin - \$__SHREG_ #(.DEPTH(DEPTH), .INIT(INIT), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(0), .E(E), .Q(Q)); - end - else if (DEPTH < 128) begin - \$__SHREG_ #(.DEPTH(DEPTH), .INIT(INIT), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); - end - else if (DEPTH == 128) begin - wire CE; - if (ENPOL == 0) - assign CE = ~E; - else if (ENPOL == 1) - assign CE = E; + //wire _TECHMAP_FAIL_ = ~&_TECHMAP_CONSTMSK_L_ || _TECHMAP_CONSTVAL_L_ != 0; + if (CLKPOL) + FDRE #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); else - assign CE = 1'b1; - + FDRE_1 #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); + end else + if (DEPTH <= 16) begin + SRL16E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A0(L[0]), .A1(L[1]), .A2(L[2]), .A3(L[3]), .CE(CE), .CLK(C), .D(D), .Q(Q)); + end else + if (DEPTH > 17 && DEPTH <= 32) begin + SRLC32E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(Q)); + end else + if (DEPTH > 33 && DEPTH <= 64) begin + wire T0, T1, T2; + SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-32), .INIT(INIT[DEPTH-32-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L), .E(E), .Q(T2)); + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T2; + else + MUXF7 fpga_mux_0 (.O(Q), .I0(T0), .I1(T2), .S(L[5])); + end else + if (DEPTH > 65 && DEPTH <= 96) begin + wire T0, T1, T2, T3, T4, T5, T6; + SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-64-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_2 (.C(C), .D(T3), .L(L[4:0]), .E(E), .Q(T4)); + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T4; + else begin + MUXF7 fpga_mux_0 (.O(T5), .I0(T0), .I1(T2), .S(L[5])); + MUXF7 fpga_mux_1 (.O(T6), .I0(T4), .I1(1'b0 /* unused */), .S(L[5])); + MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(L[6])); + end + end else + if (DEPTH > 97 && DEPTH < 128) begin + wire T0, T1, T2, T3, T4, T5, T6, T7, T8; + SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + SRLC32E #(.INIT(INIT_R[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-96-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .L(L[4:0]), .E(E), .Q(T6)); + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T6; + else begin + MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(L[5])); + MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(L[5])); + MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(L[6])); + end + end + else if (DEPTH < 128 || (DEPTH == 129 && &_TECHMAP_CONSTMSK_L_)) begin + // Handle cases where depth is just 1 over a convenient value, + if (&_TECHMAP_CONSTMSK_L_) begin + // For constant length, use the flop + wire T0; + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-1:1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(DEPTH-1-1), .E(E), .Q(T0)); + \$__XILINX_SHREG_ #(.DEPTH(1), .INIT(INIT[0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .L(0), .E(E), .Q(Q)); + end + else begin + // For variable length, bump up to the next length + \$__XILINX_SHREG_ #(.DEPTH(DEPTH+1), .INIT({INIT,1'b0}), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); + end + end + else if (DEPTH == 128) begin wire T0, T1, T2, T3, T4, T5, T6; SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); From 81c207fb9bc88c4e025ee058d767d33847682d19 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Mar 2019 10:55:14 -0700 Subject: [PATCH 28/64] Fine tune cells_map.v --- techlibs/xilinx/cells_map.v | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 71ef45085..c23e3f81a 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -104,19 +104,6 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(L[6])); end end - else if (DEPTH < 128 || (DEPTH == 129 && &_TECHMAP_CONSTMSK_L_)) begin - // Handle cases where depth is just 1 over a convenient value, - if (&_TECHMAP_CONSTMSK_L_) begin - // For constant length, use the flop - wire T0; - \$__XILINX_SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-1:1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(DEPTH-1-1), .E(E), .Q(T0)); - \$__XILINX_SHREG_ #(.DEPTH(1), .INIT(INIT[0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .L(0), .E(E), .Q(Q)); - end - else begin - // For variable length, bump up to the next length - \$__XILINX_SHREG_ #(.DEPTH(DEPTH+1), .INIT({INIT,1'b0}), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); - end - end else if (DEPTH == 128) begin wire T0, T1, T2, T3, T4, T5, T6; SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); @@ -132,20 +119,29 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(L[6])); end end - else if (DEPTH > 128) begin + else if (DEPTH <= 129 && ~&_TECHMAP_CONSTMSK_L_) begin + // Handle cases where depth is just 1 over a convenient value, + // For variable length, bump up to the next length + \$__XILINX_SHREG_ #(.DEPTH(DEPTH+1), .INIT({INIT,1'b0}), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); + end + else /*if (DEPTH > 128)*/ begin localparam lower_clog2 = $clog2((DEPTH+1)/2); localparam lower_depth = 2 ** lower_clog2; - wire T0, T1, T2; - \$__XILINX_SHREG_ #(.DEPTH(lower_depth), .INIT(INIT[DEPTH-1:DEPTH-lower_depth]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(L[lower_clog2-1:0]), .E(E), .Q(T0), .SO(T1)); - \$__XILINX_SHREG_ #(.DEPTH(DEPTH-lower_depth), .INIT(INIT[DEPTH-lower_depth-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L[lower_clog2-1:0]), .E(E), .Q(T2)); - if (&_TECHMAP_CONSTMSK_L_) - assign Q = T2; + wire T0, T1, T2, T3; + if (&_TECHMAP_CONSTMSK_L_) begin + \$__XILINX_SHREG_ #(.DEPTH(lower_depth), .INIT(INIT[DEPTH-1:DEPTH-lower_depth]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(lower_depth-1), .E(E), .Q(T0)); + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-lower_depth), .INIT(INIT[DEPTH-lower_depth-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .L(DEPTH-lower_depth-1), .E(E), .Q(Q), .SO(T3)); + end else begin + \$__XILINX_SHREG_ #(.DEPTH(lower_depth), .INIT(INIT[DEPTH-1:DEPTH-lower_depth]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(L[lower_clog2-1:0]), .E(E), .Q(T0), .SO(T1)); + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-lower_depth), .INIT(INIT[DEPTH-lower_depth-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L[lower_clog2-1:0]), .E(E), .Q(T2), .SO(T3)); //assign Q = L[lower_clog2-1] ? T2 : T0; // FIXME: Need to instantiate 2:1 MUX here since // techmap with this file is run AFTER abc LUT3 #(.INIT(8'b10101100)) fpga_mux (.I0(T2), .I1(T0), .I2(L[lower_clog2]), .O(Q)); end + if (DEPTH == 2 * lower_depth) + assign SO = T3; end endgenerate endmodule From 2b911e270ba8012aa85f342838ed31b54568f257 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Mar 2019 12:28:39 -0700 Subject: [PATCH 29/64] Fix spacing --- passes/techmap/shregmap.cc | 552 ++++++++++++++++++------------------- 1 file changed, 276 insertions(+), 276 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 1729418e6..028f4ba35 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -206,307 +206,307 @@ struct ShregmapTechXilinx7 : ShregmapTech struct ShregmapWorker { - Module *module; - SigMap sigmap; + Module *module; + SigMap sigmap; - const ShregmapOptions &opts; - int dff_count, shreg_count; + const ShregmapOptions &opts; + int dff_count, shreg_count; - pool remove_cells; - pool remove_init; + pool remove_cells; + pool remove_init; - dict sigbit_init; - dict sigbit_chain_next; - dict sigbit_chain_prev; - pool sigbit_with_non_chain_users; - pool chain_start_cells; + dict sigbit_init; + dict sigbit_chain_next; + dict sigbit_chain_prev; + pool sigbit_with_non_chain_users; + pool chain_start_cells; - void make_sigbit_chain_next_prev() - { - for (auto wire : module->wires()) + void make_sigbit_chain_next_prev() { - if (wire->port_output || wire->get_bool_attribute("\\keep")) { - 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("\\init")) { - SigSpec initsig = sigmap(wire); - Const initval = wire->attributes.at("\\init"); - for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) - if (initval[i] == State::S0 && !opts.zinit) - sigbit_init[initsig[i]] = false; - else if (initval[i] == State::S1) - sigbit_init[initsig[i]] = true; - } - } - - for (auto cell : module->cells()) - { - if (opts.ffcells.count(cell->type) && !cell->get_bool_attribute("\\keep")) - { - IdString d_port = opts.ffcells.at(cell->type).first; - IdString q_port = opts.ffcells.at(cell->type).second; - - SigBit d_bit = sigmap(cell->getPort(d_port).as_bit()); - SigBit q_bit = sigmap(cell->getPort(q_port).as_bit()); - - if (opts.init || sigbit_init.count(q_bit) == 0) + for (auto wire : module->wires()) { - if (sigbit_chain_next.count(d_bit)) { - sigbit_with_non_chain_users.insert(d_bit); - } else - sigbit_chain_next[d_bit] = cell; + if (wire->port_output || wire->get_bool_attribute("\\keep")) { + for (auto bit : sigmap(wire)) { + sigbit_with_non_chain_users.insert(bit); + if (opts.tech) opts.tech->non_chain_user(bit, nullptr, {}); + } + } - sigbit_chain_prev[q_bit] = cell; - continue; + if (wire->attributes.count("\\init")) { + SigSpec initsig = sigmap(wire); + Const initval = wire->attributes.at("\\init"); + for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) + if (initval[i] == State::S0 && !opts.zinit) + sigbit_init[initsig[i]] = false; + else if (initval[i] == State::S1) + sigbit_init[initsig[i]] = true; + } } - } - for (auto conn : cell->connections()) - if (cell->input(conn.first)) - 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); - } - } - } - - void find_chain_start_cells() - { - for (auto it : sigbit_chain_next) - { - if (opts.tech == nullptr && sigbit_with_non_chain_users.count(it.first)) - goto start_cell; - - 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; - - if (c1->parameters != c2->parameters) - goto start_cell; - - IdString d_port = opts.ffcells.at(c1->type).first; - IdString q_port = opts.ffcells.at(c1->type).second; - - auto c1_conn = c1->connections(); - auto c2_conn = c1->connections(); - - c1_conn.erase(d_port); - c1_conn.erase(q_port); - - c2_conn.erase(d_port); - c2_conn.erase(q_port); - - if (c1_conn != c2_conn) - goto start_cell; - - continue; - } - -start_cell: - chain_start_cells.insert(it.second); - } - } - - vector create_chain(Cell *start_cell) - { - vector chain; - - Cell *c = start_cell; - while (c != nullptr) - { - chain.push_back(c); - - IdString q_port = opts.ffcells.at(c->type).second; - SigBit q_bit = sigmap(c->getPort(q_port).as_bit()); - - if (sigbit_chain_next.count(q_bit) == 0) - break; - - c = sigbit_chain_next.at(q_bit); - if (chain_start_cells.count(c) != 0) - break; - } - - return chain; - } - - void process_chain(vector &chain) - { - if (GetSize(chain) < opts.keep_before + opts.minlen + opts.keep_after) - return; - - int cursor = opts.keep_before; - while (cursor < GetSize(chain) - opts.keep_after) - { - int depth = GetSize(chain) - opts.keep_after - cursor; - - if (opts.maxlen > 0) - depth = std::min(opts.maxlen, depth); - - Cell *first_cell = chain[cursor]; - IdString q_port = opts.ffcells.at(first_cell->type).second; - dict taps_dict; - - if (opts.tech) - { - vector qbits; - vector taps; - - for (int i = 0; i < depth; i++) + for (auto cell : module->cells()) { - Cell *cell = chain[cursor+i]; - auto qbit = sigmap(cell->getPort(q_port)); - qbits.push_back(qbit); + if (opts.ffcells.count(cell->type) && !cell->get_bool_attribute("\\keep")) + { + IdString d_port = opts.ffcells.at(cell->type).first; + IdString q_port = opts.ffcells.at(cell->type).second; - if (sigbit_with_non_chain_users.count(qbit)) - taps.push_back(i); + SigBit d_bit = sigmap(cell->getPort(d_port).as_bit()); + SigBit q_bit = sigmap(cell->getPort(q_port).as_bit()); + + if (opts.init || sigbit_init.count(q_bit) == 0) + { + if (sigbit_chain_next.count(d_bit)) { + sigbit_with_non_chain_users.insert(d_bit); + } else + sigbit_chain_next[d_bit] = cell; + + sigbit_chain_prev[q_bit] = cell; + continue; + } + } + + for (auto conn : cell->connections()) + if (cell->input(conn.first)) + 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); + } } - - while (depth > 0) - { - if (taps.empty() || taps.back() < depth-1) - taps.push_back(depth-1); - - if (opts.tech->analyze(taps, qbits)) - break; - - taps.pop_back(); - depth--; - } - - depth = 0; - for (auto tap : taps) { - taps_dict[tap] = qbits.at(tap); - log_assert(depth < tap+1); - depth = tap+1; - } - } - - if (depth < 2) { - cursor++; - continue; - } - - Cell *last_cell = chain[cursor+depth-1]; - - log("Converting %s.%s ... %s.%s to a shift register with depth %d.\n", - log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), depth); - - dff_count += depth; - shreg_count += 1; - - string shreg_cell_type_str = "$__SHREG"; - if (opts.params) { - shreg_cell_type_str += "_"; - } else { - if (first_cell->type[1] != '_') - shreg_cell_type_str += "_"; - shreg_cell_type_str += first_cell->type.substr(1); - } - - if (opts.init) { - vector initval; - for (int i = depth-1; i >= 0; i--) { - SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit()); - if (sigbit_init.count(bit) == 0) - initval.push_back(State::Sx); - else if (sigbit_init.at(bit)) - initval.push_back(State::S1); - else - initval.push_back(State::S0); - remove_init.insert(bit); - } - first_cell->setParam("\\INIT", initval); - } - - if (opts.zinit) - for (int i = depth-1; i >= 0; i--) { - SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit()); - remove_init.insert(bit); - } - - if (opts.params) - { - int param_clkpol = -1; - int param_enpol = 2; - - if (first_cell->type == "$_DFF_N_") param_clkpol = 0; - if (first_cell->type == "$_DFF_P_") param_clkpol = 1; - - if (first_cell->type == "$_DFFE_NN_") param_clkpol = 0, param_enpol = 0; - if (first_cell->type == "$_DFFE_NP_") param_clkpol = 0, param_enpol = 1; - if (first_cell->type == "$_DFFE_PN_") param_clkpol = 1, param_enpol = 0; - if (first_cell->type == "$_DFFE_PP_") param_clkpol = 1, param_enpol = 1; - - log_assert(param_clkpol >= 0); - first_cell->setParam("\\CLKPOL", param_clkpol); - if (opts.ffe) first_cell->setParam("\\ENPOL", param_enpol); - } - - first_cell->type = shreg_cell_type_str; - first_cell->setPort(q_port, last_cell->getPort(q_port)); - first_cell->setParam("\\DEPTH", depth); - - if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict)) - remove_cells.insert(first_cell); - - for (int i = 1; i < depth; i++) - remove_cells.insert(chain[cursor+i]); - cursor += depth; } - } - void cleanup() - { - for (auto cell : remove_cells) - module->remove(cell); - - for (auto wire : module->wires()) + void find_chain_start_cells() { - if (wire->attributes.count("\\init") == 0) - continue; + for (auto it : sigbit_chain_next) + { + if (opts.tech == nullptr && sigbit_with_non_chain_users.count(it.first)) + goto start_cell; - SigSpec initsig = sigmap(wire); - Const &initval = wire->attributes.at("\\init"); + if (sigbit_chain_prev.count(it.first) != 0) + { + Cell *c1 = sigbit_chain_prev.at(it.first); + Cell *c2 = it.second; - for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) - if (remove_init.count(initsig[i])) - initval[i] = State::Sx; + if (c1->type != c2->type) + goto start_cell; - if (SigSpec(initval).is_fully_undef()) - wire->attributes.erase("\\init"); + if (c1->parameters != c2->parameters) + goto start_cell; + + IdString d_port = opts.ffcells.at(c1->type).first; + IdString q_port = opts.ffcells.at(c1->type).second; + + auto c1_conn = c1->connections(); + auto c2_conn = c1->connections(); + + c1_conn.erase(d_port); + c1_conn.erase(q_port); + + c2_conn.erase(d_port); + c2_conn.erase(q_port); + + if (c1_conn != c2_conn) + goto start_cell; + + continue; + } + + start_cell: + chain_start_cells.insert(it.second); + } } - remove_cells.clear(); - sigbit_chain_next.clear(); - sigbit_chain_prev.clear(); - chain_start_cells.clear(); - } + vector create_chain(Cell *start_cell) + { + vector chain; - 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); + Cell *c = start_cell; + while (c != nullptr) + { + chain.push_back(c); - make_sigbit_chain_next_prev(); - find_chain_start_cells(); + IdString q_port = opts.ffcells.at(c->type).second; + SigBit q_bit = sigmap(c->getPort(q_port).as_bit()); - for (auto c : chain_start_cells) { - vector chain = create_chain(c); - process_chain(chain); + if (sigbit_chain_next.count(q_bit) == 0) + break; + + c = sigbit_chain_next.at(q_bit); + if (chain_start_cells.count(c) != 0) + break; + } + + return chain; } - cleanup(); - } + void process_chain(vector &chain) + { + if (GetSize(chain) < opts.keep_before + opts.minlen + opts.keep_after) + return; + + int cursor = opts.keep_before; + while (cursor < GetSize(chain) - opts.keep_after) + { + int depth = GetSize(chain) - opts.keep_after - cursor; + + if (opts.maxlen > 0) + depth = std::min(opts.maxlen, depth); + + Cell *first_cell = chain[cursor]; + IdString q_port = opts.ffcells.at(first_cell->type).second; + dict taps_dict; + + if (opts.tech) + { + vector qbits; + vector taps; + + for (int i = 0; i < depth; i++) + { + Cell *cell = chain[cursor+i]; + auto qbit = sigmap(cell->getPort(q_port)); + qbits.push_back(qbit); + + if (sigbit_with_non_chain_users.count(qbit)) + taps.push_back(i); + } + + while (depth > 0) + { + if (taps.empty() || taps.back() < depth-1) + taps.push_back(depth-1); + + if (opts.tech->analyze(taps, qbits)) + break; + + taps.pop_back(); + depth--; + } + + depth = 0; + for (auto tap : taps) { + taps_dict[tap] = qbits.at(tap); + log_assert(depth < tap+1); + depth = tap+1; + } + } + + if (depth < 2) { + cursor++; + continue; + } + + Cell *last_cell = chain[cursor+depth-1]; + + log("Converting %s.%s ... %s.%s to a shift register with depth %d.\n", + log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), depth); + + dff_count += depth; + shreg_count += 1; + + string shreg_cell_type_str = "$__SHREG"; + if (opts.params) { + shreg_cell_type_str += "_"; + } else { + if (first_cell->type[1] != '_') + shreg_cell_type_str += "_"; + shreg_cell_type_str += first_cell->type.substr(1); + } + + if (opts.init) { + vector initval; + for (int i = depth-1; i >= 0; i--) { + SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit()); + if (sigbit_init.count(bit) == 0) + initval.push_back(State::Sx); + else if (sigbit_init.at(bit)) + initval.push_back(State::S1); + else + initval.push_back(State::S0); + remove_init.insert(bit); + } + first_cell->setParam("\\INIT", initval); + } + + if (opts.zinit) + for (int i = depth-1; i >= 0; i--) { + SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit()); + remove_init.insert(bit); + } + + if (opts.params) + { + int param_clkpol = -1; + int param_enpol = 2; + + if (first_cell->type == "$_DFF_N_") param_clkpol = 0; + if (first_cell->type == "$_DFF_P_") param_clkpol = 1; + + if (first_cell->type == "$_DFFE_NN_") param_clkpol = 0, param_enpol = 0; + if (first_cell->type == "$_DFFE_NP_") param_clkpol = 0, param_enpol = 1; + if (first_cell->type == "$_DFFE_PN_") param_clkpol = 1, param_enpol = 0; + if (first_cell->type == "$_DFFE_PP_") param_clkpol = 1, param_enpol = 1; + + log_assert(param_clkpol >= 0); + first_cell->setParam("\\CLKPOL", param_clkpol); + if (opts.ffe) first_cell->setParam("\\ENPOL", param_enpol); + } + + first_cell->type = shreg_cell_type_str; + first_cell->setPort(q_port, last_cell->getPort(q_port)); + first_cell->setParam("\\DEPTH", depth); + + if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict)) + remove_cells.insert(first_cell); + + for (int i = 1; i < depth; i++) + remove_cells.insert(chain[cursor+i]); + cursor += depth; + } + } + + void cleanup() + { + for (auto cell : remove_cells) + module->remove(cell); + + for (auto wire : module->wires()) + { + if (wire->attributes.count("\\init") == 0) + continue; + + SigSpec initsig = sigmap(wire); + Const &initval = wire->attributes.at("\\init"); + + for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) + if (remove_init.count(initsig[i])) + initval[i] = State::Sx; + + if (SigSpec(initval).is_fully_undef()) + wire->attributes.erase("\\init"); + } + + remove_cells.clear(); + sigbit_chain_next.clear(); + sigbit_chain_prev.clear(); + chain_start_cells.clear(); + } + + 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(); + + for (auto c : chain_start_cells) { + vector chain = create_chain(c); + process_chain(chain); + } + + cleanup(); + } }; struct ShregmapPass : public Pass { From 5597270b9e2331d8836c8c24a073aadc1e19584a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Mar 2019 10:20:27 -0700 Subject: [PATCH 30/64] Opt --- passes/techmap/shregmap.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 028f4ba35..d5221d46f 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -102,7 +102,7 @@ struct ShregmapTechXilinx7 : ShregmapTech virtual void init(const Module* module, const SigMap &sigmap) override { - for (auto i : module->cells_) { + for (const auto &i : module->cells_) { auto cell = i.second; if (cell->type != "$shiftx") continue; if (cell->getParam("\\Y_WIDTH") != 1) continue; From 4cc6b3e942a54e94f472df7817788dc321955a20 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Mar 2019 15:04:44 -0700 Subject: [PATCH 31/64] Add '-nosrl' option to synth_xilinx --- techlibs/xilinx/synth_xilinx.cc | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 0eccb97f2..5237cc4c6 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -64,10 +64,13 @@ struct SynthXilinxPass : public Pass log(" (this feature is experimental and incomplete)\n"); log("\n"); log(" -nobram\n"); - log(" disable infering of block rams\n"); + log(" disable inference of block rams\n"); log("\n"); log(" -nodram\n"); - log(" disable infering of distributed rams\n"); + log(" disable inference of distributed rams\n"); + log("\n"); + log(" -nobram\n"); + log(" disable inference of shift registers\n"); log("\n"); log(" -run :\n"); log(" only run the commands between the labels (see below). an empty\n"); @@ -110,8 +113,8 @@ struct SynthXilinxPass : public Pass log(" dffsr2dff\n"); log(" dff2dffe\n"); log(" opt -full\n"); - log(" simplemap t:$dff*\n"); - log(" shregmap -tech xilinx\n"); + log(" simplemap t:$dff* (only without -nosrl)\n"); + log(" shregmap -tech xilinx (only without -nosrl)\n"); log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v\n"); log(" opt -fast\n"); log("\n"); @@ -149,6 +152,7 @@ struct SynthXilinxPass : public Pass bool vpr = false; bool nobram = false; bool nodram = false; + bool nosrl = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -193,6 +197,10 @@ struct SynthXilinxPass : public Pass nodram = true; continue; } + if (args[argidx] == "-nosrl") { + nosrl = true; + continue; + } break; } extra_args(args, argidx, design); @@ -257,8 +265,10 @@ struct SynthXilinxPass : public Pass Pass::call(design, "dff2dffe"); Pass::call(design, "opt -full"); - Pass::call(design, "simplemap t:$dff*"); - Pass::call(design, "shregmap -tech xilinx"); + if (!nosrl) { + Pass::call(design, "simplemap t:$dff*"); + Pass::call(design, "shregmap -tech xilinx"); + } if (vpr) { Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v -D _EXPLICIT_CARRY"); From 03d108cd1f785fd32394746221fb81380b051ed1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Mar 2019 17:46:49 -0700 Subject: [PATCH 32/64] Working for 1 bit --- passes/techmap/shregmap.cc | 60 +++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index d5221d46f..5c0f7191a 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -104,12 +104,23 @@ struct ShregmapTechXilinx7 : ShregmapTech { for (const auto &i : module->cells_) { auto cell = i.second; - if (cell->type != "$shiftx") continue; - if (cell->getParam("\\Y_WIDTH") != 1) continue; - int j = 0; - for (auto bit : sigmap(cell->getPort("\\A"))) - sigbit_to_shiftx_offset[bit] = std::make_pair(cell, j++); - log_assert(j == cell->getParam("\\A_WIDTH").as_int()); + if (cell->type == "$shiftx") { + if (cell->getParam("\\Y_WIDTH") != 1) continue; + int j = 0; + for (auto bit : sigmap(cell->getPort("\\A"))) + sigbit_to_shiftx_offset[bit] = std::make_pair(cell, j++); + log_assert(j == cell->getParam("\\A_WIDTH").as_int()); + } + else if (cell->type == "$pmux") { + if (cell->getParam("\\WIDTH") != 1) continue; + auto a_bit = sigmap(cell->getPort("\\A")).as_bit(); + sigbit_to_shiftx_offset[a_bit] = std::make_pair(cell, 0); + int j = cell->getParam("\\S_WIDTH").as_int(); + for (auto bit : sigmap(cell->getPort("\\B"))) + sigbit_to_shiftx_offset[bit] = std::make_pair(cell, j--); + log_assert(j == 0); + + } } } @@ -118,8 +129,12 @@ struct ShregmapTechXilinx7 : ShregmapTech auto it = sigbit_to_shiftx_offset.find(bit); if (it == sigbit_to_shiftx_offset.end()) return; - if (cell && cell->type == "$shiftx" && port == "\\A") - return; + if (cell) { + if (cell->type == "$shiftx" && port == "\\A") + return; + if (cell->type == "$pmux" && (port == "\\A" || port == "\\B")) + return; + } sigbit_to_shiftx_offset.erase(it); } @@ -166,8 +181,15 @@ struct ShregmapTechXilinx7 : ShregmapTech log_assert(shiftx); // Only map if $shiftx exclusively covers the shift register - if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) - return false; + if (shiftx->type == "$shiftx") { + if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) + return false; + } + else if (shiftx->type == "$pmux") { + if (GetSize(taps) != shiftx->getParam("\\S_WIDTH").as_int() + 1) + return false; + } + else log_abort(); return true; } @@ -193,9 +215,25 @@ struct ShregmapTechXilinx7 : ShregmapTech newcell->setPort("\\E", cell->getPort("\\E")); Cell* shiftx = it->second.first; + RTLIL::SigSpec l_wire; + if (shiftx->type == "$shiftx") { + l_wire = shiftx->getPort("\\B"); + } + else if (shiftx->type == "$pmux") { + // Create a new encoder, out of a $pmux, that takes + // the existing pmux's 'S' input and transforms it + // back into a binary value + int clog2taps = ceil(log2(taps.size())); + RTLIL::SigSpec b_port; + for (int i = shiftx->getParam("\\S_WIDTH").as_int(); i > 0; i--) + b_port.append(RTLIL::Const(i, clog2taps)); + l_wire = cell->module->addWire(NEW_ID, clog2taps); + cell->module->addPmux(NEW_ID, RTLIL::Const(0, clog2taps), b_port, shiftx->getPort("\\S"), l_wire); + } + else log_abort(); - newcell->setPort("\\L", shiftx->getPort("\\B")); newcell->setPort("\\Q", shiftx->getPort("\\Y")); + newcell->setPort("\\L", l_wire); cell->module->remove(shiftx); From 456295eb6686316dd6090ed32787bd91dc6e8d61 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Mar 2019 18:32:42 -0700 Subject: [PATCH 33/64] Fixes for multibit --- passes/techmap/shregmap.cc | 56 ++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 5c0f7191a..7e01ff134 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -95,7 +95,7 @@ struct ShregmapTechGreenpak4 : ShregmapTech struct ShregmapTechXilinx7 : ShregmapTech { - dict> sigbit_to_shiftx_offset; + dict> sigbit_to_shiftx_offset; const ShregmapOptions &opts; ShregmapTechXilinx7(const ShregmapOptions &opts) : opts(opts) {} @@ -108,18 +108,25 @@ struct ShregmapTechXilinx7 : ShregmapTech if (cell->getParam("\\Y_WIDTH") != 1) continue; int j = 0; for (auto bit : sigmap(cell->getPort("\\A"))) - sigbit_to_shiftx_offset[bit] = std::make_pair(cell, j++); + sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j++, 0); log_assert(j == cell->getParam("\\A_WIDTH").as_int()); } else if (cell->type == "$pmux") { - if (cell->getParam("\\WIDTH") != 1) continue; - auto a_bit = sigmap(cell->getPort("\\A")).as_bit(); - sigbit_to_shiftx_offset[a_bit] = std::make_pair(cell, 0); - int j = cell->getParam("\\S_WIDTH").as_int(); - for (auto bit : sigmap(cell->getPort("\\B"))) - sigbit_to_shiftx_offset[bit] = std::make_pair(cell, j--); + int width = cell->getParam("\\WIDTH").as_int(); + int j = 0; + for (auto bit : cell->getPort("\\A")) + sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 0, j++); + j = cell->getParam("\\S_WIDTH").as_int(); + int k = 0; + for (auto bit : sigmap(cell->getPort("\\B"))) { + printf("%d\n", bit.offset); + sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j, k++); + if (k == width) { + k = 0; + --j; + } + } log_assert(j == 0); - } } } @@ -140,6 +147,9 @@ struct ShregmapTechXilinx7 : ShregmapTech virtual bool analyze(vector &taps, const vector &qbits) override { + log("analyze() with %zu taps", taps.size()); + for (auto t : taps) log(" %d", t); + log("\n"); if (GetSize(taps) == 1) return taps[0] >= opts.minlen-1; @@ -147,6 +157,7 @@ struct ShregmapTechXilinx7 : ShregmapTech return false; Cell *shiftx = nullptr; + int group = 0; for (int i = 0; i < GetSize(taps); ++i) { // Check taps are sequential if (i != taps[i]) @@ -159,8 +170,8 @@ struct ShregmapTechXilinx7 : ShregmapTech return false; } else { - shiftx = it->second.first; - int offset = it->second.second; + int offset; + std::tie(shiftx,offset,group) = it->second; if (offset != i) return false; } @@ -170,11 +181,15 @@ struct ShregmapTechXilinx7 : ShregmapTech return false; } else { - if (shiftx != it->second.first) + Cell *shiftx_ = std::get<0>(it->second); + if (shiftx_ != shiftx) return false; - int offset = it->second.second; + int offset = std::get<1>(it->second); if (offset != i) return false; + int group_ = std::get<2>(it->second); + if (group_ != group) + return false; } } } @@ -214,10 +229,12 @@ struct ShregmapTechXilinx7 : ShregmapTech newcell->setPort("\\D", cell->getPort("\\D")); newcell->setPort("\\E", cell->getPort("\\E")); - Cell* shiftx = it->second.first; - RTLIL::SigSpec l_wire; + Cell* shiftx = std::get<0>(it->second); + RTLIL::SigSpec l_wire, q_wire; if (shiftx->type == "$shiftx") { l_wire = shiftx->getPort("\\B"); + q_wire = shiftx->getPort("\\Y"); + shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); } else if (shiftx->type == "$pmux") { // Create a new encoder, out of a $pmux, that takes @@ -229,14 +246,17 @@ struct ShregmapTechXilinx7 : ShregmapTech b_port.append(RTLIL::Const(i, clog2taps)); l_wire = cell->module->addWire(NEW_ID, clog2taps); cell->module->addPmux(NEW_ID, RTLIL::Const(0, clog2taps), b_port, shiftx->getPort("\\S"), l_wire); + int group = std::get<2>(it->second); + RTLIL::SigSpec y_wire = shiftx->getPort("\\Y"); + q_wire = y_wire[group]; + y_wire[group] = cell->module->addWire(NEW_ID); + shiftx->setPort("\\Y", y_wire); } else log_abort(); - newcell->setPort("\\Q", shiftx->getPort("\\Y")); + newcell->setPort("\\Q", q_wire); newcell->setPort("\\L", l_wire); - cell->module->remove(shiftx); - return false; } }; From 0895093c7ce91e13c7fa8e878ae41f8877b3870d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Mar 2019 19:14:04 -0700 Subject: [PATCH 34/64] Leftover printf --- passes/techmap/shregmap.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 7e01ff134..d9a4aba99 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -119,7 +119,6 @@ struct ShregmapTechXilinx7 : ShregmapTech j = cell->getParam("\\S_WIDTH").as_int(); int k = 0; for (auto bit : sigmap(cell->getPort("\\B"))) { - printf("%d\n", bit.offset); sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j, k++); if (k == width) { k = 0; From 098bd5758fe2e4cb7efa44503a1c498b0a2ace5e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Mar 2019 23:22:19 -0700 Subject: [PATCH 35/64] Add support for SHREGMAP+$mux, also fine tune $pmux --- passes/techmap/shregmap.cc | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index d9a4aba99..fb48094ec 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -111,6 +111,14 @@ struct ShregmapTechXilinx7 : ShregmapTech sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j++, 0); log_assert(j == cell->getParam("\\A_WIDTH").as_int()); } + else if (cell->type == "$mux") { + int j = 0; + for (auto bit : cell->getPort("\\A")) + sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 0, j++); + j = 0; + for (auto bit : sigmap(cell->getPort("\\B"))) + sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 1, j++); + } else if (cell->type == "$pmux") { int width = cell->getParam("\\WIDTH").as_int(); int j = 0; @@ -140,6 +148,8 @@ struct ShregmapTechXilinx7 : ShregmapTech return; if (cell->type == "$pmux" && (port == "\\A" || port == "\\B")) return; + if (cell->type == "$mux" && (port == "\\A" || port == "\\B")) + return; } sigbit_to_shiftx_offset.erase(it); } @@ -203,6 +213,10 @@ struct ShregmapTechXilinx7 : ShregmapTech if (GetSize(taps) != shiftx->getParam("\\S_WIDTH").as_int() + 1) return false; } + else if (shiftx->type == "$mux") { + if (GetSize(taps) != 2) + return false; + } else log_abort(); return true; @@ -243,14 +257,23 @@ struct ShregmapTechXilinx7 : ShregmapTech RTLIL::SigSpec b_port; for (int i = shiftx->getParam("\\S_WIDTH").as_int(); i > 0; i--) b_port.append(RTLIL::Const(i, clog2taps)); + for (int i = (1 << clog2taps); i > shiftx->getParam("\\S_WIDTH").as_int(); i--) + b_port.append(RTLIL::Const(RTLIL::Sx, clog2taps)); l_wire = cell->module->addWire(NEW_ID, clog2taps); - cell->module->addPmux(NEW_ID, RTLIL::Const(0, clog2taps), b_port, shiftx->getPort("\\S"), l_wire); + RTLIL::SigSpec s_wire = cell->module->addWire(NEW_ID, (1 << clog2taps)); + cell->module->connect(s_wire.extract(0, shiftx->getParam("\\S_WIDTH").as_int()), shiftx->getPort("\\S")); + cell->module->addPmux(NEW_ID, RTLIL::Const(0, clog2taps), b_port, s_wire, l_wire); int group = std::get<2>(it->second); RTLIL::SigSpec y_wire = shiftx->getPort("\\Y"); q_wire = y_wire[group]; y_wire[group] = cell->module->addWire(NEW_ID); shiftx->setPort("\\Y", y_wire); } + else if (shiftx->type == "$mux") { + l_wire = shiftx->getPort("\\S"); + q_wire = shiftx->getPort("\\Y"); + shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); + } else log_abort(); newcell->setPort("\\Q", q_wire); From bf83c074c82756b1cd23a9c3998b6c4d535dae29 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 23 Mar 2019 16:09:38 -0700 Subject: [PATCH 36/64] Cope with SHREG not having E port; Revert $pmux fine tune --- passes/techmap/shregmap.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index fb48094ec..7cf52c19a 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -240,7 +240,8 @@ struct ShregmapTechXilinx7 : ShregmapTech newcell->setPort("\\C", cell->getPort("\\C")); newcell->setPort("\\D", cell->getPort("\\D")); - newcell->setPort("\\E", cell->getPort("\\E")); + if (cell->hasPort("\\E")) + newcell->setPort("\\E", cell->getPort("\\E")); Cell* shiftx = std::get<0>(it->second); RTLIL::SigSpec l_wire, q_wire; @@ -257,10 +258,8 @@ struct ShregmapTechXilinx7 : ShregmapTech RTLIL::SigSpec b_port; for (int i = shiftx->getParam("\\S_WIDTH").as_int(); i > 0; i--) b_port.append(RTLIL::Const(i, clog2taps)); - for (int i = (1 << clog2taps); i > shiftx->getParam("\\S_WIDTH").as_int(); i--) - b_port.append(RTLIL::Const(RTLIL::Sx, clog2taps)); l_wire = cell->module->addWire(NEW_ID, clog2taps); - RTLIL::SigSpec s_wire = cell->module->addWire(NEW_ID, (1 << clog2taps)); + RTLIL::SigSpec s_wire = cell->module->addWire(NEW_ID, shiftx->getParam("\\S_WIDTH").as_int()); cell->module->connect(s_wire.extract(0, shiftx->getParam("\\S_WIDTH").as_int()), shiftx->getPort("\\S")); cell->module->addPmux(NEW_ID, RTLIL::Const(0, clog2taps), b_port, s_wire, l_wire); int group = std::get<2>(it->second); From f9fb05cf6684d855ce2fc776a20cd5552a4ef4a8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Mar 2019 13:18:55 -0700 Subject: [PATCH 37/64] synth_xilinx to use shregmap with -minlen 3 --- techlibs/xilinx/synth_xilinx.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 5237cc4c6..b6225a1a3 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -114,7 +114,7 @@ struct SynthXilinxPass : public Pass log(" dff2dffe\n"); log(" opt -full\n"); log(" simplemap t:$dff* (only without -nosrl)\n"); - log(" shregmap -tech xilinx (only without -nosrl)\n"); + log(" shregmap -tech xilinx -minlen 3 (only without -nosrl)\n"); log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v\n"); log(" opt -fast\n"); log("\n"); @@ -267,7 +267,7 @@ struct SynthXilinxPass : public Pass if (!nosrl) { Pass::call(design, "simplemap t:$dff*"); - Pass::call(design, "shregmap -tech xilinx"); + Pass::call(design, "shregmap -tech xilinx -minlen 3"); } if (vpr) { From f7a0434d54261834a7371727741e5cdf24ec5ca0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 3 Apr 2019 07:05:28 -0700 Subject: [PATCH 38/64] Add changelog entry --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 42e01645e..95bbb3f33 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,6 +16,7 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "gate2lut.v" techmap rule - Added "rename -src" - Added "equiv_opt" pass + - Added "shregmap -tech xilinx", used by "synth_xilinx" Yosys 0.7 .. Yosys 0.8 From 88630cd02cfb7cb124c949777280b60f66ee5eb5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 3 Apr 2019 07:14:20 -0700 Subject: [PATCH 39/64] Disable shregmap in synth_xilinx if -retime --- techlibs/xilinx/synth_xilinx.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index b6225a1a3..df30a22de 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -113,8 +113,8 @@ struct SynthXilinxPass : public Pass log(" dffsr2dff\n"); log(" dff2dffe\n"); log(" opt -full\n"); - log(" simplemap t:$dff* (only without -nosrl)\n"); - log(" shregmap -tech xilinx -minlen 3 (only without -nosrl)\n"); + log(" simplemap t:$dff* (without -nosrl and without -retime only)\n"); + log(" shregmap -tech xilinx -minlen 3 (without -nosrl and without -retime only)\n"); log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v\n"); log(" opt -fast\n"); log("\n"); @@ -265,7 +265,7 @@ struct SynthXilinxPass : public Pass Pass::call(design, "dff2dffe"); Pass::call(design, "opt -full"); - if (!nosrl) { + if (!nosrl && !retime) { Pass::call(design, "simplemap t:$dff*"); Pass::call(design, "shregmap -tech xilinx -minlen 3"); } From ff385a5ad0570cb56ae63d450e1dcba76ffaff7e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 3 Apr 2019 08:14:09 -0700 Subject: [PATCH 40/64] Remove duplicate STARTUPE2 --- techlibs/xilinx/cells_xtra.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/techlibs/xilinx/cells_xtra.sh b/techlibs/xilinx/cells_xtra.sh index 3f8efeebd..c23e67029 100644 --- a/techlibs/xilinx/cells_xtra.sh +++ b/techlibs/xilinx/cells_xtra.sh @@ -137,7 +137,6 @@ function xtract_cell_decl() xtract_cell_decl ROM64X1 #xtract_cell_decl SRL16E #xtract_cell_decl SRLC32E - xtract_cell_decl STARTUPE2 xtract_cell_decl STARTUPE2 "(* keep *)" xtract_cell_decl USR_ACCESSE2 xtract_cell_decl XADC From 0e2d929cead2a32ae176a408da257ec5b8b79f47 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 3 Apr 2019 08:28:07 -0700 Subject: [PATCH 41/64] -nosrl meant when -nobram --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index df30a22de..601a6811d 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -69,7 +69,7 @@ struct SynthXilinxPass : public Pass log(" -nodram\n"); log(" disable inference of distributed rams\n"); log("\n"); - log(" -nobram\n"); + log(" -nosrl\n"); log(" disable inference of shift registers\n"); log("\n"); log(" -run :\n"); From aa693d5723ef1438d42cd35a26673703b1eff79f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 3 Apr 2019 08:35:32 -0700 Subject: [PATCH 42/64] Remove handling for $pmux, since #895 --- passes/techmap/shregmap.cc | 40 -------------------------------------- 1 file changed, 40 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 7cf52c19a..408e3f8c7 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -119,22 +119,6 @@ struct ShregmapTechXilinx7 : ShregmapTech for (auto bit : sigmap(cell->getPort("\\B"))) sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 1, j++); } - else if (cell->type == "$pmux") { - int width = cell->getParam("\\WIDTH").as_int(); - int j = 0; - for (auto bit : cell->getPort("\\A")) - sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 0, j++); - j = cell->getParam("\\S_WIDTH").as_int(); - int k = 0; - for (auto bit : sigmap(cell->getPort("\\B"))) { - sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j, k++); - if (k == width) { - k = 0; - --j; - } - } - log_assert(j == 0); - } } } @@ -146,8 +130,6 @@ struct ShregmapTechXilinx7 : ShregmapTech if (cell) { if (cell->type == "$shiftx" && port == "\\A") return; - if (cell->type == "$pmux" && (port == "\\A" || port == "\\B")) - return; if (cell->type == "$mux" && (port == "\\A" || port == "\\B")) return; } @@ -209,10 +191,6 @@ struct ShregmapTechXilinx7 : ShregmapTech if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) return false; } - else if (shiftx->type == "$pmux") { - if (GetSize(taps) != shiftx->getParam("\\S_WIDTH").as_int() + 1) - return false; - } else if (shiftx->type == "$mux") { if (GetSize(taps) != 2) return false; @@ -250,24 +228,6 @@ struct ShregmapTechXilinx7 : ShregmapTech q_wire = shiftx->getPort("\\Y"); shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); } - else if (shiftx->type == "$pmux") { - // Create a new encoder, out of a $pmux, that takes - // the existing pmux's 'S' input and transforms it - // back into a binary value - int clog2taps = ceil(log2(taps.size())); - RTLIL::SigSpec b_port; - for (int i = shiftx->getParam("\\S_WIDTH").as_int(); i > 0; i--) - b_port.append(RTLIL::Const(i, clog2taps)); - l_wire = cell->module->addWire(NEW_ID, clog2taps); - RTLIL::SigSpec s_wire = cell->module->addWire(NEW_ID, shiftx->getParam("\\S_WIDTH").as_int()); - cell->module->connect(s_wire.extract(0, shiftx->getParam("\\S_WIDTH").as_int()), shiftx->getPort("\\S")); - cell->module->addPmux(NEW_ID, RTLIL::Const(0, clog2taps), b_port, s_wire, l_wire); - int group = std::get<2>(it->second); - RTLIL::SigSpec y_wire = shiftx->getPort("\\Y"); - q_wire = y_wire[group]; - y_wire[group] = cell->module->addWire(NEW_ID); - shiftx->setPort("\\Y", y_wire); - } else if (shiftx->type == "$mux") { l_wire = shiftx->getPort("\\S"); q_wire = shiftx->getPort("\\Y"); From 736e19f02d9980691e244e08b711c5e8c0b4fc76 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 4 Apr 2019 07:39:19 -0700 Subject: [PATCH 43/64] t:$dff* -> t:$dff t:$dffe --- techlibs/xilinx/synth_xilinx.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 601a6811d..5a3725e7d 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -113,7 +113,7 @@ struct SynthXilinxPass : public Pass log(" dffsr2dff\n"); log(" dff2dffe\n"); log(" opt -full\n"); - log(" simplemap t:$dff* (without -nosrl and without -retime only)\n"); + log(" simplemap t:$dff t:$dffe (without -nosrl and without -retime only)\n"); log(" shregmap -tech xilinx -minlen 3 (without -nosrl and without -retime only)\n"); log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v\n"); log(" opt -fast\n"); @@ -266,7 +266,7 @@ struct SynthXilinxPass : public Pass Pass::call(design, "opt -full"); if (!nosrl && !retime) { - Pass::call(design, "simplemap t:$dff*"); + Pass::call(design, "simplemap t:$dff t:$dffe"); Pass::call(design, "shregmap -tech xilinx -minlen 3"); } From 77755b5a662a11a3dcc18c070e6ea859104fc872 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 4 Apr 2019 07:41:40 -0700 Subject: [PATCH 44/64] Cleanup comments --- techlibs/xilinx/cells_map.v | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index c23e3f81a..2c88e0141 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -56,7 +56,6 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o else assign CE = 1'b1; if (DEPTH == 1) begin - //wire _TECHMAP_FAIL_ = ~&_TECHMAP_CONSTMSK_L_ || _TECHMAP_CONSTVAL_L_ != 0; if (CLKPOL) FDRE #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); else @@ -120,11 +119,11 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o end end else if (DEPTH <= 129 && ~&_TECHMAP_CONSTMSK_L_) begin - // Handle cases where depth is just 1 over a convenient value, - // For variable length, bump up to the next length + // Handle cases where fixed-length depth is + // just 1 over a convenient value \$__XILINX_SHREG_ #(.DEPTH(DEPTH+1), .INIT({INIT,1'b0}), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); end - else /*if (DEPTH > 128)*/ begin + else begin localparam lower_clog2 = $clog2((DEPTH+1)/2); localparam lower_depth = 2 ** lower_clog2; wire T0, T1, T2, T3; @@ -135,9 +134,9 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o else begin \$__XILINX_SHREG_ #(.DEPTH(lower_depth), .INIT(INIT[DEPTH-1:DEPTH-lower_depth]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(L[lower_clog2-1:0]), .E(E), .Q(T0), .SO(T1)); \$__XILINX_SHREG_ #(.DEPTH(DEPTH-lower_depth), .INIT(INIT[DEPTH-lower_depth-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L[lower_clog2-1:0]), .E(E), .Q(T2), .SO(T3)); - //assign Q = L[lower_clog2-1] ? T2 : T0; // FIXME: Need to instantiate 2:1 MUX here since // techmap with this file is run AFTER abc + //assign Q = L[lower_clog2-1] ? T2 : T0; LUT3 #(.INIT(8'b10101100)) fpga_mux (.I0(T2), .I1(T0), .I2(L[lower_clog2]), .O(Q)); end if (DEPTH == 2 * lower_depth) From 2fb02247a71253460cadef492f01dac8cb8c831b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 4 Apr 2019 08:10:40 -0700 Subject: [PATCH 45/64] Use soft-logic, not LUT3 instantiation --- techlibs/xilinx/cells_map.v | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 2c88e0141..4173814fd 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -134,10 +134,8 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o else begin \$__XILINX_SHREG_ #(.DEPTH(lower_depth), .INIT(INIT[DEPTH-1:DEPTH-lower_depth]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(L[lower_clog2-1:0]), .E(E), .Q(T0), .SO(T1)); \$__XILINX_SHREG_ #(.DEPTH(DEPTH-lower_depth), .INIT(INIT[DEPTH-lower_depth-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L[lower_clog2-1:0]), .E(E), .Q(T2), .SO(T3)); - // FIXME: Need to instantiate 2:1 MUX here since - // techmap with this file is run AFTER abc - //assign Q = L[lower_clog2-1] ? T2 : T0; - LUT3 #(.INIT(8'b10101100)) fpga_mux (.I0(T2), .I1(T0), .I2(L[lower_clog2]), .O(Q)); + wire [1023:0] _TECHMAP_DO_ = "techmap -map +/techmap.v"; + assign Q = L[lower_clog2] ? T2 : T0; end if (DEPTH == 2 * lower_depth) assign SO = T3; From 544843da717734ab9bd9bd88f71db2475fc3abc0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 5 Apr 2019 12:55:52 -0700 Subject: [PATCH 46/64] techmap inside map_cells stage --- techlibs/xilinx/cells_map.v | 1 - techlibs/xilinx/synth_xilinx.cc | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 4173814fd..c80e51bd0 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -134,7 +134,6 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o else begin \$__XILINX_SHREG_ #(.DEPTH(lower_depth), .INIT(INIT[DEPTH-1:DEPTH-lower_depth]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(L[lower_clog2-1:0]), .E(E), .Q(T0), .SO(T1)); \$__XILINX_SHREG_ #(.DEPTH(DEPTH-lower_depth), .INIT(INIT[DEPTH-lower_depth-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L[lower_clog2-1:0]), .E(E), .Q(T2), .SO(T3)); - wire [1023:0] _TECHMAP_DO_ = "techmap -map +/techmap.v"; assign Q = L[lower_clog2] ? T2 : T0; end if (DEPTH == 2 * lower_depth) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 326684daf..cabf0b76e 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -283,7 +283,7 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "map_cells")) { - Pass::call(design, "techmap -map +/xilinx/cells_map.v"); + Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/cells_map.v"); Pass::call(design, "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"); Pass::call(design, "clean"); From a5f33b5409d9325730204eb776e0046726d55d2c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 5 Apr 2019 16:20:43 -0700 Subject: [PATCH 47/64] Move dffinit til after abc --- techlibs/xilinx/.synth_xilinx.cc.swn | Bin 24576 -> 0 bytes techlibs/xilinx/.synth_xilinx.cc.swo | Bin 20480 -> 0 bytes techlibs/xilinx/synth_xilinx.cc | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 techlibs/xilinx/.synth_xilinx.cc.swn delete mode 100644 techlibs/xilinx/.synth_xilinx.cc.swo diff --git a/techlibs/xilinx/.synth_xilinx.cc.swn b/techlibs/xilinx/.synth_xilinx.cc.swn deleted file mode 100644 index a6564691a9dd301e314532bf5953acd2a49674ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24576 zcmeI4e~cqneZbukD4UQ#n^vVNf_F~1+s&@Mw|9Yty~`!OUGJ^Mu6JX5?{c||EdLm< zr)PUC&v@@Pm!qwc7H9>cfvQRiw4m}MG=)}z7BvzSAyiU@6p)cN|naC&)V~TeBbwd-;a6oeQ&OO_;hAf-IhEY8+r&REQ-R!u{~clqdacA{$77aXfSI`P|d!r5)h-nM6(CEGDNvyM@zH_Wm7oF5LqCyKxBc)0{`zV;Iyxa{Q|Z4QLiTc6ZemJ*Z%i41M$^?_?LUvj`#i4 zK>W+R>sNZ;tDazAz84&QMHYxG5LqCyKxBc)0+9tG3q%%(ED%{BvOr{k$O8Wh7AWx` zFVE(`FAw7E|NGDXKYVp8_I3Cg{02M(Y54COVzE!dA3+t~08d>Xi@gI*!1J$)#Xbd( z!pGrb@T<^(9L&R8;3l{Zu7yutM|yZ4JOE8N2XBQ8EW=H30KR^0EcP@!2A_o@-iciHVb!=n)d@DY6j4JBzz=b4|PpwgM9HSK)*X~%Ap$IR-yv{vo zwHn*Xtf_<-JQYYExX>B+Q#XxHsZ*(Mt3;)4R4%9lXF}9*{+tL+-!V$n;+D}dsf0>! z6huw?XF)%~>%T4ZC>B>6G@H*EX9WSZYyqNf*QBmzQpg-0=E$Tk24$TsfpJnoeCMs?9~;w+E3*-~YrW}$me)uB9o#|T6OE_}(zuv*(qt7|LA z!U9;NRaI6^|MV=N8m8?eL$lX9R#P=fWuu{7+w}=Mq?_f?jKbK;Xto_JZ1oa{iqjpt zg8@a6UOSZy=b~Y_fx0YPP1=Tm8EDa|B=TMHLn0F*>bU4w)cH=#)8W0Jfy99e-!xUz zE|nXGGFvsHW3(!Un8mJ}HAi*maB@z{9?F<#S$3xp2o79~6;6px$1LmqD1&S$C(^4# z1i}LsW5t&n76X5jU>Vi{S%C{*@T49jHKXKo>4CJlajDHL(KK34si9liY|(J-hT#~& zX~~zcX|$M%97CGT>N@SNqgsX|T}(|%PdT}gSyDB#VN5BzYdX3K=z zlS&fHL_>GksiV|rNV`P2fkwwAE;tPjrIfn-pVY&sqLC+-rRo9<)(> zN?lf0VwYn~mEDS?24o_!-DOl&v|tvDu?cRn-A+rDDvr5j$hyq^rEXWXQp1)Idi|zYpOpTC50xFJIfTRlr5{F^s>smxlHPSgKjx9%66*r^D?tDCx~>(HXQ0$ z!7#1RR4lfh%bZRX(#33QHJx8iEu@Pl)2A}o*hW5+JykrrmdD1uI99OCzm0CyQ1J^! zr)4x|S->Uh@!@bfyx9nik!6~*-DZr0=JW1-5*bss%mV+ETFa?SRxPY$v+0FGW-Y7E zWD3iwu$)#K`Lx8Yr*lhdxz$v5fy*UgGI^C>TPmDM<-}ml12IwT%LzwX8GCsX~4&P3Kd&bbe!{An{ANwNPXkUE)J$rR2Kzo;lSo6hHxV!iB|LgQ>f z<(E?{E82LejlwdLPNvmLCUtTpt+1h6K{0PGeJYh(#2`U)B5Pq~V^OLsax$yyE1C47 z!qPcP&xmram85z6Hc+(3dT#ABV|7u*Q+clAT0=?Xsj-;JFRY|8tC$|SJMz#-D^;=D z+Z}VW&OP07m}d2gz`f%dou+BqEQ5Pd?Y2?k2F%cGFnp{wleF6p+TBju;wGWzZ{|q( zW~rcREc%#D>nz7uu5WfqE#~SO#S_z(S!LGN6R_N*OJ!@z&7oF5LqCyKxBc)0+9tG3q%%(EU>!; zh8=F{>>{4TL02P=L%fT!%Uf()I6IHYwzh;!Oo&r+e!hZVW772`i)&B(f3?ZD-byHH z$Nw8`e4XMtFKUN-rAVU5sVOAM^Z!4v&n$b>{rmsl;`#n7@M~}v{4Cr6Pq5$r5S)iK zcnka#{3m<=-+;&91F!_ovA6#rcmTHG9J~=e$3Ff&a3>svpMl5OyMG_t2Xk;UTo2E& zfB%>82k^VF1#g8D@RRWOI4qulZ^Ap_SD*yTFbl7S|6*VNS=rl%&%g)a9q@M8f(5t( zu7PLR=YJ9&hj&2}if|9S9$sL-|6kxA;Sb@Lp#o=M3S#g)d;i~sFT7`7TzJ0bi3!sS9ubSny42aU&+*4k$(9z%*F9CF?`YDW zcVxs)xg&(SW1wQS*ag#$b6v!~(>~21+pT+PElKCM zR+wSg0o`2;iN?urk0INz&HQ{zlIs+bR~>Qsgq#yQ46yUF8O$Zwr38 zy;^D2!%LG)`zx+@7rL6_B-8$iW1F|g{v?IP^|o$YO}ov!ms*l}*HUG66W6^o35KVj zxno`<1e?GQot~Bk_nOy;z9b0t8aHO$el!gzkNi0X)I2hP|?-;TLH7QE@doai7TKI}3 zIHk9=m`fMu)LrbJW(pjxln}Pt2SV0|Lh?HyLrRK#tRY>&lbA~rG*HH1$ofzkw$OXI z&Yur0X27=Yf7UhYp1IVmK9ox=sN?rwLYb`-HU4+7At@*}*xyFAYl)Llb+@mDim~gQ ztV1hKr_zCyTLn6+*=n#)dQ?sNJHhTTJH5Ny3-TsYIYSs6rJ|sGI6TU^G!aj?l4F_f zm+>OSx|ZoSf~Wr6B6Z^*p{(GcpuR}EBhjJOXc|qcvn}QdjqbGw?Gjcxoo+8@k;A)< z+}Z3gE#>K^?{plqY;aPkH_hn0N$1jVSCN=`<(^;eoxHtRr)>{;4Wg0cRbS@~RbOI8t1q!vt-e0^r1U{m_w=}1NqPQ%1J8@s@k}Yt|Ni^?&-1MR zUHA+5EPMh!0>2Hv2{v>)}iI3BCY-23KGk?t$CjRyYbjz;Ez9cmlo*e-019yWxH~1~1@4_&)px{5yOe zZj8S#YEd( z^D2h88tt_6HI+QBM{oa{iVSH5+D@w);!%tT7MkwbEzI*6m*wV|=)py&oAfGsjn-v1 zg~R9Sy{$?^Yo^zAW2!cCjVjNZu19v#TQ=OG;`&{UI44NsRD`FWP(N;bpc3BYo|drt zvaBr9WSP60ar7PMoGJG87FT+{}xS<(isSxsdkcEBCCzCvO3?=8$d0byzA#Cmx?K8d?X zACqQhsXiuAum89Ub~oi!&a<+p@9(F3?pNO9VBfml(=@ax_O!hB1W4DQT|~0$&%DYi zNyZmbCB0tncVL9i+vBRFMaYsrSS1PGSCu4Vf0e>|-q6Z_U;V*-XxOc+p0|DET}|FP z4JzO}AsK6XTsihi8M|!hZG;X^mF~*Qb44cmHbcixID2|iHN0I%-FU``bZ<89E36`P z-@3Vi^!u!ya=Xsw!)hfK2WIP?hwx$feN*_=KNQFtwq7sO8{S>JE<4`t_II6^g^f;c zt2>_7FV)KHF8Q32oFH=}sLucgEZGW-hH0pDw&rzzJZoj4(Bi|*TAypbT!NoZt9vle9!M{nft rZh+o9nDO2Q)791U?amI8JN*uBb@B!%y8?aNhhaNI`c5`#|LcDMt4eXQ diff --git a/techlibs/xilinx/.synth_xilinx.cc.swo b/techlibs/xilinx/.synth_xilinx.cc.swo deleted file mode 100644 index 6fc27ed3be0e70fedafe56653d4ea02d7b0fba9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20480 zcmeI3dyHdM9mlVr$n1ik5{=Qo*)HsKn6|SI6fDa?cjnGaWwssK&h8GoOTBGRrw_D=5{=6opqRI;Ze8 zJ|dkRuWbII{;)_mwqn{V_E=rB9d3;|yj(N%l0CMp8+v1T%wB0YwW54Tl*|2v zg)yN8LJO?l0xhQ+zvy&j*UlYcsBevIVQ+ui{QC2UDMJf{76>g6S|GGQXo1iIp#?$< zgckU}w}8_;S@{TRagtk;lKcIJuJ1Rx&qv*F?_}AYl>00l)N%jso&W!RhN3(Jo&>jm z&jA(u>n)0MKe!K6z&YTl(-q|=Fb@85nxfnb?gn>(JHe-b0dgP--Ve5d&0rI_XEV}+ zo52mB4i19LK^n|}tzZjyW|N{k4Za5+07Z}kqu^}tgCRxH!3AI#41vc^Rg{Op?H~GC1vi5VxEzdu2-pN(M0-%1{BmOsl%XNRT#QBzH6kMy z!v^AkxgYV01&dp)1}mGIW%Hg?GC1iA_dR%`s)pt`yb&1Jw9Il(gqtBL1Vqh-vBLB! zi@U)izVyBauf&?pEzK&|R#?1T8isjPZ!Dtm>UFJAv6*IZ z#+P}y}~G2#T~uw z??-_$-F9YpRY+fKuoADD(7ml{Padyh_#%7{UcZ10v$0Y)TQ+k{SO6AjRG3*6KV1tj zL${qoVD_qI)|sJ|xWT0DI)n|2W*Lq#7@P5W(}9J}cH%&BqGQtlBSqTnRN~H2&Sjt| z%VtrVbC>}wI+B2VDZWRf7^}NU$D+tLopIjPuK2g30Pi|E7;wsmi7P<%;g)cXuew{ZQ z%@9qYH(=SO!5!|OH#`Z8yn(sG;bd2{7BCAcFVwRC7q z-NqdwZf|a9TU9&3D6!k1t97Ir^=KC_8PI4q#rfySo|IIV|4Kc01sah;CsYrSYrXYo z+0vA&#;co^7KVaGvqY20rydi?B}GOKuom?`&CzLSi5c?3cpe>;+w6dNl@SfNq?ftv zZ)fxe2aBG~4PK^xB3s!`u#_WOy>3zumwm^Zw#rz<9LRNhFLbYI4$b;L%?mW^ds#5| zbS?qZtzE6A=B869&X>Akl5})V6GMzfOxGOmD~CFWn6cfrG}%G9D%gj8$-IZLF{J-c zJRV;HuiLjWbW9mqGW80paibX>VGH?UcAuKdr6*Nv`ttM^sjTpvX4{BQGVvqQsd*&E z6imrO`(wlJ#7LNGRr$`Dq;mepWd+0mCcZM)CAL-A)AMd+i}>DWBxT- z70x0@xYgjs7IYg&9_uQQ3T6rPw(&HER{=>HCT4O0MSC${+U!EpH4MgruO{*v(2MG(_qY$-M%}vatGKJKh^lZAYfcQyN3sgr zZyH$5%kJZ4-j9UljC=XTTlOp-XAAVYJRiD9m zmd^j){ry8Y>wgzK2(AHjV1N;D9ykTOh_nB1zzg6ma64EA4zR&ENP;N%Eqnvt0C#{} z!PmeMun6YCS>Rdt0-gkqfuDmff}6qBKm}XCEARn42Yv;92CfEIfiuBounD{XKLGg$ zz5~7uj)N7j75oDJfP2AJ;7YIn&H?WRFTgMGVGswWgCTG#coKer$G~miMsNrm0Q*4% zoDEI}_rXW-O|T3cumH{iXM!`pN#Ir3`48atfNV}ah42$vAhbYef!ECfy*oKIGl_Yy zdk>2pDYmWT9V|9Y?4mCwe<_6w4bg5nnJi<$jLIVl?HOrfS&c@-8MP=*l;_#lMAMn9 zC{A+aA`(SMMugK*>~^bdnJf8P}_vI3~uM zOE_d7NZUcf@wILDAiwP$}sIEh}_c zQ(=Q^t|J*eBNB%raB4EA7I&~Ku>VUJ;J>9192mMn=6XW%t04nw4p$@D#+92>yUX!E z&vnJ)5a8++p{^X%1oXcS>sph==}+4sEZw>YN-S;2n8;ZaGS)I^aPdaVDT>0o)T&lx z@Bo9AJ6b5HzHsBh`Q37Cwlldiwk!6&Mp0v!kcyL5oPg2oQjv+wj0>1wim zwbkH}tNEJiIO90`Ga8q#$&MY8S$vWe)dM(cO{5FO37oYS+`5u~0iH^DE@%b{?E2C? zEyEaK9*n=8fDcY$Ta;)(nmVtW)(Tl;K%#bYq0!n}o!~5n*#f$*&bsSvM*07Y$H>!d z`&uo~bZ&jfe@)kC2ApQ?xkHFZILltIqn6kredyF0C%oj5yw_4CdAZdwmj(BRK~)kW zdaFdi8>$jz?5tAIL?zsFop+P6=bT`FkoT8smE~SW4d|P6h3QwoyTIDE&F6+2uy<*f zvf4cZD&F2(bOZt z1AoK${Bc0%_FKSB;3}{SYy&UjjQ#}pA$S;E0~#O=wu5(qzvH}4=lGw1`@vVh$HB*d z15)4;a1wY9XZA#68~7}^9vlZYFu~>E17HL^kM{c5j00-tQLvE@Rup$y^X7nli_C!TCpTI0?wmT{ zhWoJ;Brek3A-v{N+pAW5vTGq-ozZ*ccdV`_JfDj@WOqgq=dG4qqXU;bebw-m0=L>H zt%xda^T~~$U&s_@iU;7u%^YA&9Ln75BxDr6|MnGwcWg?yhZkvCDym$s6uD)YRy5+f z^%0lU?u`#FE*p&2-`=aKE#6IzXnT1WjE_^=qP)d|r-j97#3wO7uzkWlOVb1oc(Lxc29WawreH2XK-o4 zAF-k0+CGL8DNZ;QHdLIuZ$M!Yaj8wmJz>1{)DoH3v?+}|y11Yw!AM6zJ1%w`!QTX4 z=;$alxZB(^lbET*WY!+|-hHW@;~J(riv7WINczLtL(Ct%I$ql09UZabu2c>NYWmLj zb|>kMXg6nfM5p1kmSd9jBS>`2y|s2<*NTc#q?c-UM~UO2m0~Pcm`%?nlaumwsq^LJ z>%Z*wJa~Ox_UrJ~iMJ-=4ZM!xf2n~k^r?p3FXd5~|IHe2CBUi@jZilF$P&mB^8J!N zB~XIy5-4mPCHNd>fjW?@EHI*bJKd8=$R6-&oU9{b!o$*&+l!^|*U2pwSVoUSjCn3D z&-Dfce9kyH#kxY^7HfwbIuuw;my^Ri9m|c7I7;^9La20kt;2-D(%0wp^7Xj>ZPC}y z#SYT@i~cuMU=H!=(yO0q$8*DVI+i!xI?0>e~s7ZdXovb$Zf}$7UTi>as$wyQW7l*=~?iqwS~Z$w@IuCf`YJzfF6z xhHLX-cc(e*y~DSN_j?-an7D$~r^U?mHuWg6mii(u`DA)>QcQpKDK=33{{Uz)2x Date: Fri, 5 Apr 2019 17:35:49 -0700 Subject: [PATCH 48/64] Call shregmap twice -- once for variable, another for fixed --- passes/techmap/shregmap.cc | 46 ++++++++++++--------------------- techlibs/xilinx/cells_map.v | 3 +++ techlibs/xilinx/synth_xilinx.cc | 19 ++++++++------ 3 files changed, 31 insertions(+), 37 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 408e3f8c7..a805ac5a6 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -138,11 +138,8 @@ struct ShregmapTechXilinx7 : ShregmapTech virtual bool analyze(vector &taps, const vector &qbits) override { - log("analyze() with %zu taps", taps.size()); - for (auto t : taps) log(" %d", t); - log("\n"); if (GetSize(taps) == 1) - return taps[0] >= opts.minlen-1; + return taps[0] >= opts.minlen-1 && sigbit_to_shiftx_offset.count(qbits[0]); if (taps.back() < opts.minlen-1) return false; @@ -150,38 +147,31 @@ struct ShregmapTechXilinx7 : ShregmapTech 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 - auto it = sigbit_to_shiftx_offset.find(qbits[i]); if (i == 0) { - if (it == sigbit_to_shiftx_offset.end()) { + int offset; + std::tie(shiftx,offset,group) = it->second; + if (offset != i) return false; - } - else { - int offset; - std::tie(shiftx,offset,group) = it->second; - if (offset != i) - return false; - } } else { - if (it == sigbit_to_shiftx_offset.end()) { + 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; - } - 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); @@ -206,9 +196,7 @@ struct ShregmapTechXilinx7 : ShregmapTech auto bit = tap.second; auto it = sigbit_to_shiftx_offset.find(bit); - // If fixed-length, no fixup necessary - if (it == sigbit_to_shiftx_offset.end()) - return true; + log_assert(it != sigbit_to_shiftx_offset.end()); auto newcell = cell->module->addCell(NEW_ID, "$__XILINX_SHREG_"); newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH")); diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index c80e51bd0..704ab21b1 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -141,3 +141,6 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o end endgenerate endmodule + +`ifndef SRL_ONLY +`endif diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 2676f5915..57bde998f 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -113,22 +113,23 @@ struct SynthXilinxPass : public Pass log(" dffsr2dff\n"); log(" dff2dffe\n"); log(" opt -full\n"); - log(" simplemap t:$dff t:$dffe (without -nosrl and without -retime only)\n"); - log(" shregmap -tech xilinx -minlen 3 (without -nosrl and without -retime only)\n"); + log(" simplemap t:$dff t:$dffe (without '-nosrl' only)\n"); + log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n"); log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v\n"); log(" opt -fast\n"); log("\n"); log(" map_cells:\n"); - log(" techmap -map +/xilinx/cells_map.v\n"); - log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT \\\n"); - log(" -ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT\n"); + log(" techmap -map +/techmap.v -map +/xilinx/cells_map.v\n"); log(" clean\n"); log("\n"); log(" map_luts:\n"); log(" techmap -map +/techmap.v -map +/xilinx/ff_map.v t:$_DFF_?N?\n"); log(" abc -luts 2:2,3,6:5,10,20 [-dff]\n"); log(" clean\n"); - log(" techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v"); + log(" shregmap -minlen 3 -init -params -enpol any_or_none (without '-nosrl' only)\n"); + log(" techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v"); + log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT \\\n"); + log(" -ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT\n"); log("\n"); log(" check:\n"); log(" hierarchy -check\n"); @@ -266,7 +267,7 @@ struct SynthXilinxPass : public Pass Pass::call(design, "dff2dffe"); Pass::call(design, "opt -full"); - if (!nosrl && !retime) { + if (!nosrl) { Pass::call(design, "simplemap t:$dff t:$dffe"); Pass::call(design, "shregmap -tech xilinx -minlen 3"); } @@ -292,7 +293,9 @@ struct SynthXilinxPass : public Pass Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/ff_map.v t:$_DFF_?N?"); Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); Pass::call(design, "clean"); - Pass::call(design, "techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v"); + if (!nosrl) + Pass::call(design, "shregmap -minlen 3 -init -params -enpol any_or_none"); + Pass::call(design, "techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v"); Pass::call(design, "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 d3930ca79eb11952d8e64588e46b0788845997c4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Apr 2019 12:01:06 -0700 Subject: [PATCH 49/64] Revert "Remove handling for $pmux, since #895" This reverts commit aa693d5723ef1438d42cd35a26673703b1eff79f. --- passes/techmap/shregmap.cc | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index a805ac5a6..39ca60b80 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -119,6 +119,22 @@ struct ShregmapTechXilinx7 : ShregmapTech for (auto bit : sigmap(cell->getPort("\\B"))) sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 1, j++); } + else if (cell->type == "$pmux") { + int width = cell->getParam("\\WIDTH").as_int(); + int j = 0; + for (auto bit : cell->getPort("\\A")) + sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 0, j++); + j = cell->getParam("\\S_WIDTH").as_int(); + int k = 0; + for (auto bit : sigmap(cell->getPort("\\B"))) { + sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j, k++); + if (k == width) { + k = 0; + --j; + } + } + log_assert(j == 0); + } } } @@ -130,6 +146,8 @@ struct ShregmapTechXilinx7 : ShregmapTech if (cell) { if (cell->type == "$shiftx" && port == "\\A") return; + if (cell->type == "$pmux" && (port == "\\A" || port == "\\B")) + return; if (cell->type == "$mux" && (port == "\\A" || port == "\\B")) return; } @@ -181,6 +199,10 @@ struct ShregmapTechXilinx7 : ShregmapTech if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) return false; } + else if (shiftx->type == "$pmux") { + if (GetSize(taps) != shiftx->getParam("\\S_WIDTH").as_int() + 1) + return false; + } else if (shiftx->type == "$mux") { if (GetSize(taps) != 2) return false; @@ -216,6 +238,24 @@ struct ShregmapTechXilinx7 : ShregmapTech q_wire = shiftx->getPort("\\Y"); shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); } + else if (shiftx->type == "$pmux") { + // Create a new encoder, out of a $pmux, that takes + // the existing pmux's 'S' input and transforms it + // back into a binary value + int clog2taps = ceil(log2(taps.size())); + RTLIL::SigSpec b_port; + for (int i = shiftx->getParam("\\S_WIDTH").as_int(); i > 0; i--) + b_port.append(RTLIL::Const(i, clog2taps)); + l_wire = cell->module->addWire(NEW_ID, clog2taps); + RTLIL::SigSpec s_wire = cell->module->addWire(NEW_ID, shiftx->getParam("\\S_WIDTH").as_int()); + cell->module->connect(s_wire.extract(0, shiftx->getParam("\\S_WIDTH").as_int()), shiftx->getPort("\\S")); + cell->module->addPmux(NEW_ID, RTLIL::Const(0, clog2taps), b_port, s_wire, l_wire); + int group = std::get<2>(it->second); + RTLIL::SigSpec y_wire = shiftx->getPort("\\Y"); + q_wire = y_wire[group]; + y_wire[group] = cell->module->addWire(NEW_ID); + shiftx->setPort("\\Y", y_wire); + } else if (shiftx->type == "$mux") { l_wire = shiftx->getPort("\\S"); q_wire = shiftx->getPort("\\Y"); From 93b16219110d3175ffee1874e6fa0a3cb25383f8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Apr 2019 15:57:07 -0700 Subject: [PATCH 50/64] Cope with undoing #895 --- passes/techmap/shregmap.cc | 40 +++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 39ca60b80..bd75cd95e 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -96,6 +96,7 @@ struct ShregmapTechGreenpak4 : ShregmapTech struct ShregmapTechXilinx7 : ShregmapTech { dict> sigbit_to_shiftx_offset; + dict sigbit_to_eq_input; const ShregmapOptions &opts; ShregmapTechXilinx7(const ShregmapOptions &opts) : opts(opts) {} @@ -113,16 +114,17 @@ struct ShregmapTechXilinx7 : ShregmapTech } else if (cell->type == "$mux") { int j = 0; - for (auto bit : cell->getPort("\\A")) + for (auto bit : sigmap(cell->getPort("\\A"))) sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 0, j++); j = 0; for (auto bit : sigmap(cell->getPort("\\B"))) sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 1, j++); } else if (cell->type == "$pmux") { + if (!cell->get_bool_attribute("\\shiftx_compatible")) continue; int width = cell->getParam("\\WIDTH").as_int(); int j = 0; - for (auto bit : cell->getPort("\\A")) + for (auto bit : sigmap(cell->getPort("\\A"))) sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 0, j++); j = cell->getParam("\\S_WIDTH").as_int(); int k = 0; @@ -135,6 +137,15 @@ struct ShregmapTechXilinx7 : ShregmapTech } log_assert(j == 0); } + else if (cell->type == "$eq") { + auto b_wire = cell->getPort("\\B"); + // Keep track of $eq cells that compare against the value 1 + // in anticipation that they drive the select (S) port of a $pmux + if (b_wire.is_fully_const() && b_wire.as_int() == 1) { + auto y_wire = sigmap(cell->getPort("\\Y").as_bit()); + sigbit_to_eq_input[y_wire] = cell->getPort("\\A"); + } + } } } @@ -239,19 +250,20 @@ struct ShregmapTechXilinx7 : ShregmapTech shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); } else if (shiftx->type == "$pmux") { - // Create a new encoder, out of a $pmux, that takes - // the existing pmux's 'S' input and transforms it - // back into a binary value - int clog2taps = ceil(log2(taps.size())); - RTLIL::SigSpec b_port; - for (int i = shiftx->getParam("\\S_WIDTH").as_int(); i > 0; i--) - b_port.append(RTLIL::Const(i, clog2taps)); - l_wire = cell->module->addWire(NEW_ID, clog2taps); - RTLIL::SigSpec s_wire = cell->module->addWire(NEW_ID, shiftx->getParam("\\S_WIDTH").as_int()); - cell->module->connect(s_wire.extract(0, shiftx->getParam("\\S_WIDTH").as_int()), shiftx->getPort("\\S")); - cell->module->addPmux(NEW_ID, RTLIL::Const(0, clog2taps), b_port, s_wire, l_wire); - int group = std::get<2>(it->second); + // If the 'A' port is fully undef, then opt_expr -mux_undef + // has not been applied, so find the second-to-last bit of + // the 'S' port (corresponding to $eq cell comparing for 1) + // otherwise use the last bit of 'S' + const auto& s_wire_bits = shiftx->getPort("\\S").bits(); + SigBit s1; + if (shiftx->getPort("\\A").is_fully_undef()) + s1 = s_wire_bits[s_wire_bits.size() - 2]; + else + s1 = s_wire_bits[s_wire_bits.size() - 1]; RTLIL::SigSpec y_wire = shiftx->getPort("\\Y"); + l_wire = sigbit_to_eq_input.at(s1); + log_assert(l_wire.size() == ceil(log2(taps.size()))); + int group = std::get<2>(it->second); q_wire = y_wire[group]; y_wire[group] = cell->module->addWire(NEW_ID); shiftx->setPort("\\Y", y_wire); From 13fc70d7a44965fc87aa76682b32d4961efb093d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Apr 2019 16:05:24 -0700 Subject: [PATCH 51/64] Undo #895 by instead setting an attribute --- passes/proc/proc_mux.cc | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/passes/proc/proc_mux.cc b/passes/proc/proc_mux.cc index bac2dc2cd..6ac59bfb2 100644 --- a/passes/proc/proc_mux.cc +++ b/passes/proc/proc_mux.cc @@ -360,23 +360,9 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d } } - // Transform into a $shiftx where possible - if (shiftx && last_mux_cell && last_mux_cell->type == "$pmux") { - // Create bit-blasted $shiftx-es that shifts by the address line used in the case statement - auto pmux_b_port = last_mux_cell->getPort("\\B"); - auto pmux_y_port = last_mux_cell->getPort("\\Y"); - int width = last_mux_cell->getParam("\\WIDTH").as_int(); - for (int i = 0; i < width; ++i) { - RTLIL::SigSpec a_port; - // Because we went in reverse order above, un-reverse $pmux's B port here - for (int j = pmux_b_port.size()/width-1; j >= 0; --j) - a_port.append(pmux_b_port.extract(j*width+i, 1)); - // Create a $shiftx that shifts by the address line used in the case statement - mod->addShiftx(NEW_ID, a_port, sw->signal, pmux_y_port.extract(i, 1)); - } - // Disconnect $pmux by replacing its output port with a floating wire - last_mux_cell->setPort("\\Y", mod->addWire(NEW_ID, width)); - } + // Mark this pmux as being $shiftx compatible + if (shiftx && last_mux_cell && last_mux_cell->type == "$pmux") + last_mux_cell->set_bool_attribute("\\shiftx_compatible"); } return result; From f6c354c55bcba26978c8dd04c3cc4f02231aebe4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Apr 2019 16:22:07 -0700 Subject: [PATCH 52/64] Update CHANGELOG --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 95bbb3f33..36b64e111 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,7 +16,7 @@ Yosys 0.8 .. Yosys 0.8-dev - Added "gate2lut.v" techmap rule - Added "rename -src" - Added "equiv_opt" pass - - Added "shregmap -tech xilinx", used by "synth_xilinx" + - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" Yosys 0.7 .. Yosys 0.8 From 6797f6b6c4660622dbde27ced83fdd37a874f00d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Apr 2019 16:24:20 -0700 Subject: [PATCH 53/64] $_XILINX_SHREG_ to preserve src attribute --- passes/techmap/shregmap.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index bd75cd95e..ec43b5654 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -232,6 +232,7 @@ struct ShregmapTechXilinx7 : ShregmapTech log_assert(it != sigbit_to_shiftx_offset.end()); auto newcell = cell->module->addCell(NEW_ID, "$__XILINX_SHREG_"); + newcell->set_src_attribute(cell->get_src_attribute()); newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH")); newcell->setParam("\\INIT", cell->getParam("\\INIT")); newcell->setParam("\\CLKPOL", cell->getParam("\\CLKPOL")); From 09e7eb7aed85bac33fb570d2286be5689de59b31 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 15:09:13 -0700 Subject: [PATCH 54/64] Spelling fixes --- passes/techmap/pmuxtree.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/techmap/pmuxtree.cc b/passes/techmap/pmuxtree.cc index b7a22dc3b..6a923f481 100644 --- a/passes/techmap/pmuxtree.cc +++ b/passes/techmap/pmuxtree.cc @@ -71,9 +71,9 @@ struct PmuxtreePass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" pmuxtree [options] [selection]\n"); + log(" pmuxtree [selection]\n"); log("\n"); - log("This pass transforms $pmux cells to a trees of $mux cells.\n"); + log("This pass transforms $pmux cells to trees of $mux cells.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE From e8c26f2839611f5b52c29f711670888b02066064 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 15:52:04 -0700 Subject: [PATCH 55/64] WIP --- passes/techmap/Makefile.inc | 1 + passes/techmap/pmux2shiftx.cc | 88 +++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 passes/techmap/pmux2shiftx.cc diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index cf9e198ad..81df499da 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -37,6 +37,7 @@ OBJS += passes/techmap/attrmap.o OBJS += passes/techmap/zinit.o OBJS += passes/techmap/dff2dffs.o OBJS += passes/techmap/flowmap.o +OBJS += passes/techmap/pmux2shiftx.o endif GENFILES += passes/techmap/techmap.inc diff --git a/passes/techmap/pmux2shiftx.cc b/passes/techmap/pmux2shiftx.cc new file mode 100644 index 000000000..6569f995f --- /dev/null +++ b/passes/techmap/pmux2shiftx.cc @@ -0,0 +1,88 @@ +/* + * 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 + +struct Pmux2ShiftxPass : public Pass { + Pmux2ShiftxPass() : Pass("pmux2shiftx", "transform $pmux cells to $shiftx cells") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" pmux2shiftx [selection]\n"); + log("\n"); + log("This pass transforms $pmux cells to $shiftx cells.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing PMUX2SHIFTX pass.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + for (auto cell : module->selected_cells()) + { + if (cell->type != "$pmux") + continue; + + // Create a new encoder, out of a $pmux, that takes + // the existing pmux's 'S' input and transforms it + // back into a binary value + const int s_width = cell->getParam("\\S_WIDTH").as_int(); + const int width = cell->getParam("\\WIDTH").as_int(); + const int clog2width = ceil(log2(s_width)); + RTLIL::SigSpec shiftx_a; + RTLIL::SigSpec pmux_a; + RTLIL::SigSpec pmux_b; + RTLIL::SigSpec b_port = cell->getPort("\\B"); + if (!cell->getPort("\\A").is_fully_undef()) { + pmux_a = RTLIL::Const(RTLIL::S0, clog2width); + shiftx_a.append(cell->getPort("\\A")); + for (int i = s_width; i > 0; i--) { + shiftx_a.append(b_port.extract((i-1)*width, width)); + pmux_b.append(RTLIL::Const(i, clog2width)); + } + + } + else { + pmux_a = RTLIL::Const(RTLIL::Sx, clog2width); + for (int i = s_width-1; i >= 0; i--) { + shiftx_a.append(b_port.extract(i*width, width)); + pmux_b.append(RTLIL::Const(i, clog2width)); + } + } + RTLIL::SigSpec pmux_y = module->addWire(NEW_ID, clog2width); + RTLIL::SigSpec shiftx_s = module->addWire(NEW_ID, 1 << clog2width); + module->addPmux(NEW_ID, pmux_a, pmux_b, cell->getPort("\\S"), pmux_y); + module->addShiftx(NEW_ID, shiftx_a, pmux_y, cell->getPort("\\Y")); + module->remove(cell); + } + } +} Pmux2ShiftxPass; + +PRIVATE_NAMESPACE_END From b1f1db2fcf0e27fbd9cb7b94ab5c9d8879ad9694 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 16:17:09 -0700 Subject: [PATCH 56/64] Fixes --- passes/techmap/pmux2shiftx.cc | 38 ++++++++++++++++------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/passes/techmap/pmux2shiftx.cc b/passes/techmap/pmux2shiftx.cc index 6569f995f..9b05f8f6d 100644 --- a/passes/techmap/pmux2shiftx.cc +++ b/passes/techmap/pmux2shiftx.cc @@ -53,32 +53,28 @@ struct Pmux2ShiftxPass : public Pass { // Create a new encoder, out of a $pmux, that takes // the existing pmux's 'S' input and transforms it // back into a binary value - const int s_width = cell->getParam("\\S_WIDTH").as_int(); + RTLIL::SigSpec shiftx_a; + RTLIL::SigSpec pmux_s; + + int s_width = cell->getParam("\\S_WIDTH").as_int(); + if (!cell->getPort("\\A").is_fully_undef()) { + ++s_width; + shiftx_a.append(cell->getPort("\\A")); + pmux_s.append(module->Not(NEW_ID, module->ReduceOr(NEW_ID, cell->getPort("\\S")))); + } const int width = cell->getParam("\\WIDTH").as_int(); const int clog2width = ceil(log2(s_width)); - RTLIL::SigSpec shiftx_a; - RTLIL::SigSpec pmux_a; - RTLIL::SigSpec pmux_b; - RTLIL::SigSpec b_port = cell->getPort("\\B"); - if (!cell->getPort("\\A").is_fully_undef()) { - pmux_a = RTLIL::Const(RTLIL::S0, clog2width); - shiftx_a.append(cell->getPort("\\A")); - for (int i = s_width; i > 0; i--) { - shiftx_a.append(b_port.extract((i-1)*width, width)); - pmux_b.append(RTLIL::Const(i, clog2width)); - } - } - else { - pmux_a = RTLIL::Const(RTLIL::Sx, clog2width); - for (int i = s_width-1; i >= 0; i--) { - shiftx_a.append(b_port.extract(i*width, width)); - pmux_b.append(RTLIL::Const(i, clog2width)); - } - } + RTLIL::SigSpec pmux_b; + pmux_b.append(RTLIL::Const(0, clog2width)); + for (int i = s_width-1; i > 0; i--) + pmux_b.append(RTLIL::Const(i, clog2width)); + shiftx_a.append(cell->getPort("\\B")); + pmux_s.append(cell->getPort("\\S")); + RTLIL::SigSpec pmux_y = module->addWire(NEW_ID, clog2width); RTLIL::SigSpec shiftx_s = module->addWire(NEW_ID, 1 << clog2width); - module->addPmux(NEW_ID, pmux_a, pmux_b, cell->getPort("\\S"), pmux_y); + module->addPmux(NEW_ID, RTLIL::Const(RTLIL::Sx, clog2width), pmux_b, pmux_s, pmux_y); module->addShiftx(NEW_ID, shiftx_a, pmux_y, cell->getPort("\\Y")); module->remove(cell); } From b15b410b41cca3a79bfcfc9c91f665815f31ab5b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 16:18:01 -0700 Subject: [PATCH 57/64] Remove unused --- passes/techmap/pmux2shiftx.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/passes/techmap/pmux2shiftx.cc b/passes/techmap/pmux2shiftx.cc index 9b05f8f6d..08cb06d5f 100644 --- a/passes/techmap/pmux2shiftx.cc +++ b/passes/techmap/pmux2shiftx.cc @@ -73,7 +73,6 @@ struct Pmux2ShiftxPass : public Pass { pmux_s.append(cell->getPort("\\S")); RTLIL::SigSpec pmux_y = module->addWire(NEW_ID, clog2width); - RTLIL::SigSpec shiftx_s = module->addWire(NEW_ID, 1 << clog2width); module->addPmux(NEW_ID, RTLIL::Const(RTLIL::Sx, clog2width), pmux_b, pmux_s, pmux_y); module->addShiftx(NEW_ID, shiftx_a, pmux_y, cell->getPort("\\Y")); module->remove(cell); From f587950bde58b326e1f7319c84d5652a0dc43216 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 16:20:43 -0700 Subject: [PATCH 58/64] More unused --- passes/techmap/pmux2shiftx.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/passes/techmap/pmux2shiftx.cc b/passes/techmap/pmux2shiftx.cc index 08cb06d5f..f8cdf5783 100644 --- a/passes/techmap/pmux2shiftx.cc +++ b/passes/techmap/pmux2shiftx.cc @@ -62,7 +62,6 @@ struct Pmux2ShiftxPass : public Pass { shiftx_a.append(cell->getPort("\\A")); pmux_s.append(module->Not(NEW_ID, module->ReduceOr(NEW_ID, cell->getPort("\\S")))); } - const int width = cell->getParam("\\WIDTH").as_int(); const int clog2width = ceil(log2(s_width)); RTLIL::SigSpec pmux_b; From 3c1f1a6605a4463117ba358fc9528c4999628b81 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 16:25:59 -0700 Subject: [PATCH 59/64] Fix ordering of when to insert zero index --- passes/techmap/pmux2shiftx.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/passes/techmap/pmux2shiftx.cc b/passes/techmap/pmux2shiftx.cc index f8cdf5783..6ffc27a4c 100644 --- a/passes/techmap/pmux2shiftx.cc +++ b/passes/techmap/pmux2shiftx.cc @@ -65,8 +65,7 @@ struct Pmux2ShiftxPass : public Pass { const int clog2width = ceil(log2(s_width)); RTLIL::SigSpec pmux_b; - pmux_b.append(RTLIL::Const(0, clog2width)); - for (int i = s_width-1; i > 0; i--) + for (int i = s_width-1; i >= 0; i--) pmux_b.append(RTLIL::Const(i, clog2width)); shiftx_a.append(cell->getPort("\\B")); pmux_s.append(cell->getPort("\\S")); From d99422411f568d6d8d7de7d11346718e70012df4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 21 Apr 2019 14:16:34 -0700 Subject: [PATCH 60/64] Use new pmux2shiftx from #944, remove my old attempt --- passes/techmap/Makefile.inc | 1 - passes/techmap/pmux2shiftx.cc | 81 --------------------------------- passes/techmap/shregmap.cc | 52 --------------------- techlibs/xilinx/synth_xilinx.cc | 11 +++-- 4 files changed, 8 insertions(+), 137 deletions(-) delete mode 100644 passes/techmap/pmux2shiftx.cc diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index 81df499da..cf9e198ad 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -37,7 +37,6 @@ OBJS += passes/techmap/attrmap.o OBJS += passes/techmap/zinit.o OBJS += passes/techmap/dff2dffs.o OBJS += passes/techmap/flowmap.o -OBJS += passes/techmap/pmux2shiftx.o endif GENFILES += passes/techmap/techmap.inc diff --git a/passes/techmap/pmux2shiftx.cc b/passes/techmap/pmux2shiftx.cc deleted file mode 100644 index 6ffc27a4c..000000000 --- a/passes/techmap/pmux2shiftx.cc +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 - -struct Pmux2ShiftxPass : public Pass { - Pmux2ShiftxPass() : Pass("pmux2shiftx", "transform $pmux cells to $shiftx cells") { } - void help() YS_OVERRIDE - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" pmux2shiftx [selection]\n"); - log("\n"); - log("This pass transforms $pmux cells to $shiftx cells.\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE - { - log_header(design, "Executing PMUX2SHIFTX pass.\n"); - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) { - break; - } - extra_args(args, argidx, design); - - for (auto module : design->selected_modules()) - for (auto cell : module->selected_cells()) - { - if (cell->type != "$pmux") - continue; - - // Create a new encoder, out of a $pmux, that takes - // the existing pmux's 'S' input and transforms it - // back into a binary value - RTLIL::SigSpec shiftx_a; - RTLIL::SigSpec pmux_s; - - int s_width = cell->getParam("\\S_WIDTH").as_int(); - if (!cell->getPort("\\A").is_fully_undef()) { - ++s_width; - shiftx_a.append(cell->getPort("\\A")); - pmux_s.append(module->Not(NEW_ID, module->ReduceOr(NEW_ID, cell->getPort("\\S")))); - } - const int clog2width = ceil(log2(s_width)); - - RTLIL::SigSpec pmux_b; - for (int i = s_width-1; i >= 0; i--) - pmux_b.append(RTLIL::Const(i, clog2width)); - shiftx_a.append(cell->getPort("\\B")); - pmux_s.append(cell->getPort("\\S")); - - RTLIL::SigSpec pmux_y = module->addWire(NEW_ID, clog2width); - module->addPmux(NEW_ID, RTLIL::Const(RTLIL::Sx, clog2width), pmux_b, pmux_s, pmux_y); - module->addShiftx(NEW_ID, shiftx_a, pmux_y, cell->getPort("\\Y")); - module->remove(cell); - } - } -} Pmux2ShiftxPass; - -PRIVATE_NAMESPACE_END diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index ec43b5654..a541b33be 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -96,7 +96,6 @@ struct ShregmapTechGreenpak4 : ShregmapTech struct ShregmapTechXilinx7 : ShregmapTech { dict> sigbit_to_shiftx_offset; - dict sigbit_to_eq_input; const ShregmapOptions &opts; ShregmapTechXilinx7(const ShregmapOptions &opts) : opts(opts) {} @@ -120,32 +119,6 @@ struct ShregmapTechXilinx7 : ShregmapTech for (auto bit : sigmap(cell->getPort("\\B"))) sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 1, j++); } - else if (cell->type == "$pmux") { - if (!cell->get_bool_attribute("\\shiftx_compatible")) continue; - int width = cell->getParam("\\WIDTH").as_int(); - int j = 0; - for (auto bit : sigmap(cell->getPort("\\A"))) - sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 0, j++); - j = cell->getParam("\\S_WIDTH").as_int(); - int k = 0; - for (auto bit : sigmap(cell->getPort("\\B"))) { - sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j, k++); - if (k == width) { - k = 0; - --j; - } - } - log_assert(j == 0); - } - else if (cell->type == "$eq") { - auto b_wire = cell->getPort("\\B"); - // Keep track of $eq cells that compare against the value 1 - // in anticipation that they drive the select (S) port of a $pmux - if (b_wire.is_fully_const() && b_wire.as_int() == 1) { - auto y_wire = sigmap(cell->getPort("\\Y").as_bit()); - sigbit_to_eq_input[y_wire] = cell->getPort("\\A"); - } - } } } @@ -157,8 +130,6 @@ struct ShregmapTechXilinx7 : ShregmapTech if (cell) { if (cell->type == "$shiftx" && port == "\\A") return; - if (cell->type == "$pmux" && (port == "\\A" || port == "\\B")) - return; if (cell->type == "$mux" && (port == "\\A" || port == "\\B")) return; } @@ -210,10 +181,6 @@ struct ShregmapTechXilinx7 : ShregmapTech if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) return false; } - else if (shiftx->type == "$pmux") { - if (GetSize(taps) != shiftx->getParam("\\S_WIDTH").as_int() + 1) - return false; - } else if (shiftx->type == "$mux") { if (GetSize(taps) != 2) return false; @@ -250,25 +217,6 @@ struct ShregmapTechXilinx7 : ShregmapTech q_wire = shiftx->getPort("\\Y"); shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); } - else if (shiftx->type == "$pmux") { - // If the 'A' port is fully undef, then opt_expr -mux_undef - // has not been applied, so find the second-to-last bit of - // the 'S' port (corresponding to $eq cell comparing for 1) - // otherwise use the last bit of 'S' - const auto& s_wire_bits = shiftx->getPort("\\S").bits(); - SigBit s1; - if (shiftx->getPort("\\A").is_fully_undef()) - s1 = s_wire_bits[s_wire_bits.size() - 2]; - else - s1 = s_wire_bits[s_wire_bits.size() - 1]; - RTLIL::SigSpec y_wire = shiftx->getPort("\\Y"); - l_wire = sigbit_to_eq_input.at(s1); - log_assert(l_wire.size() == ceil(log2(taps.size()))); - int group = std::get<2>(it->second); - q_wire = y_wire[group]; - y_wire[group] = cell->module->addWire(NEW_ID); - shiftx->setPort("\\Y", y_wire); - } else if (shiftx->type == "$mux") { l_wire = shiftx->getPort("\\S"); q_wire = shiftx->getPort("\\Y"); diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 57bde998f..4f02a47ea 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -112,9 +112,11 @@ struct SynthXilinxPass : public Pass log(" memory_map\n"); log(" dffsr2dff\n"); log(" dff2dffe\n"); - log(" opt -full\n"); log(" simplemap t:$dff t:$dffe (without '-nosrl' only)\n"); + log(" pmux2shiftx (without '-nosrl' only)\n"); + log(" opt_expr -mux_undef (without '-nosrl' only)\n"); log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n"); + log(" opt -full\n"); log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v\n"); log(" opt -fast\n"); log("\n"); @@ -261,17 +263,20 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "fine")) { - Pass::call(design, "opt -fast -full"); + Pass::call(design, "opt -fast"); Pass::call(design, "memory_map"); Pass::call(design, "dffsr2dff"); Pass::call(design, "dff2dffe"); - Pass::call(design, "opt -full"); if (!nosrl) { Pass::call(design, "simplemap t:$dff t:$dffe"); + Pass::call(design, "pmux2shiftx"); + Pass::call(design, "opt_expr -mux_undef"); Pass::call(design, "shregmap -tech xilinx -minlen 3"); } + Pass::call(design, "opt -full"); + if (vpr) { Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); } else { From ae95aba60a573bf34034d6a70931bd55490d3f14 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 21 Apr 2019 14:16:59 -0700 Subject: [PATCH 61/64] Add comments --- techlibs/xilinx/synth_xilinx.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 4f02a47ea..f59c0c622 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -269,8 +269,15 @@ struct SynthXilinxPass : public Pass Pass::call(design, "dff2dffe"); if (!nosrl) { + // shregmap operates on bit-level flops, not word-level, + // so break those down here Pass::call(design, "simplemap t:$dff t:$dffe"); + // shregmap -tech xilinx can cope with $shiftx and $mux + // cells for identifiying variable-length shift registers, + // so attempt to convert $pmux-es to the former Pass::call(design, "pmux2shiftx"); + // pmux2shiftx can leave behind a $pmux with a single entry + // -- need this to clean that up Pass::call(design, "opt_expr -mux_undef"); Pass::call(design, "shregmap -tech xilinx -minlen 3"); } From d342b5b135a85da0df5df0fa2acc25dec5605760 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 21 Apr 2019 15:33:03 -0700 Subject: [PATCH 62/64] Tidy up, fix for -nosrl --- techlibs/xilinx/ff_map.v | 13 +++++++++---- techlibs/xilinx/synth_xilinx.cc | 15 +++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/techlibs/xilinx/ff_map.v b/techlibs/xilinx/ff_map.v index 3d5f78770..c61fd7070 100644 --- a/techlibs/xilinx/ff_map.v +++ b/techlibs/xilinx/ff_map.v @@ -22,21 +22,26 @@ `ifndef _NO_FFS +`ifndef _NO_POS_SR module \$_DFF_N_ (input D, C, output Q); FDRE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule module \$_DFF_P_ (input D, C, output Q); FDRE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule module \$_DFFE_NP_ (input D, C, E, output Q); FDRE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule module \$_DFFE_PP_ (input D, C, E, output Q); FDRE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule -module \$_DFF_NN0_ (input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule module \$_DFF_NP0_ (input D, C, R, output Q); FDCE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endmodule -module \$_DFF_PN0_ (input D, C, R, output Q); \$_DFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule module \$_DFF_PP0_ (input D, C, R, output Q); FDCE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endmodule -module \$_DFF_NN1_ (input D, C, R, output Q); \$_DFF_NP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule module \$_DFF_NP1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule -module \$_DFF_PN1_ (input D, C, R, output Q); \$_DFF_PP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule module \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule +`endif + +module \$_DFF_NN0_ (input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule +module \$_DFF_PN0_ (input D, C, R, output Q); \$_DFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule + +module \$_DFF_NN1_ (input D, C, R, output Q); \$_DFF_NP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule +module \$_DFF_PN1_ (input D, C, R, output Q); \$_DFF_PP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule +`endif `endif diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index a9e50329c..e84a6714b 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -116,8 +116,7 @@ struct SynthXilinxPass : public Pass log(" pmux2shiftx (without '-nosrl' only)\n"); log(" opt_expr -mux_undef (without '-nosrl' only)\n"); log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n"); - log(" opt -full\n"); - log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v\n"); + log(" techmap -map +/xilinx/arith_map.v\n"); log(" opt -fast\n"); log("\n"); log(" map_cells:\n"); @@ -125,7 +124,8 @@ struct SynthXilinxPass : public Pass log(" clean\n"); log("\n"); log(" map_luts:\n"); - log(" techmap -map +/techmap.v -map +/xilinx/ff_map.v t:$_DFF_?N?\n"); + log(" opt -full\n"); + log(" techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v\n"); log(" abc -luts 2:2,3,6:5,10,20 [-dff]\n"); log(" clean\n"); log(" shregmap -minlen 3 -init -params -enpol any_or_none (without '-nosrl' only)\n"); @@ -282,12 +282,10 @@ struct SynthXilinxPass : public Pass Pass::call(design, "shregmap -tech xilinx -minlen 3"); } - Pass::call(design, "opt -full"); - if (vpr) { - Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); + Pass::call(design, "techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); } else { - Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v"); + Pass::call(design, "techmap -map +/xilinx/arith_map.v"); } Pass::call(design, "hierarchy -check"); @@ -302,7 +300,8 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "map_luts")) { - Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/ff_map.v t:$_DFF_?N?"); + Pass::call(design, "opt -full"); + Pass::call(design, "techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v"); Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); Pass::call(design, "clean"); if (!nosrl) From 0e76718720895a4985a7fad24052a61550acdeda Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 10:45:39 -0700 Subject: [PATCH 63/64] Move 'shregmap -tech xilinx' into map_cells --- techlibs/xilinx/synth_xilinx.cc | 39 ++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 1449e792f..d6e7c2623 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -112,14 +112,14 @@ struct SynthXilinxPass : public Pass log(" memory_map\n"); log(" dffsr2dff\n"); log(" dff2dffe\n"); - log(" simplemap t:$dff t:$dffe (without '-nosrl' only)\n"); - log(" pmux2shiftx (without '-nosrl' only)\n"); - log(" opt_expr -mux_undef (without '-nosrl' only)\n"); - log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n"); log(" techmap -map +/xilinx/arith_map.v\n"); log(" opt -fast\n"); log("\n"); log(" map_cells:\n"); + log(" simplemap t:$dff t:$dffe (without '-nosrl' only)\n"); + log(" pmux2shiftx (without '-nosrl' only)\n"); + log(" opt_expr -mux_undef (without '-nosrl' only)\n"); + log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n"); log(" techmap -map +/xilinx/cells_map.v\n"); log(" clean\n"); log("\n"); @@ -269,20 +269,6 @@ struct SynthXilinxPass : public Pass Pass::call(design, "dffsr2dff"); Pass::call(design, "dff2dffe"); - if (!nosrl) { - // shregmap operates on bit-level flops, not word-level, - // so break those down here - Pass::call(design, "simplemap t:$dff t:$dffe"); - // shregmap -tech xilinx can cope with $shiftx and $mux - // cells for identifiying variable-length shift registers, - // so attempt to convert $pmux-es to the former - Pass::call(design, "pmux2shiftx"); - // pmux2shiftx can leave behind a $pmux with a single entry - // -- need this to clean that up - Pass::call(design, "opt_expr -mux_undef"); - Pass::call(design, "shregmap -tech xilinx -minlen 3"); - } - if (vpr) { Pass::call(design, "techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); } else { @@ -295,6 +281,21 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "map_cells")) { + if (!nosrl) { + // shregmap operates on bit-level flops, not word-level, + // so break those down here + Pass::call(design, "simplemap t:$dff t:$dffe"); + // shregmap -tech xilinx can cope with $shiftx and $mux + // cells for identifiying variable-length shift registers, + // so attempt to convert $pmux-es to the former + Pass::call(design, "pmux2shiftx"); + // pmux2shiftx can leave behind a $pmux with a single entry + // -- need this to clean that up before shregmap + Pass::call(design, "opt_expr -mux_undef"); + // shregmap with '-tech xilinx' infers variable length shift regs + Pass::call(design, "shregmap -tech xilinx -minlen 3"); + } + Pass::call(design, "techmap -map +/xilinx/cells_map.v"); Pass::call(design, "clean"); } @@ -305,6 +306,8 @@ struct SynthXilinxPass : public Pass Pass::call(design, "techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v"); Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); Pass::call(design, "clean"); + // This shregmap call infers fixed length shift registers after abc + // has performed any necessary retiming if (!nosrl) Pass::call(design, "shregmap -minlen 3 -init -params -enpol any_or_none"); Pass::call(design, "techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v"); From ec88129a5cf510afc39ea12efa6059bed3eadfc3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 11:38:23 -0700 Subject: [PATCH 64/64] Update help message --- techlibs/xilinx/synth_xilinx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index d6e7c2623..53eee7962 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -108,7 +108,7 @@ struct SynthXilinxPass : public Pass log(" techmap -map +/xilinx/drams_map.v\n"); log("\n"); log(" fine:\n"); - log(" opt -fast -full\n"); + log(" opt -fast\n"); log(" memory_map\n"); log(" dffsr2dff\n"); log(" dff2dffe\n");