Changes required for VPR place and route synth_xilinx.

Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
Keith Rothman 2019-03-01 11:21:07 -08:00
parent 66fd6396d4
commit 3090951d54
12 changed files with 601 additions and 228 deletions

View File

@ -4244,9 +4244,15 @@ compatible with 7-Series Xilinx devices.
is omitted if this parameter is not specified. is omitted if this parameter is not specified.
-vpr -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) (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> -run <from_label>:<to_label>
only run the commands between the labels (see below). an empty only run the commands between the labels (see below). an empty
from label is synonymous to 'begin', and empty to label is 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: coarse:
synth -run coarse synth -run coarse
bram: bram: (only executed when '-no-brams' is not given)
memory_bram -rules +/xilinx/brams.txt memory_bram -rules +/xilinx/brams.txt
techmap -map +/xilinx/brams_map.v techmap -map +/xilinx/brams_map.v
dram: dram: (only executed when '-no-drams' is not given)
memory_bram -rules +/xilinx/drams.txt memory_bram -rules +/xilinx/drams.txt
techmap -map +/xilinx/drams_map.v techmap -map +/xilinx/drams_map.v
@ -4288,16 +4294,17 @@ The following commands are executed by this synthesis command:
dffsr2dff dffsr2dff
dff2dffe dff2dffe
opt -full 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 opt -fast
map_luts: 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 clean
map_cells: map_cells:
techmap -map +/xilinx/cells_map.v (with -D NO_LUT in vpr mode) 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 clean
check: check:

View 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.txt))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v)) $(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/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_36.vh))
$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh)) $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh))

View File

@ -17,6 +17,9 @@
* *
*/ */
// ============================================================================
// LCU
(* techmap_celltype = "$lcu" *) (* techmap_celltype = "$lcu" *)
module _80_xilinx_lcu (P, G, CI, CO); module _80_xilinx_lcu (P, G, CI, CO);
parameter WIDTH = 2; parameter WIDTH = 2;
@ -28,10 +31,78 @@ module _80_xilinx_lcu (P, G, CI, CO);
wire _TECHMAP_FAIL_ = WIDTH <= 2; 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] C = {CO, CI};
wire [WIDTH-1:0] S = P & ~G; wire [WIDTH-1:0] S = P & ~G;
genvar i;
generate for (i = 0; i < WIDTH; i = i + 1) begin:slice generate for (i = 0; i < WIDTH; i = i + 1) begin:slice
MUXCY muxcy ( MUXCY muxcy (
.CI(C[i]), .CI(C[i]),
@ -40,8 +111,28 @@ module _80_xilinx_lcu (P, G, CI, CO);
.O(CO[i]) .O(CO[i])
); );
end endgenerate 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 endmodule
// ============================================================================
// ALU
(* techmap_celltype = "$alu" *) (* techmap_celltype = "$alu" *)
module _80_xilinx_alu (A, B, CI, BI, X, Y, CO); module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
parameter A_SIGNED = 0; parameter A_SIGNED = 0;
@ -49,6 +140,8 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
parameter A_WIDTH = 1; parameter A_WIDTH = 1;
parameter B_WIDTH = 1; parameter B_WIDTH = 1;
parameter Y_WIDTH = 1; parameter Y_WIDTH = 1;
parameter _TECHMAP_CONSTVAL_CI_ = 0;
parameter _TECHMAP_CONSTMSK_CI_ = 0;
input [A_WIDTH-1:0] A; input [A_WIDTH-1:0] A;
input [B_WIDTH-1:0] B; 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] AA = A_buf;
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
wire [Y_WIDTH-1:0] P = AA ^ BB; genvar i;
wire [Y_WIDTH-1:0] G = AA & BB;
wire [Y_WIDTH-1:0] C = {CO, CI}; `ifdef _CLB_CARRY
wire [Y_WIDTH-1:0] S = P & ~G;
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; 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 generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
MUXCY muxcy ( MUXCY muxcy (
.CI(C[i]), .CI(C[i]),
.DI(G[i]), .DI(DI[i]),
.S(S[i]), .S(S[i]),
.O(CO[i]) .O(CO[i])
); );
@ -86,6 +352,8 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
); );
end endgenerate end endgenerate
assign X = P; `endif
assign X = S;
endmodule endmodule

View File

@ -30,8 +30,8 @@ module \$__XILINX_RAMB36_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA,
.RAM_MODE("SDP"), .RAM_MODE("SDP"),
.READ_WIDTH_A(72), .READ_WIDTH_A(72),
.WRITE_WIDTH_B(72), .WRITE_WIDTH_B(72),
.WRITE_MODE_A("READ_FIRST"), .WRITE_MODE_A("WRITE_FIRST"),
.WRITE_MODE_B("READ_FIRST"), .WRITE_MODE_B("WRITE_FIRST"),
.IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKARDCLK_INVERTED(!CLKPOL2),
.IS_CLKBWRCLK_INVERTED(!CLKPOL3), .IS_CLKBWRCLK_INVERTED(!CLKPOL3),
`include "brams_init_36.vh" `include "brams_init_36.vh"
@ -95,8 +95,8 @@ module \$__XILINX_RAMB18_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA,
.RAM_MODE("SDP"), .RAM_MODE("SDP"),
.READ_WIDTH_A(36), .READ_WIDTH_A(36),
.WRITE_WIDTH_B(36), .WRITE_WIDTH_B(36),
.WRITE_MODE_A("READ_FIRST"), .WRITE_MODE_A("WRITE_FIRST"),
.WRITE_MODE_B("READ_FIRST"), .WRITE_MODE_B("WRITE_FIRST"),
.IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKARDCLK_INVERTED(!CLKPOL2),
.IS_CLKBWRCLK_INVERTED(!CLKPOL3), .IS_CLKBWRCLK_INVERTED(!CLKPOL3),
`include "brams_init_18.vh" `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), .READ_WIDTH_B(CFG_DBITS),
.WRITE_WIDTH_A(CFG_DBITS), .WRITE_WIDTH_A(CFG_DBITS),
.WRITE_WIDTH_B(CFG_DBITS), .WRITE_WIDTH_B(CFG_DBITS),
.WRITE_MODE_A("READ_FIRST"), .WRITE_MODE_A("WRITE_FIRST"),
.WRITE_MODE_B("READ_FIRST"), .WRITE_MODE_B("WRITE_FIRST"),
.IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKARDCLK_INVERTED(!CLKPOL2),
.IS_CLKBWRCLK_INVERTED(!CLKPOL3), .IS_CLKBWRCLK_INVERTED(!CLKPOL3),
`include "brams_init_36.vh" `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), .READ_WIDTH_B(CFG_DBITS),
.WRITE_WIDTH_A(CFG_DBITS), .WRITE_WIDTH_A(CFG_DBITS),
.WRITE_WIDTH_B(CFG_DBITS), .WRITE_WIDTH_B(CFG_DBITS),
.WRITE_MODE_A("READ_FIRST"), .WRITE_MODE_A("WRITE_FIRST"),
.WRITE_MODE_B("READ_FIRST"), .WRITE_MODE_B("WRITE_FIRST"),
.IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKARDCLK_INVERTED(!CLKPOL2),
.IS_CLKBWRCLK_INVERTED(!CLKPOL3), .IS_CLKBWRCLK_INVERTED(!CLKPOL3),
`include "brams_init_32.vh" `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), .READ_WIDTH_B(CFG_DBITS),
.WRITE_WIDTH_A(CFG_DBITS), .WRITE_WIDTH_A(CFG_DBITS),
.WRITE_WIDTH_B(CFG_DBITS), .WRITE_WIDTH_B(CFG_DBITS),
.WRITE_MODE_A("READ_FIRST"), .WRITE_MODE_A("WRITE_FIRST"),
.WRITE_MODE_B("READ_FIRST"), .WRITE_MODE_B("WRITE_FIRST"),
.IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKARDCLK_INVERTED(!CLKPOL2),
.IS_CLKBWRCLK_INVERTED(!CLKPOL3), .IS_CLKBWRCLK_INVERTED(!CLKPOL3),
`include "brams_init_18.vh" `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), .READ_WIDTH_B(CFG_DBITS),
.WRITE_WIDTH_A(CFG_DBITS), .WRITE_WIDTH_A(CFG_DBITS),
.WRITE_WIDTH_B(CFG_DBITS), .WRITE_WIDTH_B(CFG_DBITS),
.WRITE_MODE_A("READ_FIRST"), .WRITE_MODE_A("WRITE_FIRST"),
.WRITE_MODE_B("READ_FIRST"), .WRITE_MODE_B("WRITE_FIRST"),
.IS_CLKARDCLK_INVERTED(!CLKPOL2), .IS_CLKARDCLK_INVERTED(!CLKPOL2),
.IS_CLKBWRCLK_INVERTED(!CLKPOL3), .IS_CLKBWRCLK_INVERTED(!CLKPOL3),
`include "brams_init_16.vh" `include "brams_init_16.vh"

View 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 // Empty for now
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

View 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. // 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 // 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]; assign CO[3] = S[3] ? CO[2] : DI[3];
endmodule 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); module FDRE (output reg Q, input C, CE, D, R);
parameter [0:0] INIT = 1'b0; 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; initial Q <= INIT;
generate case (|IS_C_INVERTED) always @(posedge C) if (R) Q <= 1'b0; else if(CE) Q <= D;
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
endmodule endmodule
module FDSE (output reg Q, input C, CE, D, S); module FDSE (output reg Q, input C, CE, D, S);
parameter [0:0] INIT = 1'b0; parameter [0:0] INIT = 1'b1;
parameter [0:0] IS_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0;
parameter [0:0] IS_S_INVERTED = 1'b0;
initial Q <= INIT; initial Q <= INIT;
generate case (|IS_C_INVERTED) always @(posedge C) if (S) Q <= 1'b1; else if(CE) Q <= D;
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
endmodule endmodule
module FDCE (output reg Q, input C, CE, D, CLR); module FDCE (output reg Q, input C, CE, D, CLR);
parameter [0:0] INIT = 1'b0; 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; initial Q <= INIT;
generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED}) always @(posedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D;
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
endmodule endmodule
module FDPE (output reg Q, input C, CE, D, PRE); module FDPE (output reg Q, input C, CE, D, PRE);
parameter [0:0] INIT = 1'b0; parameter [0:0] INIT = 1'b1;
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; initial Q <= INIT;
generate case ({|IS_C_INVERTED, |IS_PRE_INVERTED}) always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;
2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; endmodule
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; module FDRE_1 (output reg Q, input C, CE, D, R);
2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED; parameter [0:0] INIT = 1'b0;
endcase endgenerate initial Q <= INIT;
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 endmodule
module RAM64X1D ( module RAM64X1D (

View File

@ -115,7 +115,7 @@ function xtract_cell_decl()
xtract_cell_decl PS7 xtract_cell_decl PS7
xtract_cell_decl PULLDOWN xtract_cell_decl PULLDOWN
xtract_cell_decl PULLUP xtract_cell_decl PULLUP
# xtract_cell_decl RAM128X1D xtract_cell_decl RAM128X1D
xtract_cell_decl RAM128X1S xtract_cell_decl RAM128X1S
xtract_cell_decl RAM256X1S xtract_cell_decl RAM256X1S
xtract_cell_decl RAM32M xtract_cell_decl RAM32M
@ -124,7 +124,7 @@ function xtract_cell_decl()
xtract_cell_decl RAM32X1S_1 xtract_cell_decl RAM32X1S_1
xtract_cell_decl RAM32X2S xtract_cell_decl RAM32X2S
xtract_cell_decl RAM64M xtract_cell_decl RAM64M
# xtract_cell_decl RAM64X1D xtract_cell_decl RAM64X1D
xtract_cell_decl RAM64X1S xtract_cell_decl RAM64X1S
xtract_cell_decl RAM64X1S_1 xtract_cell_decl RAM64X1S_1
xtract_cell_decl RAM64X2S xtract_cell_decl RAM64X2S

View File

@ -3695,6 +3695,25 @@ module RAM128X1S (...);
input A0, A1, A2, A3, A4, A5, A6, D, WCLK, WE; input A0, A1, A2, A3, A4, A5, A6, D, WCLK, WE;
endmodule 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 (...); module RAM256X1S (...);
parameter [255:0] INIT = 256'h0; parameter [255:0] INIT = 256'h0;
parameter [0:0] IS_WCLK_INVERTED = 1'b0; parameter [0:0] IS_WCLK_INVERTED = 1'b0;

42
techlibs/xilinx/ff_map.v Normal file
View File

@ -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

View File

@ -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

94
techlibs/xilinx/lut_map.v Normal file
View File

@ -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

View File

@ -63,6 +63,12 @@ struct SynthXilinxPass : public Pass
log(" generate an output netlist (and BLIF file) suitable for VPR\n"); log(" generate an output netlist (and BLIF file) suitable for VPR\n");
log(" (this feature is experimental and incomplete)\n"); log(" (this feature is experimental and incomplete)\n");
log("\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(" -run <from_label>:<to_label>\n");
log(" only run the commands between the labels (see below). an empty\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"); 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(" coarse:\n");
log(" synth -run coarse\n"); log(" synth -run coarse\n");
log("\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(" memory_bram -rules +/xilinx/brams.txt\n");
log(" techmap -map +/xilinx/brams_map.v\n"); log(" techmap -map +/xilinx/brams_map.v\n");
log("\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(" memory_bram -rules +/xilinx/drams.txt\n");
log(" techmap -map +/xilinx/drams_map.v\n"); log(" techmap -map +/xilinx/drams_map.v\n");
log("\n"); log("\n");
@ -104,16 +110,17 @@ struct SynthXilinxPass : public Pass
log(" dffsr2dff\n"); log(" dffsr2dff\n");
log(" dff2dffe\n"); log(" dff2dffe\n");
log(" opt -full\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(" opt -fast\n");
log("\n"); log("\n");
log(" map_luts:\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(" clean\n");
log("\n"); log("\n");
log(" map_cells:\n"); log(" map_cells:\n");
log(" techmap -map +/xilinx/cells_map.v (with -D NO_LUT in vpr mode)\n"); log(" techmap -map +/xilinx/cells_map.v\n");
log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT\n"); log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT\n");
log(" clean\n"); log(" clean\n");
log("\n"); log("\n");
log(" check:\n"); log(" check:\n");
@ -137,6 +144,8 @@ struct SynthXilinxPass : public Pass
bool flatten = false; bool flatten = false;
bool retime = false; bool retime = false;
bool vpr = false; bool vpr = false;
bool noBrams = false;
bool noDrams = false;
size_t argidx; size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) for (argidx = 1; argidx < args.size(); argidx++)
@ -173,6 +182,14 @@ struct SynthXilinxPass : public Pass
vpr = true; vpr = true;
continue; continue;
} }
if (args[argidx] == "-no-brams") {
noBrams = true;
continue;
}
if (args[argidx] == "-no-drams") {
noDrams = true;
continue;
}
break; break;
} }
extra_args(args, argidx, design); extra_args(args, argidx, design);
@ -187,9 +204,18 @@ struct SynthXilinxPass : public Pass
if (check_label(active, run_from, run_to, "begin")) if (check_label(active, run_from, run_to, "begin"))
{ {
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_sim.v");
}
Pass::call(design, "read_verilog -lib +/xilinx/cells_xtra.v"); Pass::call(design, "read_verilog -lib +/xilinx/cells_xtra.v");
if (!noBrams) {
Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v"); Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v");
}
Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str())); Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str()));
} }
@ -206,15 +232,19 @@ struct SynthXilinxPass : public Pass
if (check_label(active, run_from, run_to, "bram")) if (check_label(active, run_from, run_to, "bram"))
{ {
if (!noBrams) {
Pass::call(design, "memory_bram -rules +/xilinx/brams.txt"); Pass::call(design, "memory_bram -rules +/xilinx/brams.txt");
Pass::call(design, "techmap -map +/xilinx/brams_map.v"); Pass::call(design, "techmap -map +/xilinx/brams_map.v");
} }
}
if (check_label(active, run_from, run_to, "dram")) if (check_label(active, run_from, run_to, "dram"))
{ {
if (!noDrams) {
Pass::call(design, "memory_bram -rules +/xilinx/drams.txt"); Pass::call(design, "memory_bram -rules +/xilinx/drams.txt");
Pass::call(design, "techmap -map +/xilinx/drams_map.v"); Pass::call(design, "techmap -map +/xilinx/drams_map.v");
} }
}
if (check_label(active, run_from, run_to, "fine")) if (check_label(active, run_from, run_to, "fine"))
{ {
@ -223,7 +253,14 @@ struct SynthXilinxPass : public Pass
Pass::call(design, "dffsr2dff"); Pass::call(design, "dffsr2dff");
Pass::call(design, "dff2dffe"); Pass::call(design, "dff2dffe");
Pass::call(design, "opt -full"); 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"); 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, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : ""));
Pass::call(design, "clean"); Pass::call(design, "clean");
Pass::call(design, "techmap -map +/xilinx/lut_map.v");
} }
if (check_label(active, run_from, run_to, "map_cells")) if (check_label(active, run_from, run_to, "map_cells"))
{ {
Pass::call(design, "techmap -map +/xilinx/cells_map.v"); Pass::call(design, "techmap -map +/xilinx/cells_map.v");
if (vpr) Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT");
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, "clean"); Pass::call(design, "clean");
} }