aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/xilinx
diff options
context:
space:
mode:
authorKeith Rothman <537074+litghost@users.noreply.github.com>2019-03-01 11:21:07 -0800
committerKeith Rothman <537074+litghost@users.noreply.github.com>2019-03-01 12:02:27 -0800
commit3090951d54859c331d28232481361bb9c26b3d48 (patch)
tree24973f1f4bea3abbca07c82729086423a101f495 /techlibs/xilinx
parent66fd6396d4795ea9559cbbd1560387e7d7e79596 (diff)
downloadyosys-3090951d54859c331d28232481361bb9c26b3d48.tar.gz
yosys-3090951d54859c331d28232481361bb9c26b3d48.tar.bz2
yosys-3090951d54859c331d28232481361bb9c26b3d48.zip
Changes required for VPR place and route synth_xilinx.
Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
Diffstat (limited to 'techlibs/xilinx')
-rw-r--r--techlibs/xilinx/Makefile.inc3
-rw-r--r--techlibs/xilinx/arith_map.v282
-rw-r--r--techlibs/xilinx/brams_map.v24
-rw-r--r--techlibs/xilinx/cells_map.v104
-rw-r--r--techlibs/xilinx/cells_sim.v103
-rw-r--r--techlibs/xilinx/cells_xtra.sh4
-rw-r--r--techlibs/xilinx/cells_xtra.v19
-rw-r--r--techlibs/xilinx/ff_map.v42
-rw-r--r--techlibs/xilinx/lut2lut.v65
-rw-r--r--techlibs/xilinx/lut_map.v94
-rw-r--r--techlibs/xilinx/synth_xilinx.cc68
11 files changed, 587 insertions, 221 deletions
diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc
index 887ea27d9..d68f03bb4 100644
--- a/techlibs/xilinx/Makefile.inc
+++ b/techlibs/xilinx/Makefile.inc
@@ -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))
diff --git a/techlibs/xilinx/arith_map.v b/techlibs/xilinx/arith_map.v
index 03719659b..09a5f07e8 100644
--- a/techlibs/xilinx/arith_map.v
+++ b/techlibs/xilinx/arith_map.v
@@ -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
diff --git a/techlibs/xilinx/brams_map.v b/techlibs/xilinx/brams_map.v
index 7ea49158d..2a23b2553 100644
--- a/techlibs/xilinx/brams_map.v
+++ b/techlibs/xilinx/brams_map.v
@@ -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"
diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v
index 0771be0b9..d5801c0fc 100644
--- a/techlibs/xilinx/cells_map.v
+++ b/techlibs/xilinx/cells_map.v
@@ -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
diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v
index eba17ac9c..787b37cc8 100644
--- a/techlibs/xilinx/cells_sim.v
+++ b/techlibs/xilinx/cells_sim.v
@@ -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 (
diff --git a/techlibs/xilinx/cells_xtra.sh b/techlibs/xilinx/cells_xtra.sh
index 0480410f5..37c3e5480 100644
--- a/techlibs/xilinx/cells_xtra.sh
+++ b/techlibs/xilinx/cells_xtra.sh
@@ -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
diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v
index 8d8b91ddc..995d62e18 100644
--- a/techlibs/xilinx/cells_xtra.v
+++ b/techlibs/xilinx/cells_xtra.v
@@ -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
index 000000000..13beaa6ae
--- /dev/null
+++ b/techlibs/xilinx/ff_map.v
@@ -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
index 061ad2041..000000000
--- a/techlibs/xilinx/lut2lut.v
+++ /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
index 000000000..d07c59dee
--- /dev/null
+++ b/techlibs/xilinx/lut_map.v
@@ -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
+
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc
index 6c11d885d..60cfde604 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -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");
}