From c29f0c5048fce87258eb4a4b204b6584efe0170c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 28 Feb 2019 09:31:24 -0800 Subject: 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 -- cgit v1.2.3 From c9ab18889a63f74534c6fe9184ccb32e3661ab90 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 28 Feb 2019 09:32:29 -0800 Subject: 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"); -- cgit v1.2.3 From 68f38f2ee0e82ac7250e8c4b257e33fd62d21544 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 28 Feb 2019 10:21:05 -0800 Subject: 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"); -- cgit v1.2.3 From fe4d6898de378260c659dca08398fa434d71f7f0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 28 Feb 2019 11:17:13 -0800 Subject: 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"); -- cgit v1.2.3 From 8aab7fe7e64b1c213d924126e30994ab7b6d4625 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 28 Feb 2019 13:56:00 -0800 Subject: 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; -- cgit v1.2.3 From 73ddab6960a02aef0c5f9ccee8cee2e666778c06 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 28 Feb 2019 13:56:22 -0800 Subject: 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 -- cgit v1.2.3 From 1da090966263318c46dd1d91d2f1f4d11238c2c1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 28 Feb 2019 13:56:45 -0800 Subject: 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; -- cgit v1.2.3 From 24f129ddfb6496226801861a15e4e9518217dd76 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Mar 2019 16:17:54 -0700 Subject: 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)); -- cgit v1.2.3 From edca2f116373df7819ec68906ce74f15456168c2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 Mar 2019 17:13:52 -0700 Subject: 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"); } -- cgit v1.2.3 From 79b4a275ce85d231186105b6e73a596ff3326e1f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Mar 2019 08:09:48 -0700 Subject: 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 -- cgit v1.2.3 From 26ecbc1aee1dca1c186ab2b51835d74f67bc3e75 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Mar 2019 08:10:02 -0700 Subject: 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"); } -- cgit v1.2.3 From 8af9979aab5f1434ee7d0e56a85324d78e2fd9f9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Mar 2019 09:01:48 -0700 Subject: 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"); } -- cgit v1.2.3 From af5706c2a38c010e6c7343aeb1c5d6e26a6b7799 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Mar 2019 09:06:56 -0700 Subject: 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"); } -- cgit v1.2.3 From e7ef7fa443c0b7c7ec9e4bbb15893053aed8c3ce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Mar 2019 09:38:42 -0700 Subject: 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 -- cgit v1.2.3 From 06f8f2654abdef8684bfe4f373ac42cb8c62ee2a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 15 Mar 2019 19:13:40 -0700 Subject: Working --- passes/techmap/shregmap.cc | 583 ++++++++++++++++++++++++---------------- techlibs/xilinx/cells_map.v | 109 +++++--- techlibs/xilinx/synth_xilinx.cc | 16 +- 3 files changed, 434 insertions(+), 274 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 ShregmapWorker +struct ShregmapTechXilinx7 : ShregmapTech { - Module *module; - SigMap sigmap; - + dict sigbit_to_shiftx; const ShregmapOptions &opts; - int dff_count, shreg_count; - pool remove_cells; - pool remove_init; + ShregmapTechXilinx7(const ShregmapOptions &opts) : opts(opts) {} - dict sigbit_init; - dict sigbit_chain_next; - dict sigbit_chain_prev; - pool sigbit_with_non_chain_users; - pool chain_start_cells; + 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; + } + } - void make_sigbit_chain_next_prev() + virtual void non_chain_user(const SigBit &bit, const Cell *cell, IdString port) override { - 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); - } + auto it = sigbit_to_shiftx.find(bit); + if (it == sigbit_to_shiftx.end()) + return; + if (cell->type == "$shiftx" && port == "\\A") + return; + it->second = 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; - } - } + virtual bool analyze(vector &taps, const vector &qbits) override + { + if (GetSize(taps) == 1) + return taps[0] >= opts.minlen-1; - 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; + 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; } } - - for (auto conn : cell->connections()) - if (cell->input(conn.first)) - for (auto bit : sigmap(conn.second)) - sigbit_with_non_chain_users.insert(bit); } + + return true; } - void find_chain_start_cells() + virtual bool fixup(Cell *cell, dict &taps) override { - for (auto it : sigbit_chain_next) - { - if (opts.tech == nullptr && sigbit_with_non_chain_users.count(it.first)) - goto start_cell; + const auto &tap = *taps.begin(); + auto bit = tap.second; + auto it = sigbit_to_shiftx.find(bit); + if (it == sigbit_to_shiftx.end()) + return true; - if (sigbit_chain_prev.count(it.first) != 0) - { - Cell *c1 = sigbit_chain_prev.at(it.first); - Cell *c2 = it.second; + Cell* shiftx = it->second; - if (c1->type != c2->type) - goto start_cell; + auto module = cell->module; - if (c1->parameters != c2->parameters) - goto start_cell; + auto cell_q = cell->getPort("\\Q").as_bit(); - IdString d_port = opts.ffcells.at(c1->type).first; - IdString q_port = opts.ffcells.at(c1->type).second; + 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); - auto c1_conn = c1->connections(); - auto c2_conn = c1->connections(); - c1_conn.erase(d_port); - c1_conn.erase(q_port); + return true; + } +}; - c2_conn.erase(d_port); - c2_conn.erase(q_port); - if (c1_conn != c2_conn) - goto start_cell; +struct ShregmapWorker +{ + Module *module; + SigMap sigmap; - continue; - } + const ShregmapOptions &opts; + int dff_count, shreg_count; - start_cell: - chain_start_cells.insert(it.second); - } - } + 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; - vector create_chain(Cell *start_cell) + void make_sigbit_chain_next_prev() + { + for (auto wire : module->wires()) { - vector chain; + 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; + } + } - Cell *c = start_cell; - while (c != nullptr) - { - chain.push_back(c); + 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; - IdString q_port = opts.ffcells.at(c->type).second; - SigBit q_bit = sigmap(c->getPort(q_port).as_bit()); + SigBit d_bit = sigmap(cell->getPort(d_port).as_bit()); + SigBit q_bit = sigmap(cell->getPort(q_port).as_bit()); - if (sigbit_chain_next.count(q_bit) == 0) - break; + 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; - c = sigbit_chain_next.at(q_bit); - if (chain_start_cells.count(c) != 0) - break; + sigbit_chain_prev[q_bit] = cell; + continue; } - - return chain; + } + + 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 process_chain(vector &chain) + void find_chain_start_cells() + { + for (auto it : sigbit_chain_next) { - if (GetSize(chain) < opts.keep_before + opts.minlen + opts.keep_after) - return; + if (opts.tech == nullptr && sigbit_with_non_chain_users.count(it.first)) + goto start_cell; - int cursor = opts.keep_before; - while (cursor < GetSize(chain) - opts.keep_after) - { - int depth = GetSize(chain) - opts.keep_after - cursor; + if (sigbit_chain_prev.count(it.first) != 0) + { + Cell *c1 = sigbit_chain_prev.at(it.first); + Cell *c2 = it.second; - if (opts.maxlen > 0) - depth = std::min(opts.maxlen, depth); + if (c1->type != c2->type) + goto start_cell; - Cell *first_cell = chain[cursor]; - IdString q_port = opts.ffcells.at(first_cell->type).second; - dict taps_dict; + if (c1->parameters != c2->parameters) + goto start_cell; - if (opts.tech) - { - vector qbits; - vector taps; + IdString d_port = opts.ffcells.at(c1->type).first; + IdString q_port = opts.ffcells.at(c1->type).second; - for (int i = 0; i < depth; i++) - { - Cell *cell = chain[cursor+i]; - auto qbit = sigmap(cell->getPort(q_port)); - qbits.push_back(qbit); + auto c1_conn = c1->connections(); + auto c2_conn = c1->connections(); - 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); + c1_conn.erase(d_port); + c1_conn.erase(q_port); - if (opts.tech->analyze(taps)) - break; + c2_conn.erase(d_port); + c2_conn.erase(q_port); - taps.pop_back(); - depth--; - } + if (c1_conn != c2_conn) + goto start_cell; - depth = 0; - for (auto tap : taps) { - taps_dict[tap] = qbits.at(tap); - log_assert(depth < tap+1); - depth = tap+1; - } - } + continue; + } - if (depth < 2) { - cursor++; - continue; - } +start_cell: + chain_start_cells.insert(it.second); + } + } - Cell *last_cell = chain[cursor+depth-1]; + vector create_chain(Cell *start_cell) + { + vector chain; - 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); + Cell *c = start_cell; + while (c != nullptr) + { + chain.push_back(c); - dff_count += depth; - shreg_count += 1; + IdString q_port = opts.ffcells.at(c->type).second; + SigBit q_bit = sigmap(c->getPort(q_port).as_bit()); - 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 (sigbit_chain_next.count(q_bit) == 0) + break; - 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); - } + c = sigbit_chain_next.at(q_bit); + if (chain_start_cells.count(c) != 0) + break; + } - 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); - } + return chain; + } - if (opts.params) - { - int param_clkpol = -1; - int param_enpol = 2; + void process_chain(vector &chain) + { + if (GetSize(chain) < opts.keep_before + opts.minlen + opts.keep_after) + return; - if (first_cell->type == "$_DFF_N_") param_clkpol = 0; - if (first_cell->type == "$_DFF_P_") param_clkpol = 1; + int cursor = opts.keep_before; + while (cursor < GetSize(chain) - opts.keep_after) + { + int depth = GetSize(chain) - opts.keep_after - cursor; - 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; + if (opts.maxlen > 0) + depth = std::min(opts.maxlen, depth); - log_assert(param_clkpol >= 0); - first_cell->setParam("\\CLKPOL", param_clkpol); - if (opts.ffe) first_cell->setParam("\\ENPOL", param_enpol); - } + Cell *first_cell = chain[cursor]; + IdString q_port = opts.ffcells.at(first_cell->type).second; + dict taps_dict; - 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) + { + vector qbits; + vector taps; - if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict)) - remove_cells.insert(first_cell); + for (int i = 0; i < depth; i++) + { + Cell *cell = chain[cursor+i]; + auto qbit = sigmap(cell->getPort(q_port)); + qbits.push_back(qbit); - for (int i = 1; i < depth; i++) - remove_cells.insert(chain[cursor+i]); - cursor += depth; + if (sigbit_with_non_chain_users.count(qbit)) + taps.push_back(i); } - } - void cleanup() - { - for (auto cell : remove_cells) - module->remove(cell); - - for (auto wire : module->wires()) + while (depth > 0) { - if (wire->attributes.count("\\init") == 0) - continue; + if (taps.empty() || taps.back() < depth-1) + taps.push_back(depth-1); - SigSpec initsig = sigmap(wire); - Const &initval = wire->attributes.at("\\init"); + if (opts.tech->analyze(taps, qbits)) + break; + + taps.pop_back(); + depth--; + } - for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) - if (remove_init.count(initsig[i])) - initval[i] = State::Sx; + 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 (SigSpec(initval).is_fully_undef()) - wire->attributes.erase("\\init"); + 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); } - remove_cells.clear(); - sigbit_chain_next.clear(); - sigbit_chain_prev.clear(); - chain_start_cells.clear(); + 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); - ShregmapWorker(Module *module, const ShregmapOptions &opts) : - module(module), sigmap(module), opts(opts), dff_count(0), shreg_count(0) + for (auto wire : module->wires()) { - make_sigbit_chain_next_prev(); - find_chain_start_cells(); + if (wire->attributes.count("\\init") == 0) + continue; - for (auto c : chain_start_cells) { - vector chain = create_chain(c); - process_chain(chain); - } + SigSpec initsig = sigmap(wire); + Const &initval = wire->attributes.at("\\init"); - cleanup(); + 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 { @@ -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"); } -- cgit v1.2.3 From 29a8d4745eb4ecd2947694d02f51c9333bf3ac21 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 15 Mar 2019 23:01:40 -0700 Subject: 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"); -- cgit v1.2.3 From fadeadb8c87670b1cfe8f92ac9c5ac3beadcb312 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Mar 2019 08:51:13 -0700 Subject: 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 -- cgit v1.2.3 From d6d9ef0fee3a187b884cbfd0b9a97da935666189 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Mar 2019 12:49:46 -0700 Subject: 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")); -- cgit v1.2.3 From b94db546645e624b752203a4c4d2395dc84dff0c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 18 Mar 2019 13:35:54 -0700 Subject: 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; } -- cgit v1.2.3 From ed32119d133166c78870137c6ce3db781b92c2e4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 18 Mar 2019 16:12:19 -0700 Subject: 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; } -- cgit v1.2.3 From 0ea7eba5f13b20de28181a66181ee821820027db Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 13:08:43 -0700 Subject: 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")) { -- cgit v1.2.3 From f239cb821edb86c3ec48782139e982819f073a7c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 14:54:43 -0700 Subject: 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 -- cgit v1.2.3 From 4cd8f0297381c5fb9fe3b8cbb22d4240f2aaae63 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 15:05:08 -0700 Subject: 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; } -- cgit v1.2.3 From 9156e18f9215f7e8e5a36e068b137b01810769b1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 16:12:32 -0700 Subject: 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 -- cgit v1.2.3 From ae2a625d0507c9e7476497e0064ffa003aa761f1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 16:14:08 -0700 Subject: 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"); } -- cgit v1.2.3 From 5445cd4d00349f9d04f9e78c7c2804306fac6b65 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 17:44:33 -0700 Subject: Add support for variable length Xilinx SRL > 128 --- passes/techmap/shregmap.cc | 6 ---- techlibs/xilinx/cells_map.v | 78 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 67 insertions(+), 17 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)); + \$__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 + 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 - // No way to create variable length shift registers >128 bits as Q31 - // cannot be output to the fabric... - wire _TECHMAP_FAIL_ = 1; + //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 -- cgit v1.2.3 From 505e4c2d59ed81a1779644b7aaf61aee799c8f67 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 21:58:05 -0700 Subject: Revert $__SHREG_ to orig; use $__XILINX_SHREG for variable length --- passes/techmap/shregmap.cc | 19 ++++++++---- techlibs/xilinx/cells_map.v | 73 +++++++++++++-------------------------------- 2 files changed, 34 insertions(+), 58 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,12 +17,20 @@ * */ -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; + + \$__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); 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 @@ -39,6 +47,7 @@ module \$__SHREG_ (input C, input D, input [31:0] L, input E, output Q); parameter _TECHMAP_CONSTMSK_L_ = 0; parameter _TECHMAP_CONSTVAL_L_ = 0; + wire CE; generate if (ENPOL == 0) assign CE = ~E; @@ -47,7 +56,7 @@ module \$__SHREG_ (input C, input D, input [31:0] L, input E, output Q); else assign CE = 1'b1; if (DEPTH == 1) begin - wire _TECHMAP_FAIL_ = ~&_TECHMAP_CONSTMSK_L_ || _TECHMAP_CONSTVAL_L_ != 0; + //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 @@ -62,7 +71,7 @@ module \$__SHREG_ (input C, input D, input [31:0] L, input E, output Q); 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)); + \$__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 @@ -72,7 +81,7 @@ module \$__SHREG_ (input C, input D, input [31:0] L, input E, output Q); 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)); + \$__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 @@ -81,12 +90,12 @@ module \$__SHREG_ (input C, input D, input [31:0] L, input E, output Q); MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(L[6])); end end else - if (DEPTH > 97 && DEPTH <= 128) begin + 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)); + \$__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 @@ -95,62 +104,20 @@ 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 <= 128 || (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 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)); + \$__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 - \$__SHREG_ #(.DEPTH(DEPTH+1), .INIT({INIT,1'b0}), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); + \$__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 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 -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)); -- cgit v1.2.3 From 81c207fb9bc88c4e025ee058d767d33847682d19 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Mar 2019 10:55:14 -0700 Subject: 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 -- cgit v1.2.3 From 2b911e270ba8012aa85f342838ed31b54568f257 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Mar 2019 12:28:39 -0700 Subject: Fix spacing --- passes/techmap/shregmap.cc | 478 ++++++++++++++++++++++----------------------- 1 file changed, 239 insertions(+), 239 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; - - pool remove_cells; - pool remove_init; + const ShregmapOptions &opts; + int dff_count, shreg_count; - dict sigbit_init; - dict sigbit_chain_next; - dict sigbit_chain_prev; - pool sigbit_with_non_chain_users; - pool chain_start_cells; + pool remove_cells; + pool remove_init; - void make_sigbit_chain_next_prev() - { - 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 (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; - } - } + dict sigbit_init; + dict sigbit_chain_next; + dict sigbit_chain_prev; + pool sigbit_with_non_chain_users; + pool chain_start_cells; - for (auto cell : module->cells()) + void make_sigbit_chain_next_prev() { - 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; + 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 (opts.tech) opts.tech->non_chain_user(bit, nullptr, {}); + } + } - SigBit d_bit = sigmap(cell->getPort(d_port).as_bit()); - SigBit q_bit = sigmap(cell->getPort(q_port).as_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; + } + } - if (opts.init || sigbit_init.count(q_bit) == 0) + for (auto cell : module->cells()) { - if (sigbit_chain_next.count(d_bit)) { - sigbit_with_non_chain_users.insert(d_bit); - } else - sigbit_chain_next[d_bit] = cell; + 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; + } + } - 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); + } } - } - - 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) + void find_chain_start_cells() { - if (opts.tech == nullptr && sigbit_with_non_chain_users.count(it.first)) - goto start_cell; + 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 (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->type != c2->type) + goto start_cell; - if (c1->parameters != c2->parameters) - 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; + 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(); + auto c1_conn = c1->connections(); + auto c2_conn = c1->connections(); - c1_conn.erase(d_port); - c1_conn.erase(q_port); + c1_conn.erase(d_port); + c1_conn.erase(q_port); - c2_conn.erase(d_port); - c2_conn.erase(q_port); + c2_conn.erase(d_port); + c2_conn.erase(q_port); - if (c1_conn != c2_conn) - goto start_cell; + if (c1_conn != c2_conn) + goto start_cell; - continue; - } + continue; + } -start_cell: - chain_start_cells.insert(it.second); + start_cell: + chain_start_cells.insert(it.second); + } } - } - vector create_chain(Cell *start_cell) - { - vector chain; - - Cell *c = start_cell; - while (c != nullptr) + vector create_chain(Cell *start_cell) { - chain.push_back(c); + vector chain; - IdString q_port = opts.ffcells.at(c->type).second; - SigBit q_bit = sigmap(c->getPort(q_port).as_bit()); + Cell *c = start_cell; + while (c != nullptr) + { + chain.push_back(c); - if (sigbit_chain_next.count(q_bit) == 0) - break; + IdString q_port = opts.ffcells.at(c->type).second; + SigBit q_bit = sigmap(c->getPort(q_port).as_bit()); - c = sigbit_chain_next.at(q_bit); - if (chain_start_cells.count(c) != 0) - break; - } + if (sigbit_chain_next.count(q_bit) == 0) + break; - return chain; - } + c = sigbit_chain_next.at(q_bit); + if (chain_start_cells.count(c) != 0) + break; + } - void process_chain(vector &chain) - { - if (GetSize(chain) < opts.keep_before + opts.minlen + opts.keep_after) - return; + return chain; + } - int cursor = opts.keep_before; - while (cursor < GetSize(chain) - opts.keep_after) + void process_chain(vector &chain) { - int depth = GetSize(chain) - opts.keep_after - cursor; + if (GetSize(chain) < opts.keep_before + opts.minlen + opts.keep_after) + return; - if (opts.maxlen > 0) - depth = std::min(opts.maxlen, depth); + int cursor = opts.keep_before; + while (cursor < GetSize(chain) - opts.keep_after) + { + int depth = GetSize(chain) - opts.keep_after - cursor; - Cell *first_cell = chain[cursor]; - IdString q_port = opts.ffcells.at(first_cell->type).second; - dict taps_dict; + if (opts.maxlen > 0) + depth = std::min(opts.maxlen, depth); - if (opts.tech) - { - vector qbits; - vector taps; + Cell *first_cell = chain[cursor]; + IdString q_port = opts.ffcells.at(first_cell->type).second; + dict taps_dict; - for (int i = 0; i < depth; i++) - { - Cell *cell = chain[cursor+i]; - auto qbit = sigmap(cell->getPort(q_port)); - qbits.push_back(qbit); + if (opts.tech) + { + vector qbits; + vector taps; - if (sigbit_with_non_chain_users.count(qbit)) - taps.push_back(i); - } + for (int i = 0; i < depth; i++) + { + Cell *cell = chain[cursor+i]; + auto qbit = sigmap(cell->getPort(q_port)); + qbits.push_back(qbit); - while (depth > 0) - { - if (taps.empty() || taps.back() < depth-1) - taps.push_back(depth-1); + if (sigbit_with_non_chain_users.count(qbit)) + taps.push_back(i); + } - if (opts.tech->analyze(taps, qbits)) - break; + while (depth > 0) + { + if (taps.empty() || taps.back() < depth-1) + taps.push_back(depth-1); - taps.pop_back(); - depth--; - } + if (opts.tech->analyze(taps, qbits)) + break; - 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); - } + taps.pop_back(); + depth--; + } - 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); - } + depth = 0; + for (auto tap : taps) { + taps_dict[tap] = qbits.at(tap); + log_assert(depth < tap+1); + depth = tap+1; + } + } - if (opts.params) - { - int param_clkpol = -1; - int param_enpol = 2; + if (depth < 2) { + cursor++; + continue; + } - if (first_cell->type == "$_DFF_N_") param_clkpol = 0; - if (first_cell->type == "$_DFF_P_") param_clkpol = 1; + Cell *last_cell = chain[cursor+depth-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("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); - log_assert(param_clkpol >= 0); - first_cell->setParam("\\CLKPOL", param_clkpol); - if (opts.ffe) first_cell->setParam("\\ENPOL", param_enpol); - } + dff_count += depth; + shreg_count += 1; - first_cell->type = shreg_cell_type_str; - first_cell->setPort(q_port, last_cell->getPort(q_port)); - first_cell->setParam("\\DEPTH", depth); + 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.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict)) - remove_cells.insert(first_cell); + 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); + } - for (int i = 1; i < depth; i++) - remove_cells.insert(chain[cursor+i]); - cursor += depth; - } - } + 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); + } - void cleanup() - { - for (auto cell : remove_cells) - module->remove(cell); + if (opts.params) + { + int param_clkpol = -1; + int param_enpol = 2; - for (auto wire : module->wires()) - { - if (wire->attributes.count("\\init") == 0) - continue; + 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; - SigSpec initsig = sigmap(wire); - Const &initval = wire->attributes.at("\\init"); + 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); - for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) - if (remove_init.count(initsig[i])) - initval[i] = State::Sx; + if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict)) + remove_cells.insert(first_cell); - if (SigSpec(initval).is_fully_undef()) - wire->attributes.erase("\\init"); + for (int i = 1; i < depth; i++) + remove_cells.insert(chain[cursor+i]); + cursor += depth; + } } - remove_cells.clear(); - sigbit_chain_next.clear(); - sigbit_chain_prev.clear(); - chain_start_cells.clear(); - } + void cleanup() + { + for (auto cell : remove_cells) + module->remove(cell); + + for (auto wire : module->wires()) + { + if (wire->attributes.count("\\init") == 0) + continue; - 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); + SigSpec initsig = sigmap(wire); + Const &initval = wire->attributes.at("\\init"); - make_sigbit_chain_next_prev(); - find_chain_start_cells(); + for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) + if (remove_init.count(initsig[i])) + initval[i] = State::Sx; - for (auto c : chain_start_cells) { - vector chain = create_chain(c); - process_chain(chain); + 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(); } - cleanup(); - } + 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 { -- cgit v1.2.3 From 5597270b9e2331d8836c8c24a073aadc1e19584a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Mar 2019 10:20:27 -0700 Subject: 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; -- cgit v1.2.3 From 4cc6b3e942a54e94f472df7817788dc321955a20 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Mar 2019 15:04:44 -0700 Subject: 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"); -- cgit v1.2.3 From 03d108cd1f785fd32394746221fb81380b051ed1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Mar 2019 17:46:49 -0700 Subject: 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); -- cgit v1.2.3 From 456295eb6686316dd6090ed32787bd91dc6e8d61 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Mar 2019 18:32:42 -0700 Subject: 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; } }; -- cgit v1.2.3 From 0895093c7ce91e13c7fa8e878ae41f8877b3870d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Mar 2019 19:14:04 -0700 Subject: 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; -- cgit v1.2.3 From 098bd5758fe2e4cb7efa44503a1c498b0a2ace5e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Mar 2019 23:22:19 -0700 Subject: 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); -- cgit v1.2.3 From bf83c074c82756b1cd23a9c3998b6c4d535dae29 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 23 Mar 2019 16:09:38 -0700 Subject: 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); -- cgit v1.2.3 From f9fb05cf6684d855ce2fc776a20cd5552a4ef4a8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Mar 2019 13:18:55 -0700 Subject: 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) { -- cgit v1.2.3 From f7a0434d54261834a7371727741e5cdf24ec5ca0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 3 Apr 2019 07:05:28 -0700 Subject: 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 -- cgit v1.2.3 From 88630cd02cfb7cb124c949777280b60f66ee5eb5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 3 Apr 2019 07:14:20 -0700 Subject: 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"); } -- cgit v1.2.3 From ff385a5ad0570cb56ae63d450e1dcba76ffaff7e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 3 Apr 2019 08:14:09 -0700 Subject: 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 -- cgit v1.2.3 From 0e2d929cead2a32ae176a408da257ec5b8b79f47 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 3 Apr 2019 08:28:07 -0700 Subject: -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"); -- cgit v1.2.3 From aa693d5723ef1438d42cd35a26673703b1eff79f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 3 Apr 2019 08:35:32 -0700 Subject: 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"); -- cgit v1.2.3 From 736e19f02d9980691e244e08b711c5e8c0b4fc76 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 4 Apr 2019 07:39:19 -0700 Subject: 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"); } -- cgit v1.2.3 From 77755b5a662a11a3dcc18c070e6ea859104fc872 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 4 Apr 2019 07:41:40 -0700 Subject: 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) -- cgit v1.2.3 From 2fb02247a71253460cadef492f01dac8cb8c831b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 4 Apr 2019 08:10:40 -0700 Subject: 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; -- cgit v1.2.3 From 544843da717734ab9bd9bd88f71db2475fc3abc0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 5 Apr 2019 12:55:52 -0700 Subject: 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"); -- cgit v1.2.3 From a5f33b5409d9325730204eb776e0046726d55d2c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 5 Apr 2019 16:20:43 -0700 Subject: 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 a6564691a..000000000 Binary files a/techlibs/xilinx/.synth_xilinx.cc.swn and /dev/null differ diff --git a/techlibs/xilinx/.synth_xilinx.cc.swo b/techlibs/xilinx/.synth_xilinx.cc.swo deleted file mode 100644 index 6fc27ed3b..000000000 Binary files a/techlibs/xilinx/.synth_xilinx.cc.swo and /dev/null differ diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index ee8dec9ee..2676f5915 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -284,8 +284,6 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "map_cells")) { 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"); } @@ -295,6 +293,8 @@ struct SynthXilinxPass : public Pass 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"); + 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"); } if (check_label(active, run_from, run_to, "check")) -- cgit v1.2.3 From 1d526b7f061fb7e7961fa4d0b318b27cfda469d4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 5 Apr 2019 17:35:49 -0700 Subject: 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"); } -- cgit v1.2.3 From d3930ca79eb11952d8e64588e46b0788845997c4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Apr 2019 12:01:06 -0700 Subject: 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"); -- cgit v1.2.3 From 93b16219110d3175ffee1874e6fa0a3cb25383f8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Apr 2019 15:57:07 -0700 Subject: 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); -- cgit v1.2.3 From 13fc70d7a44965fc87aa76682b32d4961efb093d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Apr 2019 16:05:24 -0700 Subject: 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; -- cgit v1.2.3 From f6c354c55bcba26978c8dd04c3cc4f02231aebe4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Apr 2019 16:22:07 -0700 Subject: 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 -- cgit v1.2.3 From 6797f6b6c4660622dbde27ced83fdd37a874f00d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Apr 2019 16:24:20 -0700 Subject: $_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")); -- cgit v1.2.3 From 09e7eb7aed85bac33fb570d2286be5689de59b31 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 15:09:13 -0700 Subject: 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 -- cgit v1.2.3 From e8c26f2839611f5b52c29f711670888b02066064 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 15:52:04 -0700 Subject: 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 -- cgit v1.2.3 From b1f1db2fcf0e27fbd9cb7b94ab5c9d8879ad9694 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 16:17:09 -0700 Subject: Fixes --- passes/techmap/pmux2shiftx.cc | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 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)); - } + 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")); - } - 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->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); } -- cgit v1.2.3 From b15b410b41cca3a79bfcfc9c91f665815f31ab5b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 16:18:01 -0700 Subject: 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); -- cgit v1.2.3 From f587950bde58b326e1f7319c84d5652a0dc43216 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 16:20:43 -0700 Subject: 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; -- cgit v1.2.3 From 3c1f1a6605a4463117ba358fc9528c4999628b81 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 16:25:59 -0700 Subject: 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")); -- cgit v1.2.3 From d99422411f568d6d8d7de7d11346718e70012df4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 21 Apr 2019 14:16:34 -0700 Subject: 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 { -- cgit v1.2.3 From ae95aba60a573bf34034d6a70931bd55490d3f14 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 21 Apr 2019 14:16:59 -0700 Subject: 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"); } -- cgit v1.2.3 From d342b5b135a85da0df5df0fa2acc25dec5605760 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 21 Apr 2019 15:33:03 -0700 Subject: 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) -- cgit v1.2.3 From 0e76718720895a4985a7fad24052a61550acdeda Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 10:45:39 -0700 Subject: Move 'shregmap -tech xilinx' into map_cells --- techlibs/xilinx/synth_xilinx.cc | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 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,6 +269,18 @@ struct SynthXilinxPass : public Pass Pass::call(design, "dffsr2dff"); Pass::call(design, "dff2dffe"); + if (vpr) { + Pass::call(design, "techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); + } else { + Pass::call(design, "techmap -map +/xilinx/arith_map.v"); + } + + Pass::call(design, "hierarchy -check"); + Pass::call(design, "opt -fast"); + } + + 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 @@ -278,23 +290,12 @@ struct SynthXilinxPass : public Pass // 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 + // -- 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"); } - if (vpr) { - Pass::call(design, "techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); - } else { - Pass::call(design, "techmap -map +/xilinx/arith_map.v"); - } - - Pass::call(design, "hierarchy -check"); - Pass::call(design, "opt -fast"); - } - - if (check_label(active, run_from, run_to, "map_cells")) - { 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"); -- cgit v1.2.3 From ec88129a5cf510afc39ea12efa6059bed3eadfc3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 11:38:23 -0700 Subject: 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"); -- cgit v1.2.3