diff options
Diffstat (limited to 'techlibs/xilinx')
-rw-r--r-- | techlibs/xilinx/cells_map.v | 128 | ||||
-rw-r--r-- | techlibs/xilinx/cells_sim.v | 96 | ||||
-rw-r--r-- | techlibs/xilinx/cells_xtra.sh | 10 | ||||
-rw-r--r-- | techlibs/xilinx/cells_xtra.v | 54 | ||||
-rw-r--r-- | techlibs/xilinx/ff_map.v | 13 | ||||
-rw-r--r-- | techlibs/xilinx/synth_xilinx.cc | 75 |
6 files changed, 292 insertions, 84 deletions
diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index d5801c0fc..704ab21b1 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -17,4 +17,130 @@ * */ -// Empty for now +module \$__SHREG_ (input C, input D, input E, output Q); + parameter DEPTH = 0; + parameter [DEPTH-1:0] INIT = 0; + parameter CLKPOL = 1; + parameter ENPOL = 2; + + \$__XILINX_SHREG_ #(.DEPTH(DEPTH), .INIT(INIT), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(DEPTH-1), .E(E), .Q(Q)); +endmodule + +module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, output SO); + parameter DEPTH = 0; + parameter [DEPTH-1:0] INIT = 0; + parameter CLKPOL = 1; + parameter ENPOL = 2; + + // shregmap's INIT parameter shifts out LSB first; + // however Xilinx expects MSB first + function [DEPTH-1:0] brev; + input [DEPTH-1:0] din; + integer i; + begin + for (i = 0; i < DEPTH; i=i+1) + brev[i] = din[DEPTH-1-i]; + end + endfunction + localparam [DEPTH-1:0] INIT_R = brev(INIT); + + parameter _TECHMAP_CONSTMSK_L_ = 0; + parameter _TECHMAP_CONSTVAL_L_ = 0; + + wire CE; + generate + if (ENPOL == 0) + assign CE = ~E; + else if (ENPOL == 1) + assign CE = E; + else + assign CE = 1'b1; + if (DEPTH == 1) begin + if (CLKPOL) + FDRE #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); + else + FDRE_1 #(.INIT(INIT_R)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(CE), .R(1'b0)); + end else + if (DEPTH <= 16) begin + SRL16E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A0(L[0]), .A1(L[1]), .A2(L[2]), .A3(L[3]), .CE(CE), .CLK(C), .D(D), .Q(Q)); + end else + if (DEPTH > 17 && DEPTH <= 32) begin + SRLC32E #(.INIT(INIT_R), .IS_CLK_INVERTED(~CLKPOL[0])) _TECHMAP_REPLACE_ (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(Q)); + end else + if (DEPTH > 33 && DEPTH <= 64) begin + wire T0, T1, T2; + SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-32), .INIT(INIT[DEPTH-32-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L), .E(E), .Q(T2)); + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T2; + else + MUXF7 fpga_mux_0 (.O(Q), .I0(T0), .I1(T2), .S(L[5])); + end else + if (DEPTH > 65 && DEPTH <= 96) begin + wire T0, T1, T2, T3, T4, T5, T6; + SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-64-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_2 (.C(C), .D(T3), .L(L[4:0]), .E(E), .Q(T4)); + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T4; + else begin + MUXF7 fpga_mux_0 (.O(T5), .I0(T0), .I1(T2), .S(L[5])); + MUXF7 fpga_mux_1 (.O(T6), .I0(T4), .I1(1'b0 /* unused */), .S(L[5])); + MUXF8 fpga_mux_2 (.O(Q), .I0(T5), .I1(T6), .S(L[6])); + end + end else + if (DEPTH > 97 && DEPTH < 128) begin + wire T0, T1, T2, T3, T4, T5, T6, T7, T8; + SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + SRLC32E #(.INIT(INIT_R[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-96-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .L(L[4:0]), .E(E), .Q(T6)); + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T6; + else begin + MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(L[5])); + MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(L[5])); + MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(L[6])); + end + end + else if (DEPTH == 128) begin + wire T0, T1, T2, T3, T4, T5, T6; + SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1)); + SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3)); + SRLC32E #(.INIT(INIT_R[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5)); + SRLC32E #(.INIT(INIT_R[128-1:96]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_3 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T5), .Q(T6), .Q31(SO)); + if (&_TECHMAP_CONSTMSK_L_) + assign Q = T6; + else begin + wire T7, T8; + MUXF7 fpga_mux_0 (.O(T7), .I0(T0), .I1(T2), .S(L[5])); + MUXF7 fpga_mux_1 (.O(T8), .I0(T4), .I1(T6), .S(L[5])); + MUXF8 fpga_mux_2 (.O(Q), .I0(T7), .I1(T8), .S(L[6])); + end + end + else if (DEPTH <= 129 && ~&_TECHMAP_CONSTMSK_L_) begin + // Handle cases where fixed-length depth is + // just 1 over a convenient value + \$__XILINX_SHREG_ #(.DEPTH(DEPTH+1), .INIT({INIT,1'b0}), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) _TECHMAP_REPLACE_ (.C(C), .D(D), .L(L), .E(E), .Q(Q)); + end + else begin + localparam lower_clog2 = $clog2((DEPTH+1)/2); + localparam lower_depth = 2 ** lower_clog2; + wire T0, T1, T2, T3; + if (&_TECHMAP_CONSTMSK_L_) begin + \$__XILINX_SHREG_ #(.DEPTH(lower_depth), .INIT(INIT[DEPTH-1:DEPTH-lower_depth]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(lower_depth-1), .E(E), .Q(T0)); + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-lower_depth), .INIT(INIT[DEPTH-lower_depth-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T0), .L(DEPTH-lower_depth-1), .E(E), .Q(Q), .SO(T3)); + end + else begin + \$__XILINX_SHREG_ #(.DEPTH(lower_depth), .INIT(INIT[DEPTH-1:DEPTH-lower_depth]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_0 (.C(C), .D(D), .L(L[lower_clog2-1:0]), .E(E), .Q(T0), .SO(T1)); + \$__XILINX_SHREG_ #(.DEPTH(DEPTH-lower_depth), .INIT(INIT[DEPTH-lower_depth-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_1 (.C(C), .D(T1), .L(L[lower_clog2-1:0]), .E(E), .Q(T2), .SO(T3)); + assign Q = L[lower_clog2] ? T2 : T0; + end + if (DEPTH == 2 * lower_depth) + assign SO = T3; + end + endgenerate +endmodule + +`ifndef SRL_ONLY +`endif diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index ff5ff0726..3a4540b83 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -30,10 +30,15 @@ module GND(output G); endmodule module IBUF(output O, input I); + parameter IOSTANDARD = "default"; + parameter IBUF_LOW_PWR = 0; assign O = I; endmodule module OBUF(output O, input I); + parameter IOSTANDARD = "default"; + parameter DRIVE = 12; + parameter SLEW = "SLOW"; assign O = I; endmodule @@ -41,6 +46,42 @@ module BUFG(output O, input I); assign O = I; endmodule +module BUFGCTRL( + output O, + input I0, input I1, + input S0, input S1, + input CE0, input CE1, + input IGNORE0, input IGNORE1); + +parameter [0:0] INIT_OUT = 1'b0; +parameter PRESELECT_I0 = "FALSE"; +parameter PRESELECT_I1 = "FALSE"; +parameter [0:0] IS_CE0_INVERTED = 1'b0; +parameter [0:0] IS_CE1_INVERTED = 1'b0; +parameter [0:0] IS_S0_INVERTED = 1'b0; +parameter [0:0] IS_S1_INVERTED = 1'b0; +parameter [0:0] IS_IGNORE0_INVERTED = 1'b0; +parameter [0:0] IS_IGNORE1_INVERTED = 1'b0; + +wire I0_internal = ((CE0 ^ IS_CE0_INVERTED) ? I0 : INIT_OUT); +wire I1_internal = ((CE1 ^ IS_CE1_INVERTED) ? I1 : INIT_OUT); +wire S0_true = (S0 ^ IS_S0_INVERTED); +wire S1_true = (S1 ^ IS_S1_INVERTED); + +assign O = S0_true ? I0_internal : (S1_true ? I1_internal : INIT_OUT); + +endmodule + +module BUFHCE(output O, input I, input CE); + +parameter [0:0] INIT_OUT = 1'b0; +parameter CE_TYPE = "SYNC"; +parameter [0:0] IS_CE_INVERTED = 1'b0; + +assign O = ((CE ^ IS_CE_INVERTED) ? I : INIT_OUT); + +endmodule + // module OBUFT(output O, input I, T); // assign O = T ? 1'bz : I; // endmodule @@ -98,6 +139,22 @@ module LUT6(output O, input I0, I1, I2, I3, I4, I5); assign O = I0 ? s1[1] : s1[0]; endmodule +module LUT6_2(output O6, output O5, input I0, I1, I2, I3, I4, I5); + parameter [63:0] INIT = 0; + wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0]; + wire [15: 0] s4 = I4 ? s5[31:16] : s5[15: 0]; + wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0]; + wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0]; + wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0]; + assign O6 = I0 ? s1[1] : s1[0]; + + wire [15: 0] s5_4 = I4 ? INIT[31:16] : INIT[15: 0]; + wire [ 7: 0] s5_3 = I3 ? s5_4[15: 8] : s5_4[ 7: 0]; + wire [ 3: 0] s5_2 = I2 ? s5_3[ 7: 4] : s5_3[ 3: 0]; + wire [ 1: 0] s5_1 = I1 ? s5_2[ 3: 2] : s5_2[ 1: 0]; + assign O5 = I0 ? s5_1[1] : s5_1[0]; +endmodule + module MUXCY(output O, input CI, DI, S); assign O = S ? CI : DI; endmodule @@ -251,3 +308,42 @@ module RAM128X1D ( wire clk = WCLK ^ IS_WCLK_INVERTED; always @(posedge clk) if (WE) mem[A] <= D; endmodule + +module SRL16E ( + output Q, + input A0, A1, A2, A3, CE, CLK, D +); + parameter [15:0] INIT = 16'h0000; + parameter [0:0] IS_CLK_INVERTED = 1'b0; + + reg [15:0] r = INIT; + assign Q = r[{A3,A2,A1,A0}]; + generate + if (IS_CLK_INVERTED) begin + always @(negedge CLK) if (CE) r <= { r[14:0], D }; + end + else + always @(posedge CLK) if (CE) r <= { r[14:0], D }; + endgenerate +endmodule + +module SRLC32E ( + output Q, + output Q31, + input [4:0] A, + input CE, CLK, D +); + parameter [31:0] INIT = 32'h00000000; + parameter [0:0] IS_CLK_INVERTED = 1'b0; + + reg [31:0] r = INIT; + assign Q31 = r[31]; + assign Q = r[A]; + generate + if (IS_CLK_INVERTED) begin + always @(negedge CLK) if (CE) r <= { r[30:0], D }; + end + else + always @(posedge CLK) if (CE) r <= { r[30:0], D }; + endgenerate +endmodule diff --git a/techlibs/xilinx/cells_xtra.sh b/techlibs/xilinx/cells_xtra.sh index 56520ea10..8e39b440d 100644 --- a/techlibs/xilinx/cells_xtra.sh +++ b/techlibs/xilinx/cells_xtra.sh @@ -28,12 +28,12 @@ function xtract_cell_decl() # xtract_cell_decl BUFG xtract_cell_decl BUFGCE xtract_cell_decl BUFGCE_1 - xtract_cell_decl BUFGCTRL + #xtract_cell_decl BUFGCTRL xtract_cell_decl BUFGMUX xtract_cell_decl BUFGMUX_1 xtract_cell_decl BUFGMUX_CTRL xtract_cell_decl BUFH - xtract_cell_decl BUFHCE + #xtract_cell_decl BUFHCE xtract_cell_decl BUFIO xtract_cell_decl BUFMR xtract_cell_decl BUFMRCE @@ -92,7 +92,7 @@ function xtract_cell_decl() # xtract_cell_decl LUT4 # xtract_cell_decl LUT5 # xtract_cell_decl LUT6 - xtract_cell_decl LUT6_2 + #xtract_cell_decl LUT6_2 xtract_cell_decl MMCME2_ADV xtract_cell_decl MMCME2_BASE # xtract_cell_decl MUXF7 @@ -135,8 +135,8 @@ function xtract_cell_decl() xtract_cell_decl ROM256X1 xtract_cell_decl ROM32X1 xtract_cell_decl ROM64X1 - xtract_cell_decl SRL16E - xtract_cell_decl SRLC32E + #xtract_cell_decl SRL16E + #xtract_cell_decl SRLC32E xtract_cell_decl STARTUPE2 "(* keep *)" xtract_cell_decl USR_ACCESSE2 xtract_cell_decl XADC diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v index 497518d35..fbcc74682 100644 --- a/techlibs/xilinx/cells_xtra.v +++ b/techlibs/xilinx/cells_xtra.v @@ -30,29 +30,6 @@ module BUFGCE_1 (...); input CE, I; endmodule -module BUFGCTRL (...); - output O; - input CE0; - input CE1; - input I0; - input I1; - input IGNORE0; - input IGNORE1; - input S0; - input S1; - parameter integer INIT_OUT = 0; - parameter PRESELECT_I0 = "FALSE"; - parameter PRESELECT_I1 = "FALSE"; - parameter [0:0] IS_CE0_INVERTED = 1'b0; - parameter [0:0] IS_CE1_INVERTED = 1'b0; - parameter [0:0] IS_I0_INVERTED = 1'b0; - parameter [0:0] IS_I1_INVERTED = 1'b0; - parameter [0:0] IS_IGNORE0_INVERTED = 1'b0; - parameter [0:0] IS_IGNORE1_INVERTED = 1'b0; - parameter [0:0] IS_S0_INVERTED = 1'b0; - parameter [0:0] IS_S1_INVERTED = 1'b0; -endmodule - module BUFGMUX (...); parameter CLK_SEL_TYPE = "SYNC"; output O; @@ -77,15 +54,6 @@ module BUFH (...); input I; endmodule -module BUFHCE (...); - parameter CE_TYPE = "SYNC"; - parameter integer INIT_OUT = 0; - parameter [0:0] IS_CE_INVERTED = 1'b0; - output O; - input CE; - input I; -endmodule - module BUFIO (...); output O; input I; @@ -2420,12 +2388,6 @@ module LDPE (...); input D, G, GE, PRE; endmodule -module LUT6_2 (...); - parameter [63:0] INIT = 64'h0000000000000000; - input I0, I1, I2, I3, I4, I5; - output O5, O6; -endmodule - module MMCME2_ADV (...); parameter BANDWIDTH = "OPTIMIZED"; parameter real CLKFBOUT_MULT_F = 5.000; @@ -3847,22 +3809,6 @@ module ROM64X1 (...); input A0, A1, A2, A3, A4, A5; endmodule -module SRL16E (...); - parameter [15:0] INIT = 16'h0000; - parameter [0:0] IS_CLK_INVERTED = 1'b0; - output Q; - input A0, A1, A2, A3, CE, CLK, D; -endmodule - -module SRLC32E (...); - parameter [31:0] INIT = 32'h00000000; - parameter [0:0] IS_CLK_INVERTED = 1'b0; - output Q; - output Q31; - input [4:0] A; - input CE, CLK, D; -endmodule - (* keep *) module STARTUPE2 (...); parameter PROG_USR = "FALSE"; diff --git a/techlibs/xilinx/ff_map.v b/techlibs/xilinx/ff_map.v index 13beaa6ae..c61fd7070 100644 --- a/techlibs/xilinx/ff_map.v +++ b/techlibs/xilinx/ff_map.v @@ -22,21 +22,26 @@ `ifndef _NO_FFS +`ifndef _NO_POS_SR module \$_DFF_N_ (input D, C, output Q); FDRE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule module \$_DFF_P_ (input D, C, output Q); FDRE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule module \$_DFFE_NP_ (input D, C, E, output Q); FDRE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule module \$_DFFE_PP_ (input D, C, E, output Q); FDRE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule -module \$_DFF_NN0_ (input D, C, R, output Q); 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 + +module \$_DFF_NN0_ (input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule +module \$_DFF_PN0_ (input D, C, R, output Q); \$_DFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule + +module \$_DFF_NN1_ (input D, C, R, output Q); \$_DFF_NP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule +module \$_DFF_PN1_ (input D, C, R, output Q); \$_DFF_PP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule +`endif `endif diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 805ae8e6e..58dd928a0 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -64,10 +64,13 @@ struct SynthXilinxPass : public Pass log(" (this feature is experimental and incomplete)\n"); log("\n"); log(" -nobram\n"); - log(" disable infering of block rams\n"); + log(" disable inference of block rams\n"); log("\n"); log(" -nodram\n"); - log(" disable infering of distributed rams\n"); + log(" disable inference of distributed rams\n"); + log("\n"); + log(" -nosrl\n"); + log(" disable inference of shift registers\n"); log("\n"); log(" -run <from_label>:<to_label>\n"); log(" only run the commands between the labels (see below). an empty\n"); @@ -105,21 +108,28 @@ struct SynthXilinxPass : public Pass log(" techmap -map +/xilinx/drams_map.v\n"); log("\n"); log(" fine:\n"); - log(" opt -fast -full\n"); + log(" opt -fast\n"); log(" memory_map\n"); log(" dffsr2dff\n"); log(" dff2dffe\n"); - log(" opt -full\n"); - log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v\n"); + log(" techmap -map +/xilinx/arith_map.v\n"); log(" opt -fast\n"); log("\n"); - log(" map_luts:\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(" simplemap t:$dff t:$dffe (without '-nosrl' only)\n"); + log(" pmux2shiftx (without '-nosrl' only)\n"); + log(" opt_expr -mux_undef (without '-nosrl' only)\n"); + log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n"); log(" techmap -map +/xilinx/cells_map.v\n"); + log(" clean\n"); + log("\n"); + log(" map_luts:\n"); + log(" opt -full\n"); + log(" techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v\n"); + log(" abc -luts 2:2,3,6:5,10,20 [-dff]\n"); + log(" clean\n"); + log(" shregmap -minlen 3 -init -params -enpol any_or_none (without '-nosrl' only)\n"); + log(" techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v"); log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT \\\n"); log(" -ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT\n"); log(" clean\n"); @@ -147,6 +157,7 @@ struct SynthXilinxPass : public Pass bool vpr = false; bool nobram = false; bool nodram = false; + bool nosrl = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -191,6 +202,10 @@ struct SynthXilinxPass : public Pass nodram = true; continue; } + if (args[argidx] == "-nosrl") { + nosrl = true; + continue; + } break; } extra_args(args, argidx, design); @@ -249,32 +264,52 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "fine")) { - Pass::call(design, "opt -fast -full"); + Pass::call(design, "opt -fast"); Pass::call(design, "memory_map"); Pass::call(design, "dffsr2dff"); Pass::call(design, "dff2dffe"); - Pass::call(design, "opt -full"); if (vpr) { - Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v -D _EXPLICIT_CARRY"); + Pass::call(design, "techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); } else { - Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v"); + Pass::call(design, "techmap -map +/xilinx/arith_map.v"); } - Pass::call(design, "hierarchy -check"); Pass::call(design, "opt -fast"); } - if (check_label(active, run_from, run_to, "map_luts")) + if (check_label(active, run_from, run_to, "map_cells")) { - Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); + if (!nosrl) { + // shregmap operates on bit-level flops, not word-level, + // so break those down here + Pass::call(design, "simplemap t:$dff t:$dffe"); + // shregmap -tech xilinx can cope with $shiftx and $mux + // cells for identifiying variable-length shift registers, + // so attempt to convert $pmux-es to the former + Pass::call(design, "pmux2shiftx"); + // pmux2shiftx can leave behind a $pmux with a single entry + // -- need this to clean that up before shregmap + Pass::call(design, "opt_expr -mux_undef"); + // shregmap with '-tech xilinx' infers variable length shift regs + Pass::call(design, "shregmap -tech xilinx -minlen 3"); + } + + Pass::call(design, "techmap -map +/xilinx/cells_map.v"); 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_luts")) { - Pass::call(design, "techmap -map +/xilinx/cells_map.v"); + Pass::call(design, "opt -full"); + Pass::call(design, "techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v"); + Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); + Pass::call(design, "clean"); + // This shregmap call infers fixed length shift registers after abc + // has performed any necessary retiming + if (!nosrl) + Pass::call(design, "shregmap -minlen 3 -init -params -enpol any_or_none"); + Pass::call(design, "techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v"); Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); Pass::call(design, "clean"); |