diff options
Diffstat (limited to 'techlibs/xilinx')
| -rw-r--r-- | techlibs/xilinx/Makefile.inc | 7 | ||||
| -rw-r--r-- | techlibs/xilinx/abc_map.v | 123 | ||||
| -rw-r--r-- | techlibs/xilinx/abc_model.v | 34 | ||||
| -rw-r--r-- | techlibs/xilinx/abc_unmap.v | 28 | ||||
| -rw-r--r-- | techlibs/xilinx/abc_xc7.box | 39 | ||||
| -rw-r--r-- | techlibs/xilinx/cells_map.v | 2 | ||||
| -rw-r--r-- | techlibs/xilinx/cells_sim.v | 505 | ||||
| -rw-r--r-- | techlibs/xilinx/cells_xtra.v | 83 | ||||
| -rw-r--r-- | techlibs/xilinx/dsp_map.v | 48 | ||||
| -rw-r--r-- | techlibs/xilinx/ff_map.v | 42 | ||||
| -rw-r--r-- | techlibs/xilinx/synth_xilinx.cc | 65 | ||||
| -rw-r--r-- | techlibs/xilinx/tests/.gitignore | 5 | ||||
| -rw-r--r-- | techlibs/xilinx/tests/test_dsp_model.sh | 14 | ||||
| -rw-r--r-- | techlibs/xilinx/tests/test_dsp_model.v | 597 | ||||
| -rw-r--r-- | techlibs/xilinx/xc6s_ff_map.v | 126 | ||||
| -rw-r--r-- | techlibs/xilinx/xc7_brams_bb.v | 10 | ||||
| -rw-r--r-- | techlibs/xilinx/xc7_ff_map.v | 78 | 
17 files changed, 1614 insertions, 192 deletions
| diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 2b1af289c..5f5aa5518 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -35,10 +35,15 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_brams_bb.v))  $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lutrams.txt))  $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lutrams_map.v))  $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_ff_map.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_ff_map.v))  $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v))  $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/mux_map.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/dsp_map.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_map.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_unmap.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_model.v))  $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.box))  $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.lut))  $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7_nowide.lut)) diff --git a/techlibs/xilinx/abc_map.v b/techlibs/xilinx/abc_map.v new file mode 100644 index 000000000..0c85d6656 --- /dev/null +++ b/techlibs/xilinx/abc_map.v @@ -0,0 +1,123 @@ +/* + *  yosys -- Yosys Open SYnthesis Suite + * + *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> + *                2019  Eddie Hung    <eddie@fpgeh.com> + * + *  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. + * + */ + +// ============================================================================ + +module RAM32X1D ( +  output DPO, SPO, +  input  D, +  input  WCLK, +  input  WE, +  input  A0, A1, A2, A3, A4, +  input  DPRA0, DPRA1, DPRA2, DPRA3, DPRA4 +); +  parameter INIT = 32'h0; +  parameter IS_WCLK_INVERTED = 1'b0; +  wire \$DPO , \$SPO ; +  RAM32X1D #( +    .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) +  ) _TECHMAP_REPLACE_ ( +    .DPO(\$DPO ), .SPO(\$SPO ), +    .D(D), .WCLK(WCLK), .WE(WE), +    .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), +    .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4) +  ); +  \$__ABC_LUT6 dpo (.A(\$DPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(DPO)); +  \$__ABC_LUT6 spo (.A(\$SPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(SPO)); +endmodule + +module RAM64X1D ( +  output DPO, SPO, +  input  D, +  input  WCLK, +  input  WE, +  input  A0, A1, A2, A3, A4, A5, +  input  DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5 +); +  parameter INIT = 64'h0; +  parameter IS_WCLK_INVERTED = 1'b0; +  wire \$DPO , \$SPO ; +  RAM64X1D #( +    .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) +  ) _TECHMAP_REPLACE_ ( +    .DPO(\$DPO ), .SPO(\$SPO ), +    .D(D), .WCLK(WCLK), .WE(WE), +    .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), .A5(A5), +    .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4), .DPRA5(DPRA5) +  ); +  \$__ABC_LUT6 dpo (.A(\$DPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(DPO)); +  \$__ABC_LUT6 spo (.A(\$SPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(SPO)); +endmodule + +module RAM128X1D ( +  output       DPO, SPO, +  input        D, +  input        WCLK, +  input        WE, +  input  [6:0] A, DPRA +); +  parameter INIT = 128'h0; +  parameter IS_WCLK_INVERTED = 1'b0; +  wire \$DPO , \$SPO ; +  RAM128X1D #( +    .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) +  ) _TECHMAP_REPLACE_ ( +    .DPO(\$DPO ), .SPO(\$SPO ), +    .D(D), .WCLK(WCLK), .WE(WE), +    .A(A), +    .DPRA(DPRA) +  ); +  \$__ABC_LUT7 dpo (.A(\$DPO ), .S(A), .Y(DPO)); +  \$__ABC_LUT7 spo (.A(\$SPO ), .S(A), .Y(SPO)); +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; +  wire \$Q ; +  SRL16E #( +    .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED) +  ) _TECHMAP_REPLACE_ ( +    .Q(\$Q ), +    .A0(A0), .A1(A1), .A2(A2), .A3(A3), .CE(CE), .CLK(CLK), .D(D) +  ); +  \$__ABC_LUT6 q (.A(\$Q ), .S({1'b1, A0, A1, A2, A3, 1'b1}), .Y(Q)); +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; +  wire \$Q ; +  SRLC32E #( +    .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED) +  ) _TECHMAP_REPLACE_ ( +    .Q(\$Q ), .Q31(Q31), +    .A(A), .CE(CE), .CLK(CLK), .D(D) +  ); +  \$__ABC_LUT6 q (.A(\$Q ), .S({1'b1, A}), .Y(Q)); +endmodule diff --git a/techlibs/xilinx/abc_model.v b/techlibs/xilinx/abc_model.v new file mode 100644 index 000000000..655b993f6 --- /dev/null +++ b/techlibs/xilinx/abc_model.v @@ -0,0 +1,34 @@ +/* + *  yosys -- Yosys Open SYnthesis Suite + * + *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> + *                2019  Eddie Hung    <eddie@fpgeh.com> + * + *  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. + * + */ + +// ============================================================================ + +(* abc_box_id = 3, lib_whitebox *) +module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); +  assign O = S1 ? (S0 ? I3 : I2) +                : (S0 ? I1 : I0); +endmodule + +(* abc_box_id=2000 *) +module \$__ABC_LUT6 (input A, input [5:0] S, output Y); +endmodule +(* abc_box_id=2001 *) +module \$__ABC_LUT7 (input A, input [6:0] S, output Y); +endmodule diff --git a/techlibs/xilinx/abc_unmap.v b/techlibs/xilinx/abc_unmap.v new file mode 100644 index 000000000..f101a22d0 --- /dev/null +++ b/techlibs/xilinx/abc_unmap.v @@ -0,0 +1,28 @@ +/* + *  yosys -- Yosys Open SYnthesis Suite + * + *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> + *                2019  Eddie Hung    <eddie@fpgeh.com> + * + *  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. + * + */ + +// ============================================================================ + +module \$__ABC_LUT6 (input A, input [5:0] S, output Y); +  assign Y = A; +endmodule +module \$__ABC_LUT7 (input A, input [6:0] S, output Y); +  assign Y = A; +endmodule diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 3789ff350..20da3b8a0 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -1,4 +1,5 @@  # Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf +#                 https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf  # NB: Inputs/Outputs must be ordered alphabetically  #     (with exceptions for carry in/out) @@ -14,6 +15,10 @@ F7MUX 1 1 3 1  MUXF8 2 1 3 1  104 94 273 +# Box containing MUXF7.[AB] + MUXF8, +#   Necessary to make these an atomic unit so that +#   ABC cannot optimise just one of the MUXF7 away +#   and expect to save on its delay  # Inputs: I0 I1 I2 I3 S0 S1  # Outputs: O  $__MUXF78 3 1 6 1 @@ -37,22 +42,20 @@ CARRY4 4 1 10 8  580 526 507 398 385 508 528 378 380 114  # SLICEM/A6LUT -# Inputs: A0 A1 A2 A3 A4 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 WCLK WE +# Box to emulate comb/seq behaviour of RAMD{32,64} and SRL{16,32} +#   Necessary since RAMD* and SRL* have both combinatorial (i.e. +#   same-cycle read operation) and sequential (write operation +#   is only committed on the next clock edge). +#   To model the combinatorial path, such cells have to be split +#   into comb and seq parts, with this box modelling only the former. +# Inputs: A S0 S1 S2 S3 S4 S5 +# Outputs: Y +$__ABC_LUT6 2000 0 7 1 +0 642 631 472 407 238 127 + +# SLICEM/A6LUT + F7BMUX +# Box to emulate comb/seq behaviour of RAMD128 +# Inputs: A S0 S1 S2 S3 S4 S5 S6  # Outputs: DPO SPO -RAM32X1D 5 0 13 2 --   -   -   -   -   - 631 472 407 238 127 - - -631 472 407 238 127 - -   -   -   -   -   - - - -# SLICEM/A6LUT -# Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE -# Outputs: DPO SPO -RAM64X1D 6 0 15 2 --   -   -   -   -   -   - 642 631 472 407 238 127 - - -642 631 472 407 238 127 - -   -   -   -   -   -   - - - -# SLICEM/A6LUT + F7[AB]MUX -# Inputs: A0 A1 A2 A3 A4 A5 A6 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 DPRA6 WCLK WE -# Outputs: DPO SPO -RAM128X1D 7 0 17 2 --    -    -   -   -   -   -   - 1009 998 839 774 605 494 450 - - -1047 1036 877 812 643 532 478 - -    -   -   -   -   -   -   - - +$__ABC_LUT7 2001 0 8 1 +0 1047 1036 877 812 643 532 478 diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index b8e5bafc7..a15884ec4 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -331,7 +331,6 @@ module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y)  endmodule  `endif -`ifndef _ABC  module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1);    output O;    input I0, I1, I2, I3, S0, S1; @@ -364,4 +363,3 @@ module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1);    else      MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O));  endmodule -`endif diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index e12b77c02..ed421f85e 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -184,14 +184,6 @@ module MUXF8(output O, input I0, I1, S);    assign O = S ? I1 : I0;  endmodule -`ifdef _ABC -(* abc_box_id = 3, lib_whitebox *) -module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); -  assign O = S1 ? (S0 ? I3 : I2) -                : (S0 ? I1 : I0); -endmodule -`endif -  module XORCY(output O, input CI, LI);    assign O = CI ^ LI;  endmodule @@ -236,7 +228,15 @@ endmodule  `endif -module FDRE (output reg Q, (* clkbuf_sink *) input C, input CE, D, R); +// Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L238-L250 + +module FDRE ( +  (* abc_arrival=303 *) +  output reg Q, +  (* clkbuf_sink *) +  input C,  +  input CE, D, R +);    parameter [0:0] INIT = 1'b0;    parameter [0:0] IS_C_INVERTED = 1'b0;    parameter [0:0] IS_D_INVERTED = 1'b0; @@ -248,7 +248,13 @@ module FDRE (output reg Q, (* clkbuf_sink *) input C, input CE, D, R);    endcase endgenerate  endmodule -module FDSE (output reg Q, (* clkbuf_sink *) input C, input CE, D, S); +module FDSE ( +  (* abc_arrival=303 *) +  output reg Q, +  (* clkbuf_sink *) +  input C, +  input CE, D, S +);    parameter [0:0] INIT = 1'b1;    parameter [0:0] IS_C_INVERTED = 1'b0;    parameter [0:0] IS_D_INVERTED = 1'b0; @@ -260,7 +266,13 @@ module FDSE (output reg Q, (* clkbuf_sink *) input C, input CE, D, S);    endcase endgenerate  endmodule -module FDCE (output reg Q, (* clkbuf_sink *) input C, input CE, D, CLR); +module FDCE ( +  (* abc_arrival=303 *) +  output reg Q, +  (* clkbuf_sink *) +  input C, +  input CE, D, CLR +);    parameter [0:0] INIT = 1'b0;    parameter [0:0] IS_C_INVERTED = 1'b0;    parameter [0:0] IS_D_INVERTED = 1'b0; @@ -274,7 +286,13 @@ module FDCE (output reg Q, (* clkbuf_sink *) input C, input CE, D, CLR);    endcase endgenerate  endmodule -module FDPE (output reg Q, (* clkbuf_sink *) input C, input CE, D, PRE); +module FDPE ( +  (* abc_arrival=303 *) +  output reg Q, +  (* clkbuf_sink *) +  input C, +  input CE, D, PRE +);    parameter [0:0] INIT = 1'b1;    parameter [0:0] IS_C_INVERTED = 1'b0;    parameter [0:0] IS_D_INVERTED = 1'b0; @@ -288,38 +306,61 @@ module FDPE (output reg Q, (* clkbuf_sink *) input C, input CE, D, PRE);    endcase endgenerate  endmodule -module FDRE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, R); +module FDRE_1 ( +  (* abc_arrival=303 *) +  output reg Q, +  (* clkbuf_sink *) +  input C, +  input CE, D, R +);    parameter [0:0] INIT = 1'b0;    initial Q <= INIT;    always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D;  endmodule -module FDSE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, S); +module FDSE_1 ( +  (* abc_arrival=303 *) +  output reg Q, +  (* clkbuf_sink *) +  input C, +  input CE, D, S +);    parameter [0:0] INIT = 1'b1;    initial Q <= INIT;    always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D;  endmodule -module FDCE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, CLR); +module FDCE_1 ( +  (* abc_arrival=303 *) +  output reg Q, +  (* clkbuf_sink *) +  input C, +  input CE, D, CLR +);    parameter [0:0] INIT = 1'b0;    initial Q <= INIT;    always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D;  endmodule -module FDPE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, PRE); +module FDPE_1 ( +  (* abc_arrival=303 *) +  output reg Q, +  (* clkbuf_sink *) +  input C, +  input CE, D, PRE +);    parameter [0:0] INIT = 1'b1;    initial Q <= INIT;    always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;  endmodule -(* abc_box_id = 5 *)  module RAM32X1D ( +  // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 +  (* abc_arrival=1153 *)    output DPO, SPO, -  (* abc_scc_break *)    input  D,    (* clkbuf_sink *)    input  WCLK, -  (* abc_scc_break *)    input  WE,    input  A0, A1, A2, A3, A4,    input  DPRA0, DPRA1, DPRA2, DPRA3, DPRA4 @@ -335,14 +376,13 @@ module RAM32X1D (    always @(posedge clk) if (WE) mem[a] <= D;  endmodule -(* abc_box_id = 6 *)  module RAM64X1D ( +  // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 +  (* abc_arrival=1153 *)    output DPO, SPO, -  (* abc_scc_break *)    input  D,    (* clkbuf_sink *)    input  WCLK, -  (* abc_scc_break *)    input  WE,    input  A0, A1, A2, A3, A4, A5,    input  DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5 @@ -358,14 +398,13 @@ module RAM64X1D (    always @(posedge clk) if (WE) mem[a] <= D;  endmodule -(* abc_box_id = 7 *)  module RAM128X1D ( -  output       DPO, SPO, -  (* abc_scc_break *) +  // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 +  (* abc_arrival=1153 *) +  output DPO, SPO,    input        D,    (* clkbuf_sink *)    input        WCLK, -  (* abc_scc_break *)    input        WE,    input  [6:0] A, DPRA  ); @@ -379,6 +418,8 @@ module RAM128X1D (  endmodule  module SRL16E ( +  // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904-L905 +  (* abc_arrival=1472 *)    output Q,    input A0, A1, A2, A3, CE,    (* clkbuf_sink *) @@ -423,7 +464,10 @@ module SRLC16E (  endmodule  module SRLC32E ( +  // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904-L905 +  (* abc_arrival=1472 *)    output Q, +  (* abc_arrival=1114 *)    output Q31,    input [4:0] A,    input CE, @@ -445,3 +489,412 @@ module SRLC32E (        always @(posedge CLK) if (CE) r <= { r[30:0], D };    endgenerate  endmodule + +module DSP48E1 ( +    output [29:0] ACOUT, +    output [17:0] BCOUT, +    output reg CARRYCASCOUT, +    output reg [3:0] CARRYOUT, +    output reg MULTSIGNOUT, +    output OVERFLOW, +    output reg signed [47:0] P, +    output PATTERNBDETECT, +    output PATTERNDETECT, +    output [47:0] PCOUT, +    output UNDERFLOW, +    input signed [29:0] A, +    input [29:0] ACIN, +    input [3:0] ALUMODE, +    input signed [17:0] B, +    input [17:0] BCIN, +    input [47:0] C, +    input CARRYCASCIN, +    input CARRYIN, +    input [2:0] CARRYINSEL, +    input CEA1, +    input CEA2, +    input CEAD, +    input CEALUMODE, +    input CEB1, +    input CEB2, +    input CEC, +    input CECARRYIN, +    input CECTRL, +    input CED, +    input CEINMODE, +    input CEM, +    input CEP, +    (* clkbuf_sink *) input CLK, +    input [24:0] D, +    input [4:0] INMODE, +    input MULTSIGNIN, +    input [6:0] OPMODE, +    input [47:0] PCIN, +    input RSTA, +    input RSTALLCARRYIN, +    input RSTALUMODE, +    input RSTB, +    input RSTC, +    input RSTCTRL, +    input RSTD, +    input RSTINMODE, +    input RSTM, +    input RSTP +); +    parameter integer ACASCREG = 1; +    parameter integer ADREG = 1; +    parameter integer ALUMODEREG = 1; +    parameter integer AREG = 1; +    parameter AUTORESET_PATDET = "NO_RESET"; +    parameter A_INPUT = "DIRECT"; +    parameter integer BCASCREG = 1; +    parameter integer BREG = 1; +    parameter B_INPUT = "DIRECT"; +    parameter integer CARRYINREG = 1; +    parameter integer CARRYINSELREG = 1; +    parameter integer CREG = 1; +    parameter integer DREG = 1; +    parameter integer INMODEREG = 1; +    parameter integer MREG = 1; +    parameter integer OPMODEREG = 1; +    parameter integer PREG = 1; +    parameter SEL_MASK = "MASK"; +    parameter SEL_PATTERN = "PATTERN"; +    parameter USE_DPORT = "FALSE"; +    parameter USE_MULT = "MULTIPLY"; +    parameter USE_PATTERN_DETECT = "NO_PATDET"; +    parameter USE_SIMD = "ONE48"; +    parameter [47:0] MASK = 48'h3FFFFFFFFFFF; +    parameter [47:0] PATTERN = 48'h000000000000; +    parameter [3:0] IS_ALUMODE_INVERTED = 4'b0; +    parameter [0:0] IS_CARRYIN_INVERTED = 1'b0; +    parameter [0:0] IS_CLK_INVERTED = 1'b0; +    parameter [4:0] IS_INMODE_INVERTED = 5'b0; +    parameter [6:0] IS_OPMODE_INVERTED = 7'b0; + +    initial begin +`ifdef __ICARUS__ +        if (AUTORESET_PATDET != "NO_RESET") $fatal(1, "Unsupported AUTORESET_PATDET value"); +        //if (PREG != 0)              $fatal(1, "Unsupported PREG value"); +        if (SEL_MASK != "MASK")     $fatal(1, "Unsupported SEL_MASK value"); +        if (SEL_PATTERN != "PATTERN") $fatal(1, "Unsupported SEL_PATTERN value"); +        if (USE_PATTERN_DETECT != "NO_PATDET") $fatal(1, "Unsupported USE_PATTERN_DETECT value"); +        if (USE_SIMD != "ONE48" && USE_SIMD != "TWO24" && USE_SIMD != "FOUR12")    $fatal(1, "Unsupported USE_SIMD value"); +        if (IS_ALUMODE_INVERTED != 4'b0) $fatal(1, "Unsupported IS_ALUMODE_INVERTED value"); +        if (IS_CARRYIN_INVERTED != 1'b0) $fatal(1, "Unsupported IS_CARRYIN_INVERTED value"); +        if (IS_CLK_INVERTED != 1'b0) $fatal(1, "Unsupported IS_CLK_INVERTED value"); +        if (IS_INMODE_INVERTED != 5'b0) $fatal(1, "Unsupported IS_INMODE_INVERTED value"); +        if (IS_OPMODE_INVERTED != 7'b0) $fatal(1, "Unsupported IS_OPMODE_INVERTED value"); +`endif +    end + +    wire signed [29:0] A_muxed; +    wire signed [17:0] B_muxed; + +    generate +        if (A_INPUT == "CASCADE") assign A_muxed = ACIN; +        else assign A_muxed = A; + +        if (B_INPUT == "CASCADE") assign B_muxed = BCIN; +        else assign B_muxed = B; +    endgenerate + +    reg signed [29:0] Ar1 = 30'b0, Ar2 = 30'b0; +    reg signed [24:0] Dr = 25'b0; +    reg signed [17:0] Br1 = 18'b0, Br2 = 18'b0; +    reg signed [47:0] Cr = 48'b0; +    reg        [4:0]  INMODEr = 5'b0; +    reg        [6:0]  OPMODEr = 7'b0; +    reg        [3:0]  ALUMODEr = 4'b0; +    reg        [2:0]  CARRYINSELr = 3'b0; + +    generate +        // Configurable A register +        if (AREG == 2) begin +            always @(posedge CLK) +                if (RSTA) begin +                    Ar1 <= 30'b0; +                    Ar2 <= 30'b0; +                end else begin +                    if (CEA1) Ar1 <= A_muxed; +                    if (CEA2) Ar2 <= Ar1; +                end +        end else if (AREG == 1) begin +            always @(posedge CLK) +                if (RSTA) begin +                    Ar1 <= 30'b0; +                    Ar2 <= 30'b0; +                end else begin +                    if (CEA1) Ar1 <= A_muxed; +                    if (CEA2) Ar2 <= A_muxed; +                end +        end else begin +            always @* Ar1 <= A_muxed; +            always @* Ar2 <= A_muxed; +        end + +        // Configurable B register +        if (BREG == 2) begin +            always @(posedge CLK) +                if (RSTB) begin +                    Br1 <= 18'b0; +                    Br2 <= 18'b0; +                end else begin +                    if (CEB1) Br1 <= B_muxed; +                    if (CEB2) Br2 <= Br1; +                end +        end else if (BREG == 1) begin +            always @(posedge CLK) +                if (RSTB) begin +                    Br1 <= 18'b0; +                    Br2 <= 18'b0; +                end else begin +                    if (CEB1) Br1 <= B_muxed; +                    if (CEB2) Br2 <= B_muxed; +                end +        end else begin +            always @* Br1 <= B_muxed; +            always @* Br2 <= B_muxed; +        end + +        // C and D registers +        if (CREG == 1) begin always @(posedge CLK) if (RSTC) Cr <= 48'b0; else if (CEC) Cr <= C; end +        else           always @* Cr <= C; + +        if (DREG == 1) begin always @(posedge CLK) if (RSTD) Dr <= 25'b0; else if (CED) Dr <= D; end +        else           always @* Dr <= D; + +        // Control registers +        if (INMODEREG == 1) begin always @(posedge CLK) if (RSTINMODE) INMODEr <= 5'b0; else if (CEINMODE) INMODEr <= INMODE; end +        else           always @* INMODEr <= INMODE; +        if (OPMODEREG == 1) begin always @(posedge CLK) if (RSTCTRL) OPMODEr <= 7'b0; else if (CECTRL) OPMODEr <= OPMODE; end +        else           always @* OPMODEr <= OPMODE; +        if (ALUMODEREG == 1) begin always @(posedge CLK) if (RSTALUMODE) ALUMODEr <= 4'b0; else if (CEALUMODE) ALUMODEr <= ALUMODE; end +        else           always @* ALUMODEr <= ALUMODE; +        if (CARRYINSELREG == 1) begin always @(posedge CLK) if (RSTCTRL) CARRYINSELr <= 3'b0; else if (CECTRL) CARRYINSELr <= CARRYINSEL; end +        else           always @* CARRYINSELr <= CARRYINSEL; +    endgenerate + +    // A and B cascsde +    generate +        if (ACASCREG == 1 && AREG == 2) assign ACOUT = Ar1; +        else assign ACOUT = Ar2; +        if (BCASCREG == 1 && BREG == 2) assign BCOUT = Br1; +        else assign BCOUT = Br2; +    endgenerate + +    // A/D input selection and pre-adder +    wire signed [29:0] Ar12_muxed = INMODEr[0] ? Ar1 : Ar2; +    wire signed [24:0] Ar12_gated = INMODEr[1] ? 25'b0 : Ar12_muxed; +    wire signed [24:0] Dr_gated   = INMODEr[2] ? Dr : 25'b0; +    wire signed [24:0] AD_result  = INMODEr[3] ? (Dr_gated - Ar12_gated) : (Dr_gated + Ar12_gated); +    reg  signed [24:0] ADr = 25'b0; + +    generate +        if (ADREG == 1) begin always @(posedge CLK) if (RSTD) ADr <= 25'b0; else if (CEAD) ADr <= AD_result; end +        else            always @* ADr <= AD_result; +    endgenerate + +    // 25x18 multiplier +    wire signed [24:0] A_MULT; +    wire signed [17:0] B_MULT = INMODEr[4] ? Br1 : Br2; +    generate +        if (USE_DPORT == "TRUE") assign A_MULT = ADr; +        else assign A_MULT = Ar12_gated; +    endgenerate + +    wire signed [42:0] M = A_MULT * B_MULT; +    wire signed [42:0] Mx = (CARRYINSEL == 3'b010) ? 43'bx : M; +    reg  signed [42:0] Mr = 43'b0; + +    // Multiplier result register +    generate +        if (MREG == 1) begin always @(posedge CLK) if (RSTM) Mr <= 43'b0; else if (CEM) Mr <= Mx; end +        else           always @* Mr <= Mx; +    endgenerate + +    wire signed [42:0] Mrx = (CARRYINSELr == 3'b010) ? 43'bx : Mr; + +    // X, Y and Z ALU inputs +    reg signed [47:0] X, Y, Z; + +    always @* begin +        // X multiplexer +        case (OPMODEr[1:0]) +            2'b00: X = 48'b0; +            2'b01: begin X = $signed(Mrx); +`ifdef __ICARUS__ +                if (OPMODEr[3:2] != 2'b01) $fatal(1, "OPMODEr[3:2] must be 2'b01 when OPMODEr[1:0] is 2'b01"); +`endif +            end +            2'b10: begin X = P; +`ifdef __ICARUS__ +                if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[1:0] is 2'b10"); +`endif +            end +            2'b11: X = $signed({Ar2, Br2}); +            default: X = 48'bx; +        endcase + +        // Y multiplexer +        case (OPMODEr[3:2]) +            2'b00: Y = 48'b0; +            2'b01: begin Y = 48'b0; // FIXME: more accurate partial product modelling? +`ifdef __ICARUS__ +                if (OPMODEr[1:0] != 2'b01) $fatal(1, "OPMODEr[1:0] must be 2'b01 when OPMODEr[3:2] is 2'b01"); +`endif +            end +            2'b10: Y = {48{1'b1}}; +            2'b11: Y = Cr; +            default: Y = 48'bx; +        endcase + +        // Z multiplexer +        case (OPMODEr[6:4]) +            3'b000: Z = 48'b0; +            3'b001: Z = PCIN; +            3'b010: begin Z = P; +`ifdef __ICARUS__ +                if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] i0s 3'b010"); +`endif +            end +            3'b011: Z = Cr; +            3'b100: begin Z = P; +`ifdef __ICARUS__ +                if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b100"); +                if (OPMODEr[3:0] != 4'b1000) $fatal(1, "OPMODEr[3:0] must be 4'b1000 when OPMODEr[6:4] i0s 3'b100"); +`endif +            end +            3'b101: Z = $signed(PCIN[47:17]); +            3'b110: Z = $signed(P[47:17]); +            default: Z = 48'bx; +        endcase +    end + +    // Carry in +    wire A24_xnor_B17d = A_MULT[24] ~^ B_MULT[17]; +    reg CARRYINr = 1'b0, A24_xnor_B17 = 1'b0; +    generate +        if (CARRYINREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) CARRYINr <= 1'b0; else if (CECARRYIN) CARRYINr <= CARRYIN; end +        else                 always @* CARRYINr = CARRYIN; + +        if (MREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) A24_xnor_B17 <= 1'b0; else if (CEM) A24_xnor_B17 <= A24_xnor_B17d; end +        else                 always @* A24_xnor_B17 = A24_xnor_B17d; +    endgenerate + +    reg cin_muxed; + +    always @(*) begin +        case (CARRYINSELr) +            3'b000: cin_muxed = CARRYINr; +            3'b001: cin_muxed = ~PCIN[47]; +            3'b010: cin_muxed = CARRYCASCIN; +            3'b011: cin_muxed = PCIN[47]; +            3'b100: cin_muxed = CARRYCASCOUT; +            3'b101: cin_muxed = ~P[47]; +            3'b110: cin_muxed = A24_xnor_B17; +            3'b111: cin_muxed = P[47]; +            default: cin_muxed = 1'bx; +        endcase +    end + +    wire alu_cin = (ALUMODEr[3] || ALUMODEr[2]) ? 1'b0 : cin_muxed; + +    // ALU core +    wire [47:0] Z_muxinv = ALUMODEr[0] ? ~Z : Z; +    wire [47:0] xor_xyz = X ^ Y ^ Z_muxinv; +    wire [47:0] maj_xyz = (X & Y) | (X & Z_muxinv) | (Y & Z_muxinv); + +    wire [47:0] xor_xyz_muxed = ALUMODEr[3] ? maj_xyz : xor_xyz; +    wire [47:0] maj_xyz_gated = ALUMODEr[2] ? 48'b0 :  maj_xyz; + +    wire [48:0] maj_xyz_simd_gated; +    wire [3:0] int_carry_in, int_carry_out, ext_carry_out; +    wire [47:0] alu_sum; +    assign int_carry_in[0] = 1'b0; +    wire [3:0] carryout_reset; + +    generate +        if (USE_SIMD == "FOUR12") begin +            assign maj_xyz_simd_gated = { +                    maj_xyz_gated[47:36], +                    1'b0, maj_xyz_gated[34:24], +                    1'b0, maj_xyz_gated[22:12], +                    1'b0, maj_xyz_gated[10:0], +                    alu_cin +                }; +            assign int_carry_in[3:1] = 3'b000; +            assign ext_carry_out = { +                    int_carry_out[3], +                    maj_xyz_gated[35] ^ int_carry_out[2], +                    maj_xyz_gated[23] ^ int_carry_out[1], +                    maj_xyz_gated[11] ^ int_carry_out[0] +                }; +            assign carryout_reset = 4'b0000; +        end else if (USE_SIMD == "TWO24") begin +            assign maj_xyz_simd_gated = { +                    maj_xyz_gated[47:24], +                    1'b0, maj_xyz_gated[22:0], +                    alu_cin +                }; +            assign int_carry_in[3:1] = {int_carry_out[2], 1'b0, int_carry_out[0]}; +            assign ext_carry_out = { +                    int_carry_out[3], +                    1'bx, +                    maj_xyz_gated[23] ^ int_carry_out[1], +                    1'bx +                }; +            assign carryout_reset = 4'b0x0x; +        end else begin +            assign maj_xyz_simd_gated = {maj_xyz_gated, alu_cin}; +            assign int_carry_in[3:1] = int_carry_out[2:0]; +            assign ext_carry_out = { +                    int_carry_out[3], +                    3'bxxx +                }; +            assign carryout_reset = 4'b0xxx; +        end + +        genvar i; +        for (i = 0; i < 4; i = i + 1) +            assign {int_carry_out[i], alu_sum[i*12 +: 12]} = {1'b0, maj_xyz_simd_gated[i*12 +: ((i == 3) ? 13 : 12)]} +                                                              + xor_xyz_muxed[i*12 +: 12] + int_carry_in[i]; +    endgenerate + +    wire signed [47:0] Pd = ALUMODEr[1] ? ~alu_sum : alu_sum; +    initial P = 48'b0; +    initial CARRYOUT = carryout_reset; +    initial CARRYCASCOUT = 1'b0; +    initial MULTSIGNOUT = 1'b0; +    wire [3:0] CARRYOUTd = (OPMODEr[3:0] == 4'b0101 || ALUMODEr[3:2] != 2'b00) ? 4'bxxxx : +                           ((ALUMODEr[0] & ALUMODEr[1]) ? ~ext_carry_out : ext_carry_out); +    wire CARRYCASCOUTd = ext_carry_out[3]; +    wire MULTSIGNOUTd = Mrx[42]; + +    generate +        if (PREG == 1) begin +            always @(posedge CLK) +                if (RSTP) begin +                    P <= 48'b0; +                    CARRYOUT <= carryout_reset; +                    CARRYCASCOUT <= 1'b0; +                    MULTSIGNOUT <= 1'b0; +                end else if (CEP) begin +                    P <= Pd; +                    CARRYOUT <= CARRYOUTd; +                    CARRYCASCOUT <= CARRYCASCOUTd; +                    MULTSIGNOUT <= MULTSIGNOUTd; +                end +        end else begin +            always @* begin +                P = Pd; +                CARRYOUT = CARRYOUTd; +                CARRYCASCOUT = CARRYCASCOUTd; +                MULTSIGNOUT = MULTSIGNOUTd; +            end +        end +    endgenerate + +    assign PCOUT = P; + +endmodule diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v index a6669b872..b8abdda64 100644 --- a/techlibs/xilinx/cells_xtra.v +++ b/techlibs/xilinx/cells_xtra.v @@ -137,89 +137,6 @@ module DNA_PORT (...);      input SHIFT;  endmodule -module DSP48E1 (...); -    parameter integer ACASCREG = 1; -    parameter integer ADREG = 1; -    parameter integer ALUMODEREG = 1; -    parameter integer AREG = 1; -    parameter AUTORESET_PATDET = "NO_RESET"; -    parameter A_INPUT = "DIRECT"; -    parameter integer BCASCREG = 1; -    parameter integer BREG = 1; -    parameter B_INPUT = "DIRECT"; -    parameter integer CARRYINREG = 1; -    parameter integer CARRYINSELREG = 1; -    parameter integer CREG = 1; -    parameter integer DREG = 1; -    parameter integer INMODEREG = 1; -    parameter integer MREG = 1; -    parameter integer OPMODEREG = 1; -    parameter integer PREG = 1; -    parameter SEL_MASK = "MASK"; -    parameter SEL_PATTERN = "PATTERN"; -    parameter USE_DPORT = "FALSE"; -    parameter USE_MULT = "MULTIPLY"; -    parameter USE_PATTERN_DETECT = "NO_PATDET"; -    parameter USE_SIMD = "ONE48"; -    parameter [47:0] MASK = 48'h3FFFFFFFFFFF; -    parameter [47:0] PATTERN = 48'h000000000000; -    parameter [3:0] IS_ALUMODE_INVERTED = 4'b0; -    parameter [0:0] IS_CARRYIN_INVERTED = 1'b0; -    parameter [0:0] IS_CLK_INVERTED = 1'b0; -    parameter [4:0] IS_INMODE_INVERTED = 5'b0; -    parameter [6:0] IS_OPMODE_INVERTED = 7'b0; -    output [29:0] ACOUT; -    output [17:0] BCOUT; -    output CARRYCASCOUT; -    output [3:0] CARRYOUT; -    output MULTSIGNOUT; -    output OVERFLOW; -    output [47:0] P; -    output PATTERNBDETECT; -    output PATTERNDETECT; -    output [47:0] PCOUT; -    output UNDERFLOW; -    input [29:0] A; -    input [29:0] ACIN; -    input [3:0] ALUMODE; -    input [17:0] B; -    input [17:0] BCIN; -    input [47:0] C; -    input CARRYCASCIN; -    input CARRYIN; -    input [2:0] CARRYINSEL; -    input CEA1; -    input CEA2; -    input CEAD; -    input CEALUMODE; -    input CEB1; -    input CEB2; -    input CEC; -    input CECARRYIN; -    input CECTRL; -    input CED; -    input CEINMODE; -    input CEM; -    input CEP; -    (* clkbuf_sink *) -    input CLK; -    input [24:0] D; -    input [4:0] INMODE; -    input MULTSIGNIN; -    input [6:0] OPMODE; -    input [47:0] PCIN; -    input RSTA; -    input RSTALLCARRYIN; -    input RSTALUMODE; -    input RSTB; -    input RSTC; -    input RSTCTRL; -    input RSTD; -    input RSTINMODE; -    input RSTM; -    input RSTP; -endmodule -  module EFUSE_USR (...);      parameter [31:0] SIM_EFUSE_VALUE = 32'h00000000;      output [31:0] EFUSEUSR; diff --git a/techlibs/xilinx/dsp_map.v b/techlibs/xilinx/dsp_map.v new file mode 100644 index 000000000..cc37f0085 --- /dev/null +++ b/techlibs/xilinx/dsp_map.v @@ -0,0 +1,48 @@ +module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] Y); +	parameter A_SIGNED = 0; +	parameter B_SIGNED = 0; +	parameter A_WIDTH = 0; +	parameter B_WIDTH = 0; +	parameter Y_WIDTH = 0; + +	wire [47:0] P_48; +	DSP48E1 #( +		// Disable all registers +		.ACASCREG(0), +		.ADREG(0), +		.A_INPUT("DIRECT"), +		.ALUMODEREG(0), +		.AREG(0), +		.BCASCREG(0), +		.B_INPUT("DIRECT"), +		.BREG(0), +		.CARRYINREG(0), +		.CARRYINSELREG(0), +		.CREG(0), +		.DREG(0), +		.INMODEREG(0), +		.MREG(0), +		.OPMODEREG(0), +		.PREG(0), +		.USE_MULT("MULTIPLY"), +		.USE_SIMD("ONE48") +	) _TECHMAP_REPLACE_ ( +		//Data path +		.A({{5{A[24]}}, A}), +		.B(B), +		.C(48'b0), +		.D(24'b0), +		.P(P_48), + +		.INMODE(5'b00000), +		.ALUMODE(4'b0000), +		.OPMODE(7'b000101), +		.CARRYINSEL(3'b000), + +		.ACIN(30'b0), +		.BCIN(18'b0), +		.PCIN(48'b0), +		.CARRYIN(1'b0) +	); +	assign Y = P_48; +endmodule diff --git a/techlibs/xilinx/ff_map.v b/techlibs/xilinx/ff_map.v deleted file mode 100644 index 4571f6d5c..000000000 --- a/techlibs/xilinx/ff_map.v +++ /dev/null @@ -1,42 +0,0 @@ -/* - *  yosys -- Yosys Open SYnthesis Suite - * - *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> - * - *  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. - * - */ - -// ============================================================================ -// FF mapping - -`ifndef _NO_FFS - -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); FDCE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!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); FDCE   #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!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); FDPE_1 #(.INIT(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule -module  \$_DFF_NP1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule -module  \$_DFF_PN1_ (input D, C, R, output Q); FDPE   #(.INIT(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule -module  \$_DFF_PP1_ (input D, C, R, output Q); FDPE   #(.INIT(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule - -`endif - diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 3760a1129..3d92c3e2c 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -81,6 +81,8 @@ struct SynthXilinxPass : public ScriptPass  		log("    -nowidelut\n");  		log("        do not use MUXF[78] resources to implement LUTs larger than LUT6s\n");  		log("\n"); +		log("    -nodsp\n"); +		log("        do not use DSP48E1s to implement multipliers and associated logic\n");  		log("    -iopad\n");  		log("        enable I/O buffer insertion (selected automatically by -ise)\n");  		log("\n"); @@ -116,7 +118,7 @@ struct SynthXilinxPass : public ScriptPass  	}  	std::string top_opt, edif_file, blif_file, family; -	bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, abc9; +	bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, abc9;  	bool flatten_before_abc;  	int widemux; @@ -139,6 +141,7 @@ struct SynthXilinxPass : public ScriptPass  		nosrl = false;  		nocarry = false;  		nowidelut = false; +		nodsp = false;  		abc9 = false;  		flatten_before_abc = false;  		widemux = 0; @@ -240,6 +243,10 @@ struct SynthXilinxPass : public ScriptPass  				abc9 = true;  				continue;  			} +			if (args[argidx] == "-nodsp") { +				nodsp = true; +				continue; +			}  			break;  		}  		extra_args(args, argidx, design); @@ -266,11 +273,19 @@ struct SynthXilinxPass : public ScriptPass  	void script() YS_OVERRIDE  	{ +		std::string ff_map_file; +		if (help_mode) +			ff_map_file = "+/xilinx/xc6s_ff_map.v"; +		else if (family == "xc6s") +			ff_map_file = "+/xilinx/xc6s_ff_map.v"; +		else +			ff_map_file = "+/xilinx/xc7_ff_map.v"; +  		if (check_label("begin")) {  			if (vpr) -				run("read_verilog -lib -icells -D _ABC -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); +				run("read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v");  			else -				run("read_verilog -lib -icells -D _ABC +/xilinx/cells_sim.v"); +				run("read_verilog -lib +/xilinx/cells_sim.v");  			run("read_verilog -lib +/xilinx/cells_xtra.v"); @@ -285,10 +300,10 @@ struct SynthXilinxPass : public ScriptPass  			run(stringf("hierarchy -check %s", top_opt.c_str()));  		} -		if (check_label("coarse")) { +		if (check_label("prepare")) {  			run("proc"); -			if (help_mode || flatten) -				run("flatten", "(if -flatten)"); +			if (flatten || help_mode) +				run("flatten", "(with '-flatten')");  			run("opt_expr");  			run("opt_clean");  			run("check"); @@ -312,6 +327,18 @@ struct SynthXilinxPass : public ScriptPass  			}  			run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6"); +		} + +		if (check_label("map_dsp"), "(skip if '-nodsp')") { +			if (!nodsp || help_mode) { +				// NB: Xilinx multipliers are signed only +				run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18"); +				run("xilinx_dsp"); +				run("chtype -set $mul t:$__soft_mul"); +			} +		} + +		if (check_label("coarse")) {  			run("alumacc");  			run("share");  			run("opt"); @@ -408,7 +435,7 @@ struct SynthXilinxPass : public ScriptPass  		}  		if (check_label("map_cells")) { -			std::string techmap_args = "-map +/techmap.v -D _ABC -map +/xilinx/cells_map.v"; +			std::string techmap_args = "-map +/techmap.v -map +/xilinx/cells_map.v";  			if (widemux > 0)  				techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", widemux);  			run("techmap " + techmap_args); @@ -416,11 +443,9 @@ struct SynthXilinxPass : public ScriptPass  		}  		if (check_label("map_ffs")) { -				if (abc9 || help_mode) { -						run("techmap -map +/xilinx/ff_map.v", "('-abc9' only)"); -						run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " -										"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT", "('-abc9' only)"); -				} +			if (abc9 || help_mode) { +				run("techmap -map " + ff_map_file, "('-abc9' only)"); +			}  		}  		if (check_label("map_luts")) { @@ -428,10 +453,12 @@ struct SynthXilinxPass : public ScriptPass  			if (flatten_before_abc)  				run("flatten");  			if (help_mode) -				run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(option for 'nowidelut', option for '-retime')"); +				run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(option for 'nowidelut'; option for '-retime')");  			else if (abc9) {  				if (family != "xc7")  					log_warning("'synth_xilinx -abc9' currently supports '-family xc7' only.\n"); +				run("techmap -map +/xilinx/abc_map.v -max_iter 1"); +				run("read_verilog -icells -lib +/xilinx/abc_model.v");  				if (nowidelut)  					run("abc9 -lut +/xilinx/abc_xc7_nowide.lut -box +/xilinx/abc_xc7.box -W " + std::to_string(XC7_WIRE_DELAY));  				else @@ -449,16 +476,14 @@ struct SynthXilinxPass : public ScriptPass  			//   has performed any necessary retiming  			if (!nosrl || help_mode)  				run("xilinx_srl -fixed -minlen 3", "(skip if '-nosrl')"); -  			std::string techmap_args = "-map +/xilinx/lut_map.v -map +/xilinx/cells_map.v";  			if (help_mode) -					techmap_args += " [-map +/xilinx/ff_map.v]"; -			else if (!abc9) -					techmap_args += " -map +/xilinx/ff_map.v"; +				techmap_args += " [-map " + ff_map_file + "]"; +			else if (abc9) +				techmap_args += " -map +/xilinx/abc_unmap.v"; +			else +				techmap_args += " -map " + ff_map_file;  			run("techmap " + techmap_args); -			if (!abc9) -				run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " -						"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT", "(without '-abc9' only)");  			run("clean");  		} diff --git a/techlibs/xilinx/tests/.gitignore b/techlibs/xilinx/tests/.gitignore index 496b87461..ef3699bd2 100644 --- a/techlibs/xilinx/tests/.gitignore +++ b/techlibs/xilinx/tests/.gitignore @@ -4,3 +4,8 @@ bram1_[0-9]*/  bram2.log  bram2_syn.v  bram2_tb +dsp_work*/ +test_dsp_model_ref.v +test_dsp_model_uut.v +test_dsp_model +*.vcd diff --git a/techlibs/xilinx/tests/test_dsp_model.sh b/techlibs/xilinx/tests/test_dsp_model.sh new file mode 100644 index 000000000..2acd97eb4 --- /dev/null +++ b/techlibs/xilinx/tests/test_dsp_model.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -ex +sed 's/DSP48E1/DSP48E1_UUT/; /DSP48E1_UUT/,/endmodule/ p; d;' < ../cells_sim.v > test_dsp_model_uut.v +if [ ! -f "test_dsp_model_ref.v" ]; then +	cat /opt/Xilinx/Vivado/2019.1/data/verilog/src/unisims/DSP48E1.v > test_dsp_model_ref.v +fi +for tb in simd24_preadd_noreg_nocasc simd12_preadd_noreg_nocasc \ +    mult_allreg_nopreadd_nocasc mult_noreg_nopreadd_nocasc  \ +	mult_allreg_preadd_nocasc mult_noreg_preadd_nocasc mult_inreg_preadd_nocasc \ +	 +do +	iverilog -s $tb -s glbl -o test_dsp_model test_dsp_model.v test_dsp_model_uut.v test_dsp_model_ref.v /opt/Xilinx/Vivado/2019.1/data/verilog/src/glbl.v +	vvp -N ./test_dsp_model +done diff --git a/techlibs/xilinx/tests/test_dsp_model.v b/techlibs/xilinx/tests/test_dsp_model.v new file mode 100644 index 000000000..04d5b26ab --- /dev/null +++ b/techlibs/xilinx/tests/test_dsp_model.v @@ -0,0 +1,597 @@ +`timescale 1ns / 1ps + +module testbench; +    parameter integer ACASCREG = 1; +    parameter integer ADREG = 1; +    parameter integer ALUMODEREG = 1; +    parameter integer AREG = 1; +    parameter AUTORESET_PATDET = "NO_RESET"; +    parameter A_INPUT = "DIRECT"; +    parameter integer BCASCREG = 1; +    parameter integer BREG = 1; +    parameter B_INPUT = "DIRECT"; +    parameter integer CARRYINREG = 1; +    parameter integer CARRYINSELREG = 1; +    parameter integer CREG = 1; +    parameter integer DREG = 1; +    parameter integer INMODEREG = 1; +    parameter integer MREG = 1; +    parameter integer OPMODEREG = 1; +    parameter integer PREG = 1; +    parameter SEL_MASK = "MASK"; +    parameter SEL_PATTERN = "PATTERN"; +    parameter USE_DPORT = "FALSE"; +    parameter USE_MULT = "MULTIPLY"; +    parameter USE_PATTERN_DETECT = "NO_PATDET"; +    parameter USE_SIMD = "ONE48"; +    parameter [47:0] MASK = 48'h3FFFFFFFFFFF; +    parameter [47:0] PATTERN = 48'h000000000000; +    parameter [3:0] IS_ALUMODE_INVERTED = 4'b0; +    parameter [0:0] IS_CARRYIN_INVERTED = 1'b0; +    parameter [0:0] IS_CLK_INVERTED = 1'b0; +    parameter [4:0] IS_INMODE_INVERTED = 5'b0; +    parameter [6:0] IS_OPMODE_INVERTED = 7'b0; + +	reg CLK; +	reg CEA1, CEA2, CEAD, CEALUMODE, CEB1, CEB2, CEC, CECARRYIN, CECTRL; +	reg CED, CEINMODE, CEM, CEP; +	reg RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP; +	reg [29:0] A, ACIN; +	reg [17:0] B, BCIN; +	reg [47:0] C; +	reg [24:0] D; +	reg [47:0] PCIN; +	reg [3:0] ALUMODE; +	reg [2:0] CARRYINSEL; +	reg [4:0] INMODE; +	reg [6:0] OPMODE; +	reg CARRYCASCIN, CARRYIN, MULTSIGNIN; + +    output [29:0] ACOUT, REF_ACOUT; +    output [17:0] BCOUT, REF_BCOUT; +    output CARRYCASCOUT, REF_CARRYCASCOUT; +    output [3:0] CARRYOUT, REF_CARRYOUT; +    output MULTSIGNOUT, REF_MULTSIGNOUT; +    output OVERFLOW, REF_OVERFLOW; +    output [47:0] P, REF_P; +    output PATTERNBDETECT, REF_PATTERNBDETECT; +    output PATTERNDETECT, REF_PATTERNDETECT; +    output [47:0] PCOUT, REF_PCOUT; +    output UNDERFLOW, REF_UNDERFLOW; + +	integer errcount = 0; + +	reg ERROR_FLAG = 0; + +	task clkcycle; +		begin +			#5; +			CLK = ~CLK; +			#10; +			CLK = ~CLK; +			#2; +			ERROR_FLAG = 0; +			if (REF_P !== P) begin +				$display("ERROR at %1t: REF_P=%b UUT_P=%b DIFF=%b", $time, REF_P, P, REF_P ^ P); +				errcount = errcount + 1; +				ERROR_FLAG = 1; +			end +			if (REF_CARRYOUT !== CARRYOUT) begin +				$display("ERROR at %1t: REF_CARRYOUT=%b UUT_CARRYOUT=%b", $time, REF_CARRYOUT, CARRYOUT); +				errcount = errcount + 1; +				ERROR_FLAG = 1; +			end +			#3; +		end +	endtask + +	reg config_valid = 0; +	task drc; +		begin +			config_valid = 1; +			if (AREG != 2 && INMODE[0]) config_valid = 0; +			if (BREG != 2 && INMODE[4]) config_valid = 0; + +			if (USE_SIMD != "ONE48" && OPMODE[3:0] == 4'b0101) config_valid = 0; + +			if (OPMODE[1:0] == 2'b10 && PREG != 1) config_valid = 0; +			if ((OPMODE[3:2] == 2'b01) ^ (OPMODE[1:0] == 2'b01) == 1'b1) config_valid = 0; +			if ((OPMODE[6:4] == 3'b010 || OPMODE[6:4] == 3'b110) && PREG != 1) config_valid = 0; +			if ((OPMODE[6:4] == 3'b100) && (PREG != 1 || OPMODE[3:0] != 4'b1000 || ALUMODE[3:2] == 2'b01 || ALUMODE[3:2] == 2'b11)) config_valid = 0; +			if ((CARRYINSEL == 3'b100 || CARRYINSEL == 3'b101 || CARRYINSEL == 3'b111) && (PREG != 1)) config_valid = 0; +			if (OPMODE[6:4] == 3'b111) config_valid = 0; +			if ((OPMODE[3:0] == 4'b0101) && CARRYINSEL == 3'b010) config_valid = 0; +			if (CARRYINSEL == 3'b000 && OPMODE == 7'b1001000) config_valid = 0; + +			if ((ALUMODE[3:2] == 2'b01 || ALUMODE[3:2] == 2'b11) && OPMODE[3:2] != 2'b00 && OPMODE[3:2] != 2'b10) config_valid = 0; + + +		end +	endtask + +	initial begin +		$dumpfile("test_dsp_model.vcd"); +		$dumpvars(0, testbench); + +		#2; +		CLK = 1'b0; +		{CEA1, CEA2, CEAD, CEALUMODE, CEB1, CEB2, CEC, CECARRYIN, CECTRL} = 9'b111111111; +		{CED, CEINMODE, CEM, CEP} = 4'b1111; + +		{A, B, C, D} = 0; +		{ACIN, BCIN, PCIN} = 0; +		{ALUMODE, CARRYINSEL, INMODE} = 0; +		{OPMODE, CARRYCASCIN, CARRYIN, MULTSIGNIN} = 0; + +		{RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP} = ~0; +		repeat (10) begin +			#10; +			CLK = 1'b1; +			#10; +			CLK = 1'b0; +			#10; +			CLK = 1'b1; +			#10; +			CLK = 1'b0; +		end +		{RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP} = 0; + +		repeat (10000) begin +			clkcycle; +			config_valid = 0; +			while (!config_valid) begin +				A = $urandom; +				ACIN = $urandom; +				B = $urandom; +				BCIN = $urandom; +				C = {$urandom, $urandom}; +				D = $urandom; +				PCIN = {$urandom, $urandom}; + +				{CEA1, CEA2, CEAD, CEALUMODE, CEB1, CEB2, CEC, CECARRYIN, CECTRL} = $urandom | $urandom | $urandom; +				{CED, CEINMODE, CEM, CEP} = $urandom | $urandom | $urandom | $urandom; + +				// Otherwise we can accidentally create illegal configs +				CEINMODE = CECTRL; +				CEALUMODE = CECTRL; + +				{RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP} = $urandom & $urandom & $urandom & $urandom & $urandom & $urandom; +				{ALUMODE, INMODE} = $urandom; +				CARRYINSEL = $urandom & $urandom & $urandom; +				OPMODE = $urandom;  +				if ($urandom & 1'b1) +					OPMODE[3:0] = 4'b0101; // test multiply more than other modes +				{CARRYCASCIN, CARRYIN, MULTSIGNIN} = $urandom; + +				// So few valid options in these modes, just force one valid option +				if (CARRYINSEL == 3'b001) OPMODE = 7'b1010101; +				if (CARRYINSEL == 3'b010) OPMODE = 7'b0001010; +				if (CARRYINSEL == 3'b011) OPMODE = 7'b0011011; +				if (CARRYINSEL == 3'b100) OPMODE = 7'b0110011; +				if (CARRYINSEL == 3'b101) OPMODE = 7'b0011010; +				if (CARRYINSEL == 3'b110) OPMODE = 7'b0010101; +				if (CARRYINSEL == 3'b111) OPMODE = 7'b0100011; + +				drc; +			end +		end + +		if (errcount == 0) begin +			$display("All tests passed."); +			$finish; +		end else begin +			$display("Caught %1d errors.", errcount); +			$stop; +		end +	end + +	DSP48E1 #( +		.ACASCREG           (ACASCREG), +		.ADREG              (ADREG), +		.ALUMODEREG         (ALUMODEREG), +		.AREG               (AREG), +		.AUTORESET_PATDET   (AUTORESET_PATDET), +		.A_INPUT            (A_INPUT), +		.BCASCREG           (BCASCREG), +		.BREG               (BREG), +		.B_INPUT            (B_INPUT), +		.CARRYINREG         (CARRYINREG), +		.CARRYINSELREG      (CARRYINSELREG), +		.CREG               (CREG), +		.DREG               (DREG), +		.INMODEREG          (INMODEREG), +		.MREG               (MREG), +		.OPMODEREG          (OPMODEREG), +		.PREG               (PREG), +		.SEL_MASK           (SEL_MASK), +		.SEL_PATTERN        (SEL_PATTERN), +		.USE_DPORT          (USE_DPORT), +		.USE_MULT           (USE_MULT), +		.USE_PATTERN_DETECT (USE_PATTERN_DETECT), +		.USE_SIMD           (USE_SIMD), +		.MASK               (MASK), +		.PATTERN            (PATTERN), +		.IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED), +		.IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED), +		.IS_CLK_INVERTED    (IS_CLK_INVERTED), +		.IS_INMODE_INVERTED (IS_INMODE_INVERTED), +		.IS_OPMODE_INVERTED (IS_OPMODE_INVERTED) +	) ref ( +		.ACOUT         (REF_ACOUT), +		.BCOUT         (REF_BCOUT), +		.CARRYCASCOUT  (REF_CARRYCASCOUT), +		.CARRYOUT      (REF_CARRYOUT), +		.MULTSIGNOUT   (REF_MULTSIGNOUT), +		.OVERFLOW      (REF_OVERFLOW), +		.P             (REF_P), +		.PATTERNBDETECT(REF_PATTERNBDETECT), +		.PATTERNDETECT (REF_PATTERNDETECT), +		.PCOUT         (REF_PCOUT), +		.UNDERFLOW     (REF_UNDERFLOW), +		.A             (A), +		.ACIN          (ACIN), +		.ALUMODE       (ALUMODE), +		.B             (B), +		.BCIN          (BCIN), +		.C             (C), +		.CARRYCASCIN   (CARRYCASCIN), +		.CARRYINSEL    (CARRYINSEL), +		.CEA1          (CEA1), +		.CEA2          (CEA2), +		.CEAD          (CEAD), +		.CEALUMODE     (CEALUMODE), +		.CEB1          (CEB1), +		.CEB2          (CEB2), +		.CEC           (CEC), +		.CECARRYIN     (CECARRYIN), +		.CECTRL        (CECTRL), +		.CED           (CED), +		.CEINMODE      (CEINMODE), +		.CEM           (CEM), +		.CEP           (CEP), +		.CLK           (CLK), +		.D             (D), +		.INMODE        (INMODE), +		.MULTSIGNIN    (MULTSIGNIN), +		.OPMODE        (OPMODE), +		.PCIN          (PCIN), +		.RSTA          (RSTA), +		.RSTALLCARRYIN (RSTALLCARRYIN), +		.RSTALUMODE    (RSTALUMODE), +		.RSTB          (RSTB), +		.RSTC          (RSTC), +		.RSTCTRL       (RSTCTRL), +		.RSTD          (RSTD), +		.RSTINMODE     (RSTINMODE), +		.RSTM          (RSTM), +		.RSTP          (RSTP) +	); + +	DSP48E1_UUT #( +		.ACASCREG           (ACASCREG), +		.ADREG              (ADREG), +		.ALUMODEREG         (ALUMODEREG), +		.AREG               (AREG), +		.AUTORESET_PATDET   (AUTORESET_PATDET), +		.A_INPUT            (A_INPUT), +		.BCASCREG           (BCASCREG), +		.BREG               (BREG), +		.B_INPUT            (B_INPUT), +		.CARRYINREG         (CARRYINREG), +		.CARRYINSELREG      (CARRYINSELREG), +		.CREG               (CREG), +		.DREG               (DREG), +		.INMODEREG          (INMODEREG), +		.MREG               (MREG), +		.OPMODEREG          (OPMODEREG), +		.PREG               (PREG), +		.SEL_MASK           (SEL_MASK), +		.SEL_PATTERN        (SEL_PATTERN), +		.USE_DPORT          (USE_DPORT), +		.USE_MULT           (USE_MULT), +		.USE_PATTERN_DETECT (USE_PATTERN_DETECT), +		.USE_SIMD           (USE_SIMD), +		.MASK               (MASK), +		.PATTERN            (PATTERN), +		.IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED), +		.IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED), +		.IS_CLK_INVERTED    (IS_CLK_INVERTED), +		.IS_INMODE_INVERTED (IS_INMODE_INVERTED), +		.IS_OPMODE_INVERTED (IS_OPMODE_INVERTED) +	) uut ( +		.ACOUT         (ACOUT), +		.BCOUT         (BCOUT), +		.CARRYCASCOUT  (CARRYCASCOUT), +		.CARRYOUT      (CARRYOUT), +		.MULTSIGNOUT   (MULTSIGNOUT), +		.OVERFLOW      (OVERFLOW), +		.P             (P), +		.PATTERNBDETECT(PATTERNBDETECT), +		.PATTERNDETECT (PATTERNDETECT), +		.PCOUT         (PCOUT), +		.UNDERFLOW     (UNDERFLOW), +		.A             (A), +		.ACIN          (ACIN), +		.ALUMODE       (ALUMODE), +		.B             (B), +		.BCIN          (BCIN), +		.C             (C), +		.CARRYCASCIN   (CARRYCASCIN), +		.CARRYINSEL    (CARRYINSEL), +		.CEA1          (CEA1), +		.CEA2          (CEA2), +		.CEAD          (CEAD), +		.CEALUMODE     (CEALUMODE), +		.CEB1          (CEB1), +		.CEB2          (CEB2), +		.CEC           (CEC), +		.CECARRYIN     (CECARRYIN), +		.CECTRL        (CECTRL), +		.CED           (CED), +		.CEINMODE      (CEINMODE), +		.CEM           (CEM), +		.CEP           (CEP), +		.CLK           (CLK), +		.D             (D), +		.INMODE        (INMODE), +		.MULTSIGNIN    (MULTSIGNIN), +		.OPMODE        (OPMODE), +		.PCIN          (PCIN), +		.RSTA          (RSTA), +		.RSTALLCARRYIN (RSTALLCARRYIN), +		.RSTALUMODE    (RSTALUMODE), +		.RSTB          (RSTB), +		.RSTC          (RSTC), +		.RSTCTRL       (RSTCTRL), +		.RSTD          (RSTD), +		.RSTINMODE     (RSTINMODE), +		.RSTM          (RSTM), +		.RSTP          (RSTP) +	); +endmodule + +module mult_noreg_nopreadd_nocasc; +	testbench #( +		.ACASCREG           (0), +		.ADREG              (0), +		.ALUMODEREG         (0), +		.AREG               (0), +		.AUTORESET_PATDET   ("NO_RESET"), +		.A_INPUT            ("DIRECT"), +		.BCASCREG           (0), +		.BREG               (0), +		.B_INPUT            ("DIRECT"), +		.CARRYINREG         (0), +		.CARRYINSELREG      (0), +		.CREG               (0), +		.DREG               (0), +		.INMODEREG          (0), +		.MREG               (0), +		.OPMODEREG          (0), +		.PREG               (0), +		.SEL_MASK           ("MASK"), +		.SEL_PATTERN        ("PATTERN"), +		.USE_DPORT          ("FALSE"), +		.USE_MULT           ("DYNAMIC"), +		.USE_PATTERN_DETECT ("NO_PATDET"), +		.USE_SIMD           ("ONE48"), +		.MASK               (48'h3FFFFFFFFFFF), +		.PATTERN            (48'h000000000000), +		.IS_ALUMODE_INVERTED(4'b0), +		.IS_CARRYIN_INVERTED(1'b0), +		.IS_CLK_INVERTED    (1'b0), +		.IS_INMODE_INVERTED (5'b0), +		.IS_OPMODE_INVERTED (7'b0) +	) testbench (); +endmodule + +module mult_allreg_nopreadd_nocasc; +	testbench #( +		.ACASCREG           (1), +		.ADREG              (1), +		.ALUMODEREG         (1), +		.AREG               (2), +		.AUTORESET_PATDET   ("NO_RESET"), +		.A_INPUT            ("DIRECT"), +		.BCASCREG           (1), +		.BREG               (2), +		.B_INPUT            ("DIRECT"), +		.CARRYINREG         (1), +		.CARRYINSELREG      (1), +		.CREG               (1), +		.DREG               (1), +		.INMODEREG          (1), +		.MREG               (1), +		.OPMODEREG          (1), +		.PREG               (1), +		.SEL_MASK           ("MASK"), +		.SEL_PATTERN        ("PATTERN"), +		.USE_DPORT          ("FALSE"), +		.USE_MULT           ("DYNAMIC"), +		.USE_PATTERN_DETECT ("NO_PATDET"), +		.USE_SIMD           ("ONE48"), +		.MASK               (48'h3FFFFFFFFFFF), +		.PATTERN            (48'h000000000000), +		.IS_ALUMODE_INVERTED(4'b0), +		.IS_CARRYIN_INVERTED(1'b0), +		.IS_CLK_INVERTED    (1'b0), +		.IS_INMODE_INVERTED (5'b0), +		.IS_OPMODE_INVERTED (7'b0) +	) testbench (); +endmodule + +module mult_noreg_preadd_nocasc; +	testbench #( +		.ACASCREG           (0), +		.ADREG              (0), +		.ALUMODEREG         (0), +		.AREG               (0), +		.AUTORESET_PATDET   ("NO_RESET"), +		.A_INPUT            ("DIRECT"), +		.BCASCREG           (0), +		.BREG               (0), +		.B_INPUT            ("DIRECT"), +		.CARRYINREG         (0), +		.CARRYINSELREG      (0), +		.CREG               (0), +		.DREG               (0), +		.INMODEREG          (0), +		.MREG               (0), +		.OPMODEREG          (0), +		.PREG               (0), +		.SEL_MASK           ("MASK"), +		.SEL_PATTERN        ("PATTERN"), +		.USE_DPORT          ("TRUE"), +		.USE_MULT           ("DYNAMIC"), +		.USE_PATTERN_DETECT ("NO_PATDET"), +		.USE_SIMD           ("ONE48"), +		.MASK               (48'h3FFFFFFFFFFF), +		.PATTERN            (48'h000000000000), +		.IS_ALUMODE_INVERTED(4'b0), +		.IS_CARRYIN_INVERTED(1'b0), +		.IS_CLK_INVERTED    (1'b0), +		.IS_INMODE_INVERTED (5'b0), +		.IS_OPMODE_INVERTED (7'b0) +	) testbench (); +endmodule + +module mult_allreg_preadd_nocasc; +	testbench #( +		.ACASCREG           (1), +		.ADREG              (1), +		.ALUMODEREG         (1), +		.AREG               (2), +		.AUTORESET_PATDET   ("NO_RESET"), +		.A_INPUT            ("DIRECT"), +		.BCASCREG           (1), +		.BREG               (2), +		.B_INPUT            ("DIRECT"), +		.CARRYINREG         (1), +		.CARRYINSELREG      (1), +		.CREG               (1), +		.DREG               (1), +		.INMODEREG          (1), +		.MREG               (1), +		.OPMODEREG          (1), +		.PREG               (1), +		.SEL_MASK           ("MASK"), +		.SEL_PATTERN        ("PATTERN"), +		.USE_DPORT          ("TRUE"), +		.USE_MULT           ("DYNAMIC"), +		.USE_PATTERN_DETECT ("NO_PATDET"), +		.USE_SIMD           ("ONE48"), +		.MASK               (48'h3FFFFFFFFFFF), +		.PATTERN            (48'h000000000000), +		.IS_ALUMODE_INVERTED(4'b0), +		.IS_CARRYIN_INVERTED(1'b0), +		.IS_CLK_INVERTED    (1'b0), +		.IS_INMODE_INVERTED (5'b0), +		.IS_OPMODE_INVERTED (7'b0) +	) testbench (); +endmodule + +module mult_inreg_preadd_nocasc; +	testbench #( +		.ACASCREG           (1), +		.ADREG              (0), +		.ALUMODEREG         (0), +		.AREG               (1), +		.AUTORESET_PATDET   ("NO_RESET"), +		.A_INPUT            ("DIRECT"), +		.BCASCREG           (1), +		.BREG               (1), +		.B_INPUT            ("DIRECT"), +		.CARRYINREG         (0), +		.CARRYINSELREG      (0), +		.CREG               (1), +		.DREG               (1), +		.INMODEREG          (0), +		.MREG               (0), +		.OPMODEREG          (0), +		.PREG               (0), +		.SEL_MASK           ("MASK"), +		.SEL_PATTERN        ("PATTERN"), +		.USE_DPORT          ("TRUE"), +		.USE_MULT           ("DYNAMIC"), +		.USE_PATTERN_DETECT ("NO_PATDET"), +		.USE_SIMD           ("ONE48"), +		.MASK               (48'h3FFFFFFFFFFF), +		.PATTERN            (48'h000000000000), +		.IS_ALUMODE_INVERTED(4'b0), +		.IS_CARRYIN_INVERTED(1'b0), +		.IS_CLK_INVERTED    (1'b0), +		.IS_INMODE_INVERTED (5'b0), +		.IS_OPMODE_INVERTED (7'b0) +	) testbench (); +endmodule + +module simd12_preadd_noreg_nocasc; +	testbench #( +		.ACASCREG           (0), +		.ADREG              (0), +		.ALUMODEREG         (0), +		.AREG               (0), +		.AUTORESET_PATDET   ("NO_RESET"), +		.A_INPUT            ("DIRECT"), +		.BCASCREG           (0), +		.BREG               (0), +		.B_INPUT            ("DIRECT"), +		.CARRYINREG         (0), +		.CARRYINSELREG      (0), +		.CREG               (0), +		.DREG               (0), +		.INMODEREG          (0), +		.MREG               (0), +		.OPMODEREG          (0), +		.PREG               (0), +		.SEL_MASK           ("MASK"), +		.SEL_PATTERN        ("PATTERN"), +		.USE_DPORT          ("TRUE"), +		.USE_MULT           ("DYNAMIC"), +		.USE_PATTERN_DETECT ("NO_PATDET"), +		.USE_SIMD           ("FOUR12"), +		.MASK               (48'h3FFFFFFFFFFF), +		.PATTERN            (48'h000000000000), +		.IS_ALUMODE_INVERTED(4'b0), +		.IS_CARRYIN_INVERTED(1'b0), +		.IS_CLK_INVERTED    (1'b0), +		.IS_INMODE_INVERTED (5'b0), +		.IS_OPMODE_INVERTED (7'b0) +	) testbench (); +endmodule + + +module simd24_preadd_noreg_nocasc; +	testbench #( +		.ACASCREG           (0), +		.ADREG              (0), +		.ALUMODEREG         (0), +		.AREG               (0), +		.AUTORESET_PATDET   ("NO_RESET"), +		.A_INPUT            ("DIRECT"), +		.BCASCREG           (0), +		.BREG               (0), +		.B_INPUT            ("DIRECT"), +		.CARRYINREG         (0), +		.CARRYINSELREG      (0), +		.CREG               (0), +		.DREG               (0), +		.INMODEREG          (0), +		.MREG               (0), +		.OPMODEREG          (0), +		.PREG               (0), +		.SEL_MASK           ("MASK"), +		.SEL_PATTERN        ("PATTERN"), +		.USE_DPORT          ("TRUE"), +		.USE_MULT           ("DYNAMIC"), +		.USE_PATTERN_DETECT ("NO_PATDET"), +		.USE_SIMD           ("TWO24"), +		.MASK               (48'h3FFFFFFFFFFF), +		.PATTERN            (48'h000000000000), +		.IS_ALUMODE_INVERTED(4'b0), +		.IS_CARRYIN_INVERTED(1'b0), +		.IS_CLK_INVERTED    (1'b0), +		.IS_INMODE_INVERTED (5'b0), +		.IS_OPMODE_INVERTED (7'b0) +	) testbench (); +endmodule
\ No newline at end of file diff --git a/techlibs/xilinx/xc6s_ff_map.v b/techlibs/xilinx/xc6s_ff_map.v new file mode 100644 index 000000000..520a67579 --- /dev/null +++ b/techlibs/xilinx/xc6s_ff_map.v @@ -0,0 +1,126 @@ +/* + *  yosys -- Yosys Open SYnthesis Suite + * + *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> + * + *  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. + * + */ + +// ============================================================================ +// FF mapping + +`ifndef _NO_FFS + +module  \$_DFF_N_   (input D, C, output Q); +  parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; +  generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) +    FDSE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .S(1'b0)); +  else +    FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); +  endgenerate +endmodule +module  \$_DFF_P_   (input D, C, output Q); +  parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; +  generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) +    FDSE   #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .S(1'b0)); +  else +    FDRE   #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); +  endgenerate +endmodule + +module  \$_DFFE_NP_ (input D, C, E, output Q); +  parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; +  generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) +    FDSE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E),    .S(1'b0)); +  else +    FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E),    .R(1'b0)); +  endgenerate +endmodule +module  \$_DFFE_PP_ (input D, C, E, output Q); +  parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; +  generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) +    FDSE   #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E),    .S(1'b0)); +  else +    FDRE   #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E),    .R(1'b0)); +  endgenerate +endmodule + +module  \$_DFF_NN0_ (input D, C, R, output Q); +  parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; +  generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) +    $error("Spartan 6 doesn't support FFs with asynchronous reset initialized to 1"); +  else +    FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); +  endgenerate +endmodule +module  \$_DFF_NP0_ (input D, C, R, output Q); +  parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; +  generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) +    $error("Spartan 6 doesn't support FFs with asynchronous reset initialized to 1"); +  else +    FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); +  endgenerate +endmodule +module  \$_DFF_PN0_ (input D, C, R, output Q); +  parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; +  generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) +    $error("Spartan 6 doesn't support FFs with asynchronous reset initialized to 1"); +  else +    FDCE   #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); +  endgenerate +endmodule +module  \$_DFF_PP0_ (input D, C, R, output Q); +  parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; +  generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) +    $error("Spartan 6 doesn't support FFs with asynchronous reset initialized to 1"); +  else +    FDCE   #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); +  endgenerate +endmodule + +module  \$_DFF_NN1_ (input D, C, R, output Q); +  parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; +  generate if (_TECHMAP_WIREINIT_Q_ === 1'b0) +    $error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0"); +  else +    FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); +  endgenerate +endmodule +module  \$_DFF_NP1_ (input D, C, R, output Q); +  parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; +  generate if (_TECHMAP_WIREINIT_Q_ === 1'b0) +    $error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0"); +  else +    FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); +  endgenerate +endmodule +module  \$_DFF_PN1_ (input D, C, R, output Q); +  parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; +  generate if (_TECHMAP_WIREINIT_Q_ === 1'b0) +    $error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0"); +  else +    FDPE   #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); +  endgenerate +endmodule +module  \$_DFF_PP1_ (input D, C, R, output Q); +  parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; +  generate if (_TECHMAP_WIREINIT_Q_ === 1'b0) +    $error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0"); +  else +    FDPE   #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); +  endgenerate +endmodule + +`endif + diff --git a/techlibs/xilinx/xc7_brams_bb.v b/techlibs/xilinx/xc7_brams_bb.v index a43b4b5a1..5b40a457d 100644 --- a/techlibs/xilinx/xc7_brams_bb.v +++ b/techlibs/xilinx/xc7_brams_bb.v @@ -1,3 +1,5 @@ +// Max delays from https://github.com/SymbiFlow/prjxray-db/blob/f8e0364116b2983ac72a3dc8c509ea1cc79e2e3d/artix7/timings/BRAM_L.sdf#L138-L147 +  module RAMB18E1 (  	(* clkbuf_sink *)  	input CLKARDCLK, @@ -21,9 +23,13 @@ module RAMB18E1 (  	input [1:0] WEA,  	input [3:0] WEBWE, +	(* abc_arrival=2454 *)  	output [15:0] DOADO, +	(* abc_arrival=2454 *)  	output [15:0] DOBDO, +	(* abc_arrival=2454 *)  	output [1:0] DOPADOP, +	(* abc_arrival=2454 *)  	output [1:0] DOPBDOP  );  	parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; @@ -147,9 +153,13 @@ module RAMB36E1 (  	input [3:0] WEA,  	input [7:0] WEBWE, +	(* abc_arrival=2454 *)  	output [31:0] DOADO, +	(* abc_arrival=2454 *)  	output [31:0] DOBDO, +	(* abc_arrival=2454 *)  	output [3:0] DOPADOP, +	(* abc_arrival=2454 *)  	output [3:0] DOPBDOP  );  	parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; diff --git a/techlibs/xilinx/xc7_ff_map.v b/techlibs/xilinx/xc7_ff_map.v new file mode 100644 index 000000000..f6197b78b --- /dev/null +++ b/techlibs/xilinx/xc7_ff_map.v @@ -0,0 +1,78 @@ +/* + *  yosys -- Yosys Open SYnthesis Suite + * + *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> + * + *  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. + * + */ + +// ============================================================================ +// FF mapping + +`ifndef _NO_FFS + +module  \$_DFF_N_   (input D, C, output Q); +  parameter _TECHMAP_WIREINIT_Q_ = 1'bx; +  FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); +endmodule +module  \$_DFF_P_   (input D, C, output Q); +  parameter _TECHMAP_WIREINIT_Q_ = 1'bx; +  FDRE   #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); +endmodule + +module  \$_DFFE_NP_ (input D, C, E, output Q); +  parameter _TECHMAP_WIREINIT_Q_ = 1'bx; +  FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E),    .R(1'b0)); +endmodule +module  \$_DFFE_PP_ (input D, C, E, output Q); +  parameter _TECHMAP_WIREINIT_Q_ = 1'bx; +  FDRE   #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E),    .R(1'b0)); +endmodule + +module  \$_DFF_NN0_ (input D, C, R, output Q); +  parameter _TECHMAP_WIREINIT_Q_ = 1'bx; +  FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); +endmodule +module  \$_DFF_NP0_ (input D, C, R, output Q); +  parameter _TECHMAP_WIREINIT_Q_ = 1'bx; +  FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); +endmodule +module  \$_DFF_PN0_ (input D, C, R, output Q); +  parameter _TECHMAP_WIREINIT_Q_ = 1'bx; +  FDCE   #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); +endmodule +module  \$_DFF_PP0_ (input D, C, R, output Q); +  parameter _TECHMAP_WIREINIT_Q_ = 1'bx; +  FDCE   #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); +endmodule + +module  \$_DFF_NN1_ (input D, C, R, output Q); +  parameter _TECHMAP_WIREINIT_Q_ = 1'bx; +  FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); +endmodule +module  \$_DFF_NP1_ (input D, C, R, output Q); +  parameter _TECHMAP_WIREINIT_Q_ = 1'bx; +  FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); +endmodule +module  \$_DFF_PN1_ (input D, C, R, output Q); +  parameter _TECHMAP_WIREINIT_Q_ = 1'bx; +  FDPE   #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); +endmodule +module  \$_DFF_PP1_ (input D, C, R, output Q); +  parameter _TECHMAP_WIREINIT_Q_ = 1'bx; +  FDPE   #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); +endmodule + +`endif + | 
