Changes required for VPR place and route synth_xilinx.
authorKeith Rothman <537074+litghost@users.noreply.github.com>
Fri, 1 Mar 2019 19:21:07 +0000 (11:21 -0800)
committerKeith Rothman <537074+litghost@users.noreply.github.com>
Fri, 1 Mar 2019 20:02:27 +0000 (12:02 -0800)
Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
12 files changed:
manual/command-reference-manual.tex
techlibs/xilinx/Makefile.inc
techlibs/xilinx/arith_map.v
techlibs/xilinx/brams_map.v
techlibs/xilinx/cells_map.v
techlibs/xilinx/cells_sim.v
techlibs/xilinx/cells_xtra.sh
techlibs/xilinx/cells_xtra.v
techlibs/xilinx/ff_map.v [new file with mode: 0644]
techlibs/xilinx/lut2lut.v [deleted file]
techlibs/xilinx/lut_map.v [new file with mode: 0644]
techlibs/xilinx/synth_xilinx.cc

index bed6326e2446a94fabaa79f967e709dce66aa3d9..257bf79868c977d3e5953e9a2c788ddaad72fe1b 100644 (file)
@@ -4244,9 +4244,15 @@ compatible with 7-Series Xilinx devices.
         is omitted if this parameter is not specified.
 
     -vpr
-        generate an output netlist (and BLIF file) suitable for VPR
+        generate an output netlist (and BLIF file) suitable for VPR.
         (this feature is experimental and incomplete)
 
+    -no-brams
+               disable infering of block rams
+
+    -no-drams
+        disable infering of distributed rams
+
     -run <from_label>:<to_label>
         only run the commands between the labels (see below). an empty
         from label is synonymous to 'begin', and empty to label is
@@ -4274,11 +4280,11 @@ The following commands are executed by this synthesis command:
     coarse:
         synth -run coarse
 
-    bram:
+    bram: (only executed when '-no-brams' is not given)
         memory_bram -rules +/xilinx/brams.txt
         techmap -map +/xilinx/brams_map.v
 
-    dram:
+    dram: (only executed when '-no-drams' is not given)
         memory_bram -rules +/xilinx/drams.txt
         techmap -map +/xilinx/drams_map.v
 
@@ -4288,16 +4294,17 @@ The following commands are executed by this synthesis command:
         dffsr2dff
         dff2dffe
         opt -full
-        techmap -map +/techmap.v -map +/xilinx/arith_map.v
+        techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v
         opt -fast
 
     map_luts:
-        abc -luts 2:2,3,6:5,10,20 [-dff]
+        abc -luts 2:2,3,6:5,10,20 [-dff] (without '-vpr' only!)
+        abc -lut 5 [-dff] (with '-vpr' only!)
         clean
 
     map_cells:
         techmap -map +/xilinx/cells_map.v (with -D NO_LUT in vpr mode)
-        dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT
+        dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT
         clean
 
     check:
index 887ea27d9547e5e516f554c1e4a8c9d2b28ddf19..d68f03bb44f3635209e3224be27e87562b2fd8aa 100644 (file)
@@ -28,7 +28,8 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams_bb.v))
 $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams.txt))
 $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v))
 $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v))
-$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut2lut.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v))
 
 $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh))
 $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh))
index 03719659bd65aec8eb2d37412a2e5a57d7fbe189..09a5f07e83d76b2d1b6bdfa3b450ddea750bc833 100644 (file)
@@ -17,6 +17,9 @@
  *
  */
 
+// ============================================================================
+// LCU
+
 (* techmap_celltype = "$lcu" *)
 module _80_xilinx_lcu (P, G, CI, CO);
        parameter WIDTH = 2;
@@ -28,10 +31,78 @@ module _80_xilinx_lcu (P, G, CI, CO);
 
        wire _TECHMAP_FAIL_ = WIDTH <= 2;
 
+       genvar i;
+
+`ifdef _CLB_CARRY
+
+       localparam CARRY4_COUNT = (WIDTH + 3) / 4;
+       localparam MAX_WIDTH    = CARRY4_COUNT * 4;
+       localparam PAD_WIDTH    = MAX_WIDTH - WIDTH;
+
+       wire [MAX_WIDTH-1:0] S  = {{PAD_WIDTH{1'b0}}, P & ~G};
+       wire [MAX_WIDTH-1:0] C  = CO;
+
+       generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice
+
+               // Partially occupied CARRY4
+               if ((i+1)*4 > WIDTH) begin
+
+                       // First one
+                       if (i == 0) begin
+                               CARRY4 carry4_1st_part
+                               (
+                               .CYINIT(CI),
+                               .CI    (1'd0),
+                               .DI    (G [(Y_WIDTH - 1):i*4]),
+                               .S     (S [(Y_WIDTH - 1):i*4]),
+                               .CO    (CO[(Y_WIDTH - 1):i*4]),
+                               );
+                       // Another one
+                       end else begin
+                               CARRY4 carry4_part
+                               (
+                               .CYINIT(1'd0),
+                               .CI    (C [i*4 - 1]),
+                               .DI    (G [(Y_WIDTH - 1):i*4]),
+                               .S     (S [(Y_WIDTH - 1):i*4]),
+                               .CO    (CO[(Y_WIDTH - 1):i*4]),
+                               );
+                       end
+
+               // Fully occupied CARRY4
+               end else begin
+
+                       // First one
+                       if (i == 0) begin
+                               CARRY4 carry4_1st_full
+                               (
+                               .CYINIT(CI),
+                               .CI    (1'd0),
+                               .DI    (G [((i+1)*4 - 1):i*4]),
+                               .S     (S [((i+1)*4 - 1):i*4]),
+                               .CO    (CO[((i+1)*4 - 1):i*4]),
+                               );
+                       // Another one
+                       end else begin
+                               CARRY4 carry4_full
+                               (
+                               .CYINIT(1'd0),
+                               .CI    (C [i*4 - 1]),
+                               .DI    (G [((i+1)*4 - 1):i*4]),
+                               .S     (S [((i+1)*4 - 1):i*4]),
+                               .CO    (CO[((i+1)*4 - 1):i*4]),
+                               );
+                       end
+
+               end
+
+       end endgenerate
+
+`elsif _EXPLICIT_CARRY
+
        wire [WIDTH-1:0] C = {CO, CI};
        wire [WIDTH-1:0] S = P & ~G;
 
-       genvar i;
        generate for (i = 0; i < WIDTH; i = i + 1) begin:slice
                MUXCY muxcy (
                        .CI(C[i]),
@@ -40,8 +111,28 @@ module _80_xilinx_lcu (P, G, CI, CO);
                        .O(CO[i])
                );
        end endgenerate
+
+`else
+
+       wire [WIDTH-1:0] C = {CO, CI};
+       wire [WIDTH-1:0] S = P & ~G;
+
+       generate for (i = 0; i < WIDTH; i = i + 1) begin:slice
+               MUXCY muxcy (
+                       .CI(C[i]),
+                       .DI(G[i]),
+                       .S(S[i]),
+                       .O(CO[i])
+               );
+       end endgenerate
+`endif
+
 endmodule
 
+
+// ============================================================================
+// ALU
+
 (* techmap_celltype = "$alu" *)
 module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
        parameter A_SIGNED = 0;
@@ -49,6 +140,8 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
        parameter A_WIDTH = 1;
        parameter B_WIDTH = 1;
        parameter Y_WIDTH = 1;
+       parameter _TECHMAP_CONSTVAL_CI_ = 0;
+       parameter _TECHMAP_CONSTMSK_CI_ = 0;
 
        input [A_WIDTH-1:0] A;
        input [B_WIDTH-1:0] B;
@@ -66,16 +159,189 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
        wire [Y_WIDTH-1:0] AA = A_buf;
        wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
 
-       wire [Y_WIDTH-1:0] P = AA ^ BB;
-       wire [Y_WIDTH-1:0] G = AA & BB;
-       wire [Y_WIDTH-1:0] C = {CO, CI};
-       wire [Y_WIDTH-1:0] S = P & ~G;
+       genvar i;
+
+`ifdef _CLB_CARRY
+
+       localparam CARRY4_COUNT = (Y_WIDTH + 3) / 4;
+       localparam MAX_WIDTH    = CARRY4_COUNT * 4;
+       localparam PAD_WIDTH    = MAX_WIDTH - Y_WIDTH;
+
+       wire [MAX_WIDTH-1:0] S  = {{PAD_WIDTH{1'b0}}, AA ^ BB};
+       wire [MAX_WIDTH-1:0] DI = {{PAD_WIDTH{1'b0}}, AA & BB};
+
+       wire [MAX_WIDTH-1:0] C  = CO;
 
        genvar i;
+       generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice
+
+               // Partially occupied CARRY4
+               if ((i+1)*4 > Y_WIDTH) begin
+
+                       // First one
+                       if (i == 0) begin
+                               CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_part
+                               (
+                               .CYINIT(CI),
+                               .CI    (1'd0),
+                               .DI    (DI[(Y_WIDTH - 1):i*4]),
+                               .S     (S [(Y_WIDTH - 1):i*4]),
+                               .O     (Y [(Y_WIDTH - 1):i*4]),
+                               .CO    (CO[(Y_WIDTH - 1):i*4])
+                               );
+                       // Another one
+                       end else begin
+                               CARRY4 carry4_part
+                               (
+                               .CYINIT(1'd0),
+                               .CI    (C [i*4 - 1]),
+                               .DI    (DI[(Y_WIDTH - 1):i*4]),
+                               .S     (S [(Y_WIDTH - 1):i*4]),
+                               .O     (Y [(Y_WIDTH - 1):i*4]),
+                               .CO    (CO[(Y_WIDTH - 1):i*4])
+                               );
+                       end
+
+               // Fully occupied CARRY4
+               end else begin
+
+                       // First one
+                       if (i == 0) begin
+                               CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_full
+                               (
+                               .CYINIT(CI),
+                               .CI    (1'd0),
+                               .DI    (DI[((i+1)*4 - 1):i*4]),
+                               .S     (S [((i+1)*4 - 1):i*4]),
+                               .O     (Y [((i+1)*4 - 1):i*4]),
+                               .CO    (CO[((i+1)*4 - 1):i*4])
+                               );
+                       // Another one
+                       end else begin
+                               CARRY4 carry4_full
+                               (
+                               .CYINIT(1'd0),
+                               .CI    (C [i*4 - 1]),
+                               .DI    (DI[((i+1)*4 - 1):i*4]),
+                               .S     (S [((i+1)*4 - 1):i*4]),
+                               .O     (Y [((i+1)*4 - 1):i*4]),
+                               .CO    (CO[((i+1)*4 - 1):i*4])
+                               );
+                       end
+
+               end
+
+       end endgenerate
+
+`elsif _EXPLICIT_CARRY
+
+       wire [Y_WIDTH-1:0] S = AA ^ BB;
+       wire [Y_WIDTH-1:0] DI = AA & BB;
+
+       wire CINIT;
+       // Carry chain.
+       //
+       // VPR requires that the carry chain never hit the fabric.      The CO input
+       // to this techmap is the carry outputs for synthesis, e.g. might hit the
+       // fabric.
+       //
+       // So we maintain two wire sets, CO_CHAIN is the carry that is for VPR,
+       // e.g. off fabric dedicated chain.  CO is the carry outputs that are
+       // available to the fabric.
+       wire [Y_WIDTH-1:0] CO_CHAIN;
+       wire [Y_WIDTH-1:0] C = {CO_CHAIN, CINIT};
+
+       // If carry chain is being initialized to a constant, techmap the constant
+       // source.      Otherwise techmap the fabric source.
+       generate for (i = 0; i < 1; i = i + 1) begin:slice
+               CARRY0 #(.CYINIT_FABRIC(1)) carry(
+                       .CI_INIT(CI),
+                       .DI(DI[0]),
+                       .S(S[0]),
+                       .CO_CHAIN(CO_CHAIN[0]),
+                       .CO_FABRIC(CO[0]),
+                       .O(Y[0])
+               );
+       end endgenerate
+
+       generate for (i = 1; i < Y_WIDTH-1; i = i + 1) begin:slice
+               if(i % 4 == 0) begin
+                       CARRY0 carry (
+                               .CI(C[i]),
+                               .DI(DI[i]),
+                               .S(S[i]),
+                               .CO_CHAIN(CO_CHAIN[i]),
+                               .CO_FABRIC(CO[i]),
+                               .O(Y[i])
+                       );
+               end
+               else
+               begin
+                       CARRY carry (
+                               .CI(C[i]),
+                               .DI(DI[i]),
+                               .S(S[i]),
+                               .CO_CHAIN(CO_CHAIN[i]),
+                               .CO_FABRIC(CO[i]),
+                               .O(Y[i])
+                       );
+               end
+       end endgenerate
+
+       generate for (i = Y_WIDTH-1; i < Y_WIDTH; i = i + 1) begin:slice
+               if(i % 4 == 0) begin
+                       CARRY0 top_of_carry (
+                               .CI(C[i]),
+                               .DI(DI[i]),
+                               .S(S[i]),
+                               .CO_CHAIN(CO_CHAIN[i]),
+                               .O(Y[i])
+                       );
+               end
+               else
+               begin
+                       CARRY top_of_carry (
+                               .CI(C[i]),
+                               .DI(DI[i]),
+                               .S(S[i]),
+                               .CO_CHAIN(CO_CHAIN[i]),
+                               .O(Y[i])
+                       );
+               end
+               // Turns out CO_FABRIC and O both use [ABCD]MUX, so provide
+               // a non-congested path to output the top of the carry chain.
+               // Registering the output of the CARRY block would solve this, but not
+               // all designs do that.
+               if((i+1) % 4 == 0) begin
+                       CARRY0 carry_output (
+                               .CI(CO_CHAIN[i]),
+                               .DI(0),
+                               .S(0),
+                               .O(CO[i])
+                       );
+               end
+               else
+               begin
+                       CARRY carry_output (
+                               .CI(CO_CHAIN[i]),
+                               .DI(0),
+                               .S(0),
+                               .O(CO[i])
+                       );
+               end
+       end endgenerate
+
+`else
+
+       wire [Y_WIDTH-1:0] S = AA ^ BB;
+       wire [Y_WIDTH-1:0] DI = AA & BB;
+
+       wire [Y_WIDTH-1:0] C = {CO, CI};
+
        generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
                MUXCY muxcy (
                        .CI(C[i]),
-                       .DI(G[i]),
+                       .DI(DI[i]),
                        .S(S[i]),
                        .O(CO[i])
                );
@@ -86,6 +352,8 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
                );
        end endgenerate
 
-       assign X = P;
+`endif
+
+       assign X = S;
 endmodule
 
index 7ea49158d27cbf83e99877432eb77539bcc392a4..2a23b2553fa3c8125e0aef0b783068d34c046927 100644 (file)
@@ -30,8 +30,8 @@ module \$__XILINX_RAMB36_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA,
                .RAM_MODE("SDP"),
                .READ_WIDTH_A(72),
                .WRITE_WIDTH_B(72),
-               .WRITE_MODE_A("READ_FIRST"),
-               .WRITE_MODE_B("READ_FIRST"),
+               .WRITE_MODE_A("WRITE_FIRST"),
+               .WRITE_MODE_B("WRITE_FIRST"),
                .IS_CLKARDCLK_INVERTED(!CLKPOL2),
                .IS_CLKBWRCLK_INVERTED(!CLKPOL3),
                `include "brams_init_36.vh"
@@ -95,8 +95,8 @@ module \$__XILINX_RAMB18_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA,
                .RAM_MODE("SDP"),
                .READ_WIDTH_A(36),
                .WRITE_WIDTH_B(36),
-               .WRITE_MODE_A("READ_FIRST"),
-               .WRITE_MODE_B("READ_FIRST"),
+               .WRITE_MODE_A("WRITE_FIRST"),
+               .WRITE_MODE_B("WRITE_FIRST"),
                .IS_CLKARDCLK_INVERTED(!CLKPOL2),
                .IS_CLKBWRCLK_INVERTED(!CLKPOL3),
                `include "brams_init_18.vh"
@@ -171,8 +171,8 @@ module \$__XILINX_RAMB36_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA,
                        .READ_WIDTH_B(CFG_DBITS),
                        .WRITE_WIDTH_A(CFG_DBITS),
                        .WRITE_WIDTH_B(CFG_DBITS),
-                       .WRITE_MODE_A("READ_FIRST"),
-                       .WRITE_MODE_B("READ_FIRST"),
+                       .WRITE_MODE_A("WRITE_FIRST"),
+                       .WRITE_MODE_B("WRITE_FIRST"),
                        .IS_CLKARDCLK_INVERTED(!CLKPOL2),
                        .IS_CLKBWRCLK_INVERTED(!CLKPOL3),
                        `include "brams_init_36.vh"
@@ -209,8 +209,8 @@ module \$__XILINX_RAMB36_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA,
                        .READ_WIDTH_B(CFG_DBITS),
                        .WRITE_WIDTH_A(CFG_DBITS),
                        .WRITE_WIDTH_B(CFG_DBITS),
-                       .WRITE_MODE_A("READ_FIRST"),
-                       .WRITE_MODE_B("READ_FIRST"),
+                       .WRITE_MODE_A("WRITE_FIRST"),
+                       .WRITE_MODE_B("WRITE_FIRST"),
                        .IS_CLKARDCLK_INVERTED(!CLKPOL2),
                        .IS_CLKBWRCLK_INVERTED(!CLKPOL3),
                        `include "brams_init_32.vh"
@@ -285,8 +285,8 @@ module \$__XILINX_RAMB18_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA,
                        .READ_WIDTH_B(CFG_DBITS),
                        .WRITE_WIDTH_A(CFG_DBITS),
                        .WRITE_WIDTH_B(CFG_DBITS),
-                       .WRITE_MODE_A("READ_FIRST"),
-                       .WRITE_MODE_B("READ_FIRST"),
+                       .WRITE_MODE_A("WRITE_FIRST"),
+                       .WRITE_MODE_B("WRITE_FIRST"),
                        .IS_CLKARDCLK_INVERTED(!CLKPOL2),
                        .IS_CLKBWRCLK_INVERTED(!CLKPOL3),
                        `include "brams_init_18.vh"
@@ -323,8 +323,8 @@ module \$__XILINX_RAMB18_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA,
                        .READ_WIDTH_B(CFG_DBITS),
                        .WRITE_WIDTH_A(CFG_DBITS),
                        .WRITE_WIDTH_B(CFG_DBITS),
-                       .WRITE_MODE_A("READ_FIRST"),
-                       .WRITE_MODE_B("READ_FIRST"),
+                       .WRITE_MODE_A("WRITE_FIRST"),
+                       .WRITE_MODE_B("WRITE_FIRST"),
                        .IS_CLKARDCLK_INVERTED(!CLKPOL2),
                        .IS_CLKBWRCLK_INVERTED(!CLKPOL3),
                        `include "brams_init_16.vh"
index 0771be0b95e8cf4200f4a87a4a5fad852dd887aa..d5801c0fceba0d1bf203be8ecfb9c52ded411e00 100644 (file)
@@ -1,86 +1,20 @@
+/*
+ *  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.
+ *
+ */
 
-module  \$_DFF_N_ (input D, C, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_R_INVERTED(|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), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_R_INVERTED(|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 #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_R_INVERTED(|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), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_R_INVERTED(|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 #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule
-module  \$_DFF_NP0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|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), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|1)) _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), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|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 #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|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 #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _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(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|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(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule
-
-`ifndef NO_LUT
-module \$lut (A, Y);
-  parameter WIDTH = 0;
-  parameter LUT = 0;
-
-  input [WIDTH-1:0] A;
-  output Y;
-
-  generate
-    if (WIDTH == 1) begin
-      LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
-        .I0(A[0]));
-    end else
-    if (WIDTH == 2) begin
-      LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
-        .I0(A[0]), .I1(A[1]));
-    end else
-    if (WIDTH == 3) begin
-      LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
-        .I0(A[0]), .I1(A[1]), .I2(A[2]));
-    end else
-    if (WIDTH == 4) begin
-      LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
-        .I0(A[0]), .I1(A[1]), .I2(A[2]),
-        .I3(A[3]));
-    end else
-    if (WIDTH == 5) begin
-      LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
-        .I0(A[0]), .I1(A[1]), .I2(A[2]),
-        .I3(A[3]), .I4(A[4]));
-    end else
-    if (WIDTH == 6) begin
-      LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
-        .I0(A[0]), .I1(A[1]), .I2(A[2]),
-        .I3(A[3]), .I4(A[4]), .I5(A[5]));
-    end else
-    if (WIDTH == 7) begin
-      wire T0, T1;
-      LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0),
-        .I0(A[0]), .I1(A[1]), .I2(A[2]),
-        .I3(A[3]), .I4(A[4]), .I5(A[5]));
-      LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1),
-        .I0(A[0]), .I1(A[1]), .I2(A[2]),
-        .I3(A[3]), .I4(A[4]), .I5(A[5]));
-      MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6]));
-    end else
-    if (WIDTH == 8) begin
-      wire T0, T1, T2, T3, T4, T5;
-      LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0),
-        .I0(A[0]), .I1(A[1]), .I2(A[2]),
-        .I3(A[3]), .I4(A[4]), .I5(A[5]));
-      LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1),
-        .I0(A[0]), .I1(A[1]), .I2(A[2]),
-        .I3(A[3]), .I4(A[4]), .I5(A[5]));
-      LUT6 #(.INIT(LUT[191:128])) fpga_lut_2 (.O(T2),
-        .I0(A[0]), .I1(A[1]), .I2(A[2]),
-        .I3(A[3]), .I4(A[4]), .I5(A[5]));
-      LUT6 #(.INIT(LUT[255:192])) fpga_lut_3 (.O(T3),
-        .I0(A[0]), .I1(A[1]), .I2(A[2]),
-        .I3(A[3]), .I4(A[4]), .I5(A[5]));
-      MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6]));
-      MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6]));
-      MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7]));
-    end else begin
-      wire _TECHMAP_FAIL_ = 1;
-    end
-  endgenerate
-endmodule
-`endif
+// Empty for now
index eba17ac9cb5b4b581248d1727cf7c507270d828a..787b37cc8d6acf1ebb9634a81acb5f7f4a637f79 100644 (file)
@@ -1,3 +1,21 @@
+/*
+ *  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.
+ *
+ */
 
 // See Xilinx UG953 and UG474 for a description of the cell types below.
 // http://www.xilinx.com/support/documentation/user_guides/ug474_7Series_CLB.pdf
@@ -104,56 +122,75 @@ module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S);
   assign CO[3] = S[3] ? CO[2] : DI[3];
 endmodule
 
+`ifdef _EXPLICIT_CARRY
+
+module CARRY0(output CO_CHAIN, CO_FABRIC, O, input CI, CI_INIT, DI, S);
+  parameter CYINIT_FABRIC = 0;
+  wire CI_COMBINE;
+  if(CYINIT_FABRIC) begin
+    assign CI_COMBINE = CI_INIT;
+  end else begin
+    assign CI_COMBINE = CI;
+  end
+  assign CO_CHAIN = S ? CI_COMBINE : DI;
+  assign CO_FABRIC = S ? CI_COMBINE : DI;
+  assign O = S ^ CI_COMBINE;
+endmodule
+
+module CARRY(output CO_CHAIN, CO_FABRIC, O, input CI, DI, S);
+  assign CO_CHAIN = S ? CI : DI;
+  assign CO_FABRIC = S ? CI : DI;
+  assign O = S ^ CI;
+endmodule
+
+`endif
+
 module FDRE (output reg Q, input C, 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;
-  parameter [0:0] IS_R_INVERTED = 1'b0;
   initial Q <= INIT;
-  generate case (|IS_C_INVERTED)
-    1'b0: always @(posedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
-    1'b1: always @(negedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
-  endcase endgenerate
+  always @(posedge C) if (R) Q <= 1'b0; else if(CE) Q <= D;
 endmodule
 
 module FDSE (output reg Q, input C, CE, D, S);
-  parameter [0:0] INIT = 1'b0;
-  parameter [0:0] IS_C_INVERTED = 1'b0;
-  parameter [0:0] IS_D_INVERTED = 1'b0;
-  parameter [0:0] IS_S_INVERTED = 1'b0;
+  parameter [0:0] INIT = 1'b1;
   initial Q <= INIT;
-  generate case (|IS_C_INVERTED)
-    1'b0: always @(posedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
-    1'b1: always @(negedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
-  endcase endgenerate
+  always @(posedge C) if (S) Q <= 1'b1; else if(CE) Q <= D;
 endmodule
 
 module FDCE (output reg Q, input C, 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;
-  parameter [0:0] IS_CLR_INVERTED = 1'b0;
   initial Q <= INIT;
-  generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED})
-    2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
-    2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
-    2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
-    2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
-  endcase endgenerate
+  always @(posedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D;
 endmodule
 
 module FDPE (output reg Q, input C, 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
+
+module FDRE_1 (output reg Q, input C, 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;
-  parameter [0:0] IS_PRE_INVERTED = 1'b0;
   initial Q <= INIT;
-  generate case ({|IS_C_INVERTED, |IS_PRE_INVERTED})
-    2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
-    2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
-    2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
-    2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
-  endcase endgenerate
+  always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D;
+endmodule
+
+module FDSE_1 (output reg Q, input C, 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, input C, 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, input C, 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
 
 module RAM64X1D (
index 0480410f5d5d8df260f3af6e89a0f5b629e17a5f..37c3e5480b9c6d06b80f811ca8e2e4b585cab06e 100644 (file)
@@ -115,7 +115,7 @@ function xtract_cell_decl()
        xtract_cell_decl PS7
        xtract_cell_decl PULLDOWN
        xtract_cell_decl PULLUP
-       xtract_cell_decl RAM128X1D
+       xtract_cell_decl RAM128X1D
        xtract_cell_decl RAM128X1S
        xtract_cell_decl RAM256X1S
        xtract_cell_decl RAM32M
@@ -124,7 +124,7 @@ function xtract_cell_decl()
        xtract_cell_decl RAM32X1S_1
        xtract_cell_decl RAM32X2S
        xtract_cell_decl RAM64M
-       xtract_cell_decl RAM64X1D
+       xtract_cell_decl RAM64X1D
        xtract_cell_decl RAM64X1S
        xtract_cell_decl RAM64X1S_1
        xtract_cell_decl RAM64X2S
index 8d8b91ddcd0c2a1f69ddaf85664630e3132a20a9..995d62e18fe4565912f938a02dba8202643fc218 100644 (file)
@@ -3695,6 +3695,25 @@ module RAM128X1S (...);
     input A0, A1, A2, A3, A4, A5, A6, D, WCLK, WE;
 endmodule
 
+module RAM128X1D (
+  output       DPO, SPO,
+  input        D, WCLK, WE,
+  input  [6:0] A, DPRA
+);
+       parameter [127:0] INIT = 128'bx;
+       parameter IS_WCLK_INVERTED = 0;
+endmodule
+
+module RAM64X1D (
+  output DPO, SPO,
+  input  D, WCLK, WE,
+  input  A0, A1, A2, A3, A4, A5,
+  input  DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
+);
+       parameter [63:0] INIT = 64'bx;
+       parameter IS_WCLK_INVERTED = 0;
+endmodule
+
 module RAM256X1S (...);
     parameter [255:0] INIT = 256'h0;
     parameter [0:0] IS_WCLK_INVERTED = 1'b0;
diff --git a/techlibs/xilinx/ff_map.v b/techlibs/xilinx/ff_map.v
new file mode 100644 (file)
index 0000000..13beaa6
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  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(|0)) _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(|0)) _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(|0)) _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(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule
+
+`endif
+
diff --git a/techlibs/xilinx/lut2lut.v b/techlibs/xilinx/lut2lut.v
deleted file mode 100644 (file)
index 061ad20..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-module LUT1(output O, input I0);
-  parameter [1:0] INIT = 0;
-  \$lut #(
-    .WIDTH(1),
-    .LUT(INIT)
-  ) _TECHMAP_REPLACE_ (
-    .A(I0),
-    .Y(O)
-  );
-endmodule
-
-module LUT2(output O, input I0, I1);
-  parameter [3:0] INIT = 0;
-  \$lut #(
-    .WIDTH(2),
-    .LUT(INIT)
-  ) _TECHMAP_REPLACE_ (
-    .A({I1, I0}),
-    .Y(O)
-  );
-endmodule
-
-module LUT3(output O, input I0, I1, I2);
-  parameter [7:0] INIT = 0;
-  \$lut #(
-    .WIDTH(3),
-    .LUT(INIT)
-  ) _TECHMAP_REPLACE_ (
-    .A({I2, I1, I0}),
-    .Y(O)
-  );
-endmodule
-
-module LUT4(output O, input I0, I1, I2, I3);
-  parameter [15:0] INIT = 0;
-  \$lut #(
-    .WIDTH(4),
-    .LUT(INIT)
-  ) _TECHMAP_REPLACE_ (
-    .A({I3, I2, I1, I0}),
-    .Y(O)
-  );
-endmodule
-
-module LUT5(output O, input I0, I1, I2, I3, I4);
-  parameter [31:0] INIT = 0;
-  \$lut #(
-    .WIDTH(5),
-    .LUT(INIT)
-  ) _TECHMAP_REPLACE_ (
-    .A({I4, I3, I2, I1, I0}),
-    .Y(O)
-  );
-endmodule
-
-module LUT6(output O, input I0, I1, I2, I3, I4, I5);
-  parameter [63:0] INIT = 0;
-  \$lut #(
-    .WIDTH(6),
-    .LUT(INIT)
-  ) _TECHMAP_REPLACE_ (
-    .A({I5, I4, I3, I2, I1, I0}),
-    .Y(O)
-  );
-endmodule
diff --git a/techlibs/xilinx/lut_map.v b/techlibs/xilinx/lut_map.v
new file mode 100644 (file)
index 0000000..d07c59d
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *  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.
+ *
+ */
+
+// ============================================================================
+// LUT mapping
+
+`ifndef _NO_LUTS
+
+module \$lut (A, Y);
+  parameter WIDTH = 0;
+  parameter LUT = 0;
+
+  input [WIDTH-1:0] A;
+  output Y;
+
+  generate
+    if (WIDTH == 1) begin
+      LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+        .I0(A[0]));
+    end else
+    if (WIDTH == 2) begin
+      LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+        .I0(A[0]), .I1(A[1]));
+    end else
+    if (WIDTH == 3) begin
+      LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+        .I0(A[0]), .I1(A[1]), .I2(A[2]));
+    end else
+    if (WIDTH == 4) begin
+      LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+        .I0(A[0]), .I1(A[1]), .I2(A[2]),
+        .I3(A[3]));
+    end else
+    if (WIDTH == 5) begin
+      LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+        .I0(A[0]), .I1(A[1]), .I2(A[2]),
+        .I3(A[3]), .I4(A[4]));
+    end else
+    if (WIDTH == 6) begin
+      LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+        .I0(A[0]), .I1(A[1]), .I2(A[2]),
+        .I3(A[3]), .I4(A[4]), .I5(A[5]));
+    end else
+    if (WIDTH == 7) begin
+      wire T0, T1;
+      LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0),
+        .I0(A[0]), .I1(A[1]), .I2(A[2]),
+        .I3(A[3]), .I4(A[4]), .I5(A[5]));
+      LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1),
+        .I0(A[0]), .I1(A[1]), .I2(A[2]),
+        .I3(A[3]), .I4(A[4]), .I5(A[5]));
+      MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6]));
+    end else
+    if (WIDTH == 8) begin
+      wire T0, T1, T2, T3, T4, T5;
+      LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0),
+        .I0(A[0]), .I1(A[1]), .I2(A[2]),
+        .I3(A[3]), .I4(A[4]), .I5(A[5]));
+      LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1),
+        .I0(A[0]), .I1(A[1]), .I2(A[2]),
+        .I3(A[3]), .I4(A[4]), .I5(A[5]));
+      LUT6 #(.INIT(LUT[191:128])) fpga_lut_2 (.O(T2),
+        .I0(A[0]), .I1(A[1]), .I2(A[2]),
+        .I3(A[3]), .I4(A[4]), .I5(A[5]));
+      LUT6 #(.INIT(LUT[255:192])) fpga_lut_3 (.O(T3),
+        .I0(A[0]), .I1(A[1]), .I2(A[2]),
+        .I3(A[3]), .I4(A[4]), .I5(A[5]));
+      MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6]));
+      MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6]));
+      MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7]));
+    end else begin
+      wire _TECHMAP_FAIL_ = 1;
+    end
+  endgenerate
+endmodule
+
+`endif
+
index 6c11d885d53a1aeedbe62c77963e95e51b1614af..60cfde604ca29cfc7b264073f332456e562c9d6f 100644 (file)
@@ -63,6 +63,12 @@ struct SynthXilinxPass : public Pass
                log("        generate an output netlist (and BLIF file) suitable for VPR\n");
                log("        (this feature is experimental and incomplete)\n");
                log("\n");
+               log("    -no-brams\n");
+               log("        disable infering of block rams\n");
+               log("\n");
+               log("    -no-drams\n");
+               log("        disable infering of distributed rams\n");
+               log("\n");
                log("    -run <from_label>:<to_label>\n");
                log("        only run the commands between the labels (see below). an empty\n");
                log("        from label is synonymous to 'begin', and empty to label is\n");
@@ -90,11 +96,11 @@ struct SynthXilinxPass : public Pass
                log("    coarse:\n");
                log("        synth -run coarse\n");
                log("\n");
-               log("    bram:\n");
+               log("    bram: (only executed when '-no-brams' is not given)\n");
                log("        memory_bram -rules +/xilinx/brams.txt\n");
                log("        techmap -map +/xilinx/brams_map.v\n");
                log("\n");
-               log("    dram:\n");
+               log("    dram: (only executed when '-no-drams' is not given)\n");
                log("        memory_bram -rules +/xilinx/drams.txt\n");
                log("        techmap -map +/xilinx/drams_map.v\n");
                log("\n");
@@ -104,16 +110,17 @@ 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("        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");
-               log("        abc -luts 2:2,3,6:5,10,20 [-dff]\n");
+               log("        abc -luts 2:2,3,6:5,10,20 [-dff] (without '-vpr' only!)\n");
+               log("        abc -lut 5 [-dff] (with '-vpr' only!)\n");
                log("        clean\n");
                log("\n");
                log("    map_cells:\n");
-               log("        techmap -map +/xilinx/cells_map.v (with -D NO_LUT in vpr mode)\n");
-               log("        dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT\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("        clean\n");
                log("\n");
                log("    check:\n");
@@ -137,6 +144,8 @@ struct SynthXilinxPass : public Pass
                bool flatten = false;
                bool retime = false;
                bool vpr = false;
+               bool noBrams = false;
+               bool noDrams = false;
 
                size_t argidx;
                for (argidx = 1; argidx < args.size(); argidx++)
@@ -173,6 +182,14 @@ struct SynthXilinxPass : public Pass
                                vpr = true;
                                continue;
                        }
+                       if (args[argidx] == "-no-brams") {
+                               noBrams = true;
+                               continue;
+                       }
+                       if (args[argidx] == "-no-drams") {
+                               noDrams = true;
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
@@ -187,9 +204,18 @@ struct SynthXilinxPass : public Pass
 
                if (check_label(active, run_from, run_to, "begin"))
                {
-                       Pass::call(design, "read_verilog -lib +/xilinx/cells_sim.v");
+                       if (vpr) {
+                               Pass::call(design, "read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v");
+                       } else {
+                               Pass::call(design, "read_verilog -lib +/xilinx/cells_sim.v");
+                       }
+
                        Pass::call(design, "read_verilog -lib +/xilinx/cells_xtra.v");
-                       Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v");
+
+                       if (!noBrams) {
+                               Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v");
+                       }
+
                        Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str()));
                }
 
@@ -206,14 +232,18 @@ struct SynthXilinxPass : public Pass
 
                if (check_label(active, run_from, run_to, "bram"))
                {
-                       Pass::call(design, "memory_bram -rules +/xilinx/brams.txt");
-                       Pass::call(design, "techmap -map +/xilinx/brams_map.v");
+                       if (!noBrams) {
+                               Pass::call(design, "memory_bram -rules +/xilinx/brams.txt");
+                               Pass::call(design, "techmap -map +/xilinx/brams_map.v");
+                       }
                }
 
                if (check_label(active, run_from, run_to, "dram"))
                {
-                       Pass::call(design, "memory_bram -rules +/xilinx/drams.txt");
-                       Pass::call(design, "techmap -map +/xilinx/drams_map.v");
+                       if (!noDrams) {
+                               Pass::call(design, "memory_bram -rules +/xilinx/drams.txt");
+                               Pass::call(design, "techmap -map +/xilinx/drams_map.v");
+                       }
                }
 
                if (check_label(active, run_from, run_to, "fine"))
@@ -223,7 +253,14 @@ struct SynthXilinxPass : public Pass
                        Pass::call(design, "dffsr2dff");
                        Pass::call(design, "dff2dffe");
                        Pass::call(design, "opt -full");
-                       Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v");
+
+                       if (vpr) {
+                               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 -map +/xilinx/ff_map.v");
+                       }
+
+                       Pass::call(design, "hierarchy -check");
                        Pass::call(design, "opt -fast");
                }
 
@@ -231,14 +268,13 @@ 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");
                }
 
                if (check_label(active, run_from, run_to, "map_cells"))
                {
                        Pass::call(design, "techmap -map +/xilinx/cells_map.v");
-                       if (vpr)
-                           Pass::call(design, "techmap -map +/xilinx/lut2lut.v");
-                       Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT");
+                       Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT");
                        Pass::call(design, "clean");
                }