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 | 254 | 
6 files changed, 353 insertions, 202 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..c4c27d816 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -25,18 +25,9 @@  USING_YOSYS_NAMESPACE  PRIVATE_NAMESPACE_BEGIN -bool check_label(bool &active, std::string run_from, std::string run_to, std::string label) +struct SynthXilinxPass : public ScriptPass  { -	if (label == run_from) -		active = true; -	if (label == run_to) -		active = false; -	return active; -} - -struct SynthXilinxPass : public Pass -{ -	SynthXilinxPass() : Pass("synth_xilinx", "synthesis for Xilinx FPGAs") { } +	SynthXilinxPass() : ScriptPass("synth_xilinx", "synthesis for Xilinx FPGAs") { }  	void help() YS_OVERRIDE  	{ @@ -64,10 +55,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"); @@ -82,71 +76,30 @@ struct SynthXilinxPass : public Pass  		log("\n");  		log("\n");  		log("The following commands are executed by this synthesis command:\n"); +		help_script();  		log("\n"); -		log("    begin:\n"); -		log("        read_verilog -lib +/xilinx/cells_sim.v\n"); -		log("        read_verilog -lib +/xilinx/cells_xtra.v\n"); -		log("        read_verilog -lib +/xilinx/brams_bb.v\n"); -		log("        hierarchy -check -top <top>\n"); -		log("\n"); -		log("    flatten:     (only if -flatten)\n"); -		log("        proc\n"); -		log("        flatten\n"); -		log("\n"); -		log("    coarse:\n"); -		log("        synth -run coarse\n"); -		log("\n"); -		log("    bram: (only executed when '-nobram' is not given)\n"); -		log("        memory_bram -rules +/xilinx/brams.txt\n"); -		log("        techmap -map +/xilinx/brams_map.v\n"); -		log("\n"); -		log("    dram: (only executed when '-nodram' is not given)\n"); -		log("        memory_bram -rules +/xilinx/drams.txt\n"); -		log("        techmap -map +/xilinx/drams_map.v\n"); -		log("\n"); -		log("    fine:\n"); -		log("        opt -fast -full\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("        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("        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("                -ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT\n"); -		log("        clean\n"); -		log("\n"); -		log("    check:\n"); -		log("        hierarchy -check\n"); -		log("        stat\n"); -		log("        check -noinit\n"); -		log("\n"); -		log("    edif:     (only if -edif)\n"); -		log("        write_edif <file-name>\n"); -		log("\n"); -		log("    blif:     (only if -blif)\n"); -		log("        write_blif <file-name>\n"); -		log("\n");  	} + +	std::string top_opt, edif_file, blif_file; +	bool flatten, retime, vpr, nobram, nodram, nosrl; + +	void clear_flags() YS_OVERRIDE +	{ +		top_opt = "-auto-top"; +		edif_file.clear(); +		blif_file.clear(); +		flatten = false; +		retime = false; +		vpr = false; +		nobram = false; +		nodram = false; +		nosrl = false; +	} +  	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE  	{ -		std::string top_opt = "-auto-top"; -		std::string edif_file; -		std::string blif_file;  		std::string run_from, run_to; -		bool flatten = false; -		bool retime = false; -		bool vpr = false; -		bool nobram = false; -		bool nodram = false; +		clear_flags();  		size_t argidx;  		for (argidx = 1; argidx < args.size(); argidx++) @@ -191,6 +144,10 @@ struct SynthXilinxPass : public Pass  				nodram = true;  				continue;  			} +			if (args[argidx] == "-nosrl") { +				nosrl = true; +				continue; +			}  			break;  		}  		extra_args(args, argidx, design); @@ -198,107 +155,128 @@ struct SynthXilinxPass : public Pass  		if (!design->full_selection())  			log_cmd_error("This command only operates on fully selected designs!\n"); -		bool active = run_from.empty(); -  		log_header(design, "Executing SYNTH_XILINX pass.\n");  		log_push(); -		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"); -			} +		run_script(design, run_from, run_to); -			Pass::call(design, "read_verilog -lib +/xilinx/cells_xtra.v"); +		log_pop(); +	} -			if (!nobram) { -				Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v"); -			} +	void script() YS_OVERRIDE +	{ +		if (check_label("begin")) { +			if (vpr) +				run("read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); +			else +				run("read_verilog -lib +/xilinx/cells_sim.v"); + +			run("read_verilog -lib +/xilinx/cells_xtra.v"); + +			if (!nobram || help_mode) +				run("read_verilog -lib +/xilinx/brams_bb.v", "(skip if '-nobram')"); -			Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str())); +			run(stringf("hierarchy -check %s", top_opt.c_str()));  		} -		if (flatten && check_label(active, run_from, run_to, "flatten")) -		{ -			Pass::call(design, "proc"); -			Pass::call(design, "flatten"); +		if (check_label("flatten", "(with '-flatten' only)")) { +			if (flatten || help_mode) { +				run("proc"); +				run("flatten"); +			}  		} -		if (check_label(active, run_from, run_to, "coarse")) -		{ -			Pass::call(design, "synth -run coarse"); +		if (check_label("coarse")) { +			run("synth -run coarse");  		} -		if (check_label(active, run_from, run_to, "bram")) -		{ -			if (!nobram) { -				Pass::call(design, "memory_bram -rules +/xilinx/brams.txt"); -				Pass::call(design, "techmap -map +/xilinx/brams_map.v"); +		if (check_label("bram", "(skip if '-nobram')")) { +			if (!nobram || help_mode) { +				run("memory_bram -rules +/xilinx/brams.txt"); +				run("techmap -map +/xilinx/brams_map.v");  			}  		} -		if (check_label(active, run_from, run_to, "dram")) -		{ -			if (!nodram) { -				Pass::call(design, "memory_bram -rules +/xilinx/drams.txt"); -				Pass::call(design, "techmap -map +/xilinx/drams_map.v"); +		if (check_label("dram", "(skip if '-nodram')")) { +			if (!nodram || help_mode) { +				run("memory_bram -rules +/xilinx/drams.txt"); +				run("techmap -map +/xilinx/drams_map.v");  			}  		} -		if (check_label(active, run_from, run_to, "fine")) -		{ -			Pass::call(design, "opt -fast -full"); -			Pass::call(design, "memory_map"); -			Pass::call(design, "dffsr2dff"); -			Pass::call(design, "dff2dffe"); -			Pass::call(design, "opt -full"); +		if (check_label("fine")) { +			run("opt -fast"); +			run("memory_map"); +			run("dffsr2dff"); +			run("dff2dffe"); -			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"); -			} +			if (!vpr || help_mode) +				run("techmap -map +/xilinx/arith_map.v"); +			else +				run("techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); -			Pass::call(design, "hierarchy -check"); -			Pass::call(design, "opt -fast"); +			run("hierarchy -check"); +			run("opt -fast");  		} -		if (check_label(active, run_from, run_to, "map_luts")) +		if (check_label("map_cells"))  		{ -			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 (!nosrl || help_mode) { +				// shregmap operates on bit-level flops, not word-level, +				//   so break those down here +				run("simplemap t:$dff t:$dffe", "(skip if '-nosrl')"); +				// 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 +				run("pmux2shiftx", "(skip if '-nosrl')"); +				// pmux2shiftx can leave behind a $pmux with a single entry +				//   -- need this to clean that up before shregmap +				run("opt_expr -mux_undef", "(skip if '-nosrl')"); +				// shregmap with '-tech xilinx' infers variable length shift regs +				run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')"); +			} + +			run("techmap -map +/xilinx/cells_map.v"); +			run("clean");  		} -		if (check_label(active, run_from, run_to, "map_cells")) +		if (check_label("map_luts"))  		{ -			Pass::call(design, "techmap -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 " +			run("opt -full"); +			run("techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v"); +			if (help_mode) +				run("abc -luts 2:2,3,6:5,10,20 [-dff]"); +			else +				run("abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); +			run("clean"); +			// This shregmap call infers fixed length shift registers after abc +			//   has performed any necessary retiming +			if (!nosrl || help_mode) +				run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')"); +			run("techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v"); +			run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT "  					"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); -			Pass::call(design, "clean"); +			run("clean");  		} -		if (check_label(active, run_from, run_to, "check")) +		if (check_label("check"))  		{ -			Pass::call(design, "hierarchy -check"); -			Pass::call(design, "stat"); -			Pass::call(design, "check -noinit"); +			run("hierarchy -check"); +			run("stat"); +			run("check -noinit");  		} -		if (check_label(active, run_from, run_to, "edif")) +		if (check_label("edif"))  		{ -			if (!edif_file.empty()) -				Pass::call(design, stringf("write_edif -pvector bra %s", edif_file.c_str())); +			if (!edif_file.empty() || help_mode) +				run(stringf("write_edif -pvector bra %s", edif_file.c_str()));  		} -		if (check_label(active, run_from, run_to, "blif")) + +		if (check_label("blif"))  		{ -			if (!blif_file.empty()) -				Pass::call(design, stringf("write_blif %s", edif_file.c_str())); +			if (!blif_file.empty() || help_mode) +				run(stringf("write_blif %s", edif_file.c_str()));  		} - -		log_pop();  	}  } SynthXilinxPass; | 
