diff options
Diffstat (limited to 'techlibs/xilinx')
| -rw-r--r-- | techlibs/xilinx/Makefile.inc | 1 | ||||
| -rw-r--r-- | techlibs/xilinx/abc_xc7.box | 19 | ||||
| -rw-r--r-- | techlibs/xilinx/cells_map.v | 162 | ||||
| -rw-r--r-- | techlibs/xilinx/cells_sim.v | 14 | ||||
| -rw-r--r-- | techlibs/xilinx/mux_map.v | 71 | ||||
| -rw-r--r-- | techlibs/xilinx/synth_xilinx.cc | 92 | 
6 files changed, 324 insertions, 35 deletions
diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 1a652eb27..59fd61cf0 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -30,6 +30,7 @@ $(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/ff_map.v))  $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v)) +$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/mux_map.v))  $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.box))  $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.lut)) diff --git a/techlibs/xilinx/abc_xc7.box b/techlibs/xilinx/abc_xc7.box index 6dd71d758..273d36573 100644 --- a/techlibs/xilinx/abc_xc7.box +++ b/techlibs/xilinx/abc_xc7.box @@ -3,17 +3,22 @@  # NB: Inputs/Outputs must be ordered alphabetically  #     (with exceptions for carry in/out) -# F7BMUX slower than F7AMUX +# Average across F7[AB]MUX  # Inputs: I0 I1 S0  # Outputs: O -F7BMUX 1 1 3 1 -217 223 296 +F7MUX 1 1 3 1 +204 208 286  # Inputs: I0 I1 S0  # Outputs: O  MUXF8 2 1 3 1  104 94 273 +# Inputs: I0 I1 I2 I3 S0 S1 +# Outputs: O +$__MUXF78 3 1 6 1 +190 193 217 223 296 273 +  # CARRY4 + CARRY4_[ABCD]X  # Inputs: CYINIT DI0 DI1 DI2 DI3 S0 S1 S2 S3 CI  # Outputs:  O0 O1 O2 O3 CO0 CO1 CO2 CO3 @@ -21,7 +26,7 @@ MUXF8 2 1 3 1  #        input/output and the entire bus has been  #        moved there overriding the otherwise  #        alphabetical ordering) -CARRY4 3 1 10 8 +CARRY4 4 1 10 8  482 -   -   -   -   223 -   -   -   222  598 407 -   -   -   400 205 -   -   334  584 556 537 -   -   523 558 226 -   239 @@ -34,20 +39,20 @@ CARRY4 3 1 10 8  # SLICEM/A6LUT  # Inputs: A0 A1 A2 A3 A4 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 WCLK WE  # Outputs: DPO SPO -RAM32X1D 4 0 13 2 +RAM32X1D 5 0 13 2  -   -   -   -   -   - 631 472 407 238 127 - -  631 472 407 238 127 - -   -   -   -   -   - -  # SLICEM/A6LUT  # Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE  # Outputs: DPO SPO -RAM64X1D 5 0 15 2 +RAM64X1D 6 0 15 2  -   -   -   -   -   -   - 642 631 472 407 238 127 - -  642 631 472 407 238 127 - -   -   -   -   -   -   - -  # SLICEM/A6LUT + F7[AB]MUX  # Inputs: A0 A1 A2 A3 A4 A5 A6 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 DPRA6 WCLK WE  # Outputs: DPO SPO -RAM128X1D 6 0 17 2 +RAM128X1D 7 0 17 2  -    -    -   -   -   -   -   - 1009 998 839 774 605 494 450 - -  1047 1036 877 812 643 532 478 - -    -   -   -   -   -   -   - - diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v index 9a316fc96..cce70d69e 100644 --- a/techlibs/xilinx/cells_map.v +++ b/techlibs/xilinx/cells_map.v @@ -152,3 +152,165 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o      end    endgenerate  endmodule + +`ifdef MIN_MUX_INPUTS +module \$__XILINX_SHIFTX (A, B, Y); +  parameter A_SIGNED = 0; +  parameter B_SIGNED = 0; +  parameter A_WIDTH = 1; +  parameter B_WIDTH = 1; +  parameter Y_WIDTH = 1; + +  input [A_WIDTH-1:0] A; +  input [B_WIDTH-1:0] B; +  output [Y_WIDTH-1:0] Y; + +  parameter [A_WIDTH-1:0] _TECHMAP_CONSTMSK_A_ = 0; +  parameter [A_WIDTH-1:0] _TECHMAP_CONSTVAL_A_ = 0; +  parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; +  parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; + +  function integer compute_num_leading_X_in_A; +    integer i, c; +  begin +    compute_num_leading_X_in_A = 0; +    c = 1; +    for (i = A_WIDTH-1; i >= 0; i=i-1) begin +      if (!_TECHMAP_CONSTMSK_A_[i] || _TECHMAP_CONSTVAL_A_[i] !== 1'bx) +        c = 0; +      compute_num_leading_X_in_A = compute_num_leading_X_in_A + c; +    end +  end +  endfunction +  localparam num_leading_X_in_A = compute_num_leading_X_in_A(); + +  generate +    genvar i, j; +    // Bit-blast +    if (Y_WIDTH > 1) begin +      for (i = 0; i < Y_WIDTH; i++) +        \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-Y_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A(A[A_WIDTH-Y_WIDTH+i:i]), .B(B), .Y(Y[i])); +    end +    // If the LSB of B is constant zero (and Y_WIDTH is 1) then +    //   we can optimise by removing every other entry from A +    //   and popping the constant zero from B +    else if (_TECHMAP_CONSTMSK_B_[0] && !_TECHMAP_CONSTVAL_B_[0]) begin +      wire [(A_WIDTH+1)/2-1:0] A_i; +      for (i = 0; i < (A_WIDTH+1)/2; i++) +        assign A_i[i] = A[i*2]; +      \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y)); +    end +    // Trim off any leading 1'bx -es in A, and resize B accordingly +    else if (num_leading_X_in_A > 0) begin +      localparam A_WIDTH_new = A_WIDTH - num_leading_X_in_A; +      localparam B_WIDTH_new = $clog2(A_WIDTH_new); +      \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH_new), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B[B_WIDTH_new-1:0]), .Y(Y)); +    end +    else if (A_WIDTH < `MIN_MUX_INPUTS) begin +      wire _TECHMAP_FAIL_ = 1; +    end +    else if (A_WIDTH <= 2 ** 3) begin +      localparam a_width0 = 2 ** 2; +      localparam a_widthN = A_WIDTH - a_width0; +      wire T0, T1; +      \$shiftx  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[a_width0-1:0]), .B(B[2-1:0]), .Y(T0)); +      if (a_widthN > 1) +        \$shiftx  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1)); +      else +        assign T1 = A[A_WIDTH-1]; +      MUXF7 fpga_hard_mux (.I0(T0), .I1(T1), .S(B[2]), .O(Y)); +    end +    else if (A_WIDTH <= 2 ** 4) begin +      localparam a_width0 = 2 ** 2; +      localparam num_mux8 = A_WIDTH / a_width0; +      localparam a_widthN = A_WIDTH % a_width0; +      wire [a_width0-1:0] T; +      for (i = 0; i < a_width0; i++) +        if (i < num_mux8) +          \$shiftx  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2), .Y_WIDTH(Y_WIDTH)) fpga_mux (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]), .Y(T[i])); +        else if (i == num_mux8 && a_widthN > 1) +          \$shiftx  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_mux_last (.A(A[A_WIDTH-1-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i])); +        else +          assign T[i] = A[A_WIDTH-1]; +      \$__XILINX_MUXF78 fpga_hard_mux (.I0(T[0]), .I1(T[1]), .I2(T[2]), .I3(T[3]), .S0(B[2]), .S1(B[3]), .O(Y)); +    end +    else begin +      localparam a_width0 = 2 ** 4; +      localparam num_mux16 = A_WIDTH / a_width0; +      localparam a_widthN = A_WIDTH % a_width0; +      wire [num_mux16 + (a_widthN > 0 ? 1 : 0) - 1:0] T; +      for (i = 0; i < num_mux16; i++) +        \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]), .Y(T[i])); +      if (a_widthN > 0) begin +        if (a_widthN > 1) +          \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1-:a_widthN]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[num_mux16])); +        else +          assign T[num_mux16] = A[A_WIDTH-1]; +      end +      \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(num_mux16 + (a_widthN > 0 ? 1 : 0)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y)); +    end +  endgenerate +endmodule + +(* techmap_celltype = "$__XILINX_SHIFTX" *) +module _90__XILINX_SHIFTX (A, B, Y); +  parameter A_SIGNED = 0; +  parameter B_SIGNED = 0; +  parameter A_WIDTH = 1; +  parameter B_WIDTH = 1; +  parameter Y_WIDTH = 1; + +  input [A_WIDTH-1:0] A; +  input [B_WIDTH-1:0] B; +  output [Y_WIDTH-1:0] Y; + +  \$shiftx  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); +endmodule + +module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y); +input A, B, C, D, E, F, G, H, S, T, U; +output Y; +  \$__XILINX_SHIFTX  #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(3), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({H,G,F,E,D,C,B,A}), .B({U,T,S}), .Y(Y)); +endmodule + +module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y); +input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V; +output Y; +  \$__XILINX_SHIFTX  #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(16), .B_WIDTH(4), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A}), .B({V,U,T,S}), .Y(Y)); +endmodule +`endif + +`ifndef _ABC +module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1); +  output O; +  input I0, I1, I2, I3, S0, S1; +  wire T0, T1; +//  parameter _TECHMAP_BITS_CONNMAP_ = 0; +//  parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I0_ = 0; +//  parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I1_ = 0; +//  parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I2_ = 0; +//  parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_I3_ = 0; +//  parameter _TECHMAP_CONSTMSK_S0_ = 0; +//  parameter _TECHMAP_CONSTVAL_S0_ = 0; +//  parameter _TECHMAP_CONSTMSK_S1_ = 0; +//  parameter _TECHMAP_CONSTVAL_S1_ = 0; +//  if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) +//    assign T0 = I1; +//  else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_) +//    assign T0 = I0; +//  else +    MUXF7 mux7a (.I0(I0), .I1(I1), .S(S0), .O(T0)); +//  if (_TECHMAP_CONSTMSK_S0_ && _TECHMAP_CONSTVAL_S0_ === 1'b1) +//    assign T1 = I3; +//  else if (_TECHMAP_CONSTMSK_S0_ || _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_) +//    assign T1 = I2; +//  else +    MUXF7 mux7b (.I0(I2), .I1(I3), .S(S0), .O(T1)); +//  if (_TECHMAP_CONSTMSK_S1_ && _TECHMAP_CONSTVAL_S1_ === 1'b1) +//    assign O = T1; +//  else if (_TECHMAP_CONSTMSK_S1_ || (_TECHMAP_CONNMAP_I0_ === _TECHMAP_CONNMAP_I1_ && _TECHMAP_CONNMAP_I1_ === _TECHMAP_CONNMAP_I2_ && _TECHMAP_CONNMAP_I2_ === _TECHMAP_CONNMAP_I3_)) +//    assign O = T0; +//  else +    MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O)); +endmodule +`endif diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 5a148be01..94bc3ef86 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -169,6 +169,14 @@ module MUXF8(output O, input I0, I1, S);    assign O = S ? I1 : I0;  endmodule +`ifdef _ABC +(* abc_box_id = 3, lib_whitebox *) +module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); +  assign O = S1 ? (S0 ? I3 : I2) +                : (S0 ? I1 : I0); +endmodule +`endif +  module XORCY(output O, input CI, LI);    assign O = CI ^ LI;  endmodule @@ -281,7 +289,7 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE);    always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;  endmodule -(* abc_box_id = 4, abc_scc_break="D,WE" *) +(* abc_box_id = 5, abc_scc_break="D,WE" *)  module RAM32X1D (    output DPO, SPO,    input  D, WCLK, WE, @@ -299,7 +307,7 @@ module RAM32X1D (    always @(posedge clk) if (WE) mem[a] <= D;  endmodule -(* abc_box_id = 5, abc_scc_break="D,WE" *) +(* abc_box_id = 6, abc_scc_break="D,WE" *)  module RAM64X1D (    output DPO, SPO,    input  D, WCLK, WE, @@ -317,7 +325,7 @@ module RAM64X1D (    always @(posedge clk) if (WE) mem[a] <= D;  endmodule -(* abc_box_id = 6, abc_scc_break="D,WE" *) +(* abc_box_id = 7, abc_scc_break="D,WE" *)  module RAM128X1D (    output       DPO, SPO,    input        D, WCLK, WE, diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v new file mode 100644 index 000000000..91aaf2118 --- /dev/null +++ b/techlibs/xilinx/mux_map.v @@ -0,0 +1,71 @@ +/* + *  yosys -- Yosys Open SYnthesis Suite + * + *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> + *                2019  Eddie Hung    <eddie@fpgeh.com> + * + *  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. + * + */ + +// The purpose of these mapping rules is to allow preserve all (sufficiently +// wide) $shiftx cells during 'techmap' so that they can be mapped to hard +// resources, rather than being bit-blasted to gates during 'techmap' +// execution + +module \$shiftx (A, B, Y); +  parameter A_SIGNED = 0; +  parameter B_SIGNED = 0; +  parameter A_WIDTH = 1; +  parameter B_WIDTH = 1; +  parameter Y_WIDTH = 1; + +  input [A_WIDTH-1:0] A; +  input [B_WIDTH-1:0] B; +  output [Y_WIDTH-1:0] Y; + +  parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; +  parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0; + +  generate +    if (B_SIGNED) begin +      if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && (_TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0 || _TECHMAP_CONSTVAL_B_[B_WIDTH-1] === 1'bx)) +        // Optimisation to remove B_SIGNED if sign bit of B is constant-0 +        \$shiftx #( +          .A_SIGNED(A_SIGNED), +          .B_SIGNED(0), +          .A_WIDTH(A_WIDTH), +          .B_WIDTH(B_WIDTH-1'd1), +          .Y_WIDTH(Y_WIDTH) +        ) _TECHMAP_REPLACE_ ( +          .A(A), .B(B[B_WIDTH-2:0]), .Y(Y) +        ); +      else +        wire _TECHMAP_FAIL_ = 1; +    end +    else begin +      if (((A_WIDTH + Y_WIDTH - 1) / Y_WIDTH) < `MIN_MUX_INPUTS) +        wire _TECHMAP_FAIL_ = 1; +      else +        \$__XILINX_SHIFTX #( +          .A_SIGNED(A_SIGNED), +          .B_SIGNED(B_SIGNED), +          .A_WIDTH(A_WIDTH), +          .B_WIDTH(B_WIDTH), +          .Y_WIDTH(Y_WIDTH) +        ) _TECHMAP_REPLACE_ ( +          .A(A), .B(B), .Y(Y) +        ); +    end +  endgenerate +endmodule diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index c24f66e52..0a30848aa 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -77,6 +77,11 @@ struct SynthXilinxPass : public ScriptPass  		log("    -nowidelut\n");  		log("        do not use MUXF[78] resources to implement LUTs larger than LUT6s\n");  		log("\n"); +		log("    -widemux <int>\n"); +		log("        enable inference of hard multiplexer resources (MuxFx) for muxes at or\n"); +		log("        above this number of inputs (minimum value 5).\n"); +		log("        default: 0 (no inference)\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"); @@ -99,6 +104,7 @@ struct SynthXilinxPass : public ScriptPass  	std::string top_opt, edif_file, blif_file, family;  	bool flatten, retime, vpr, nobram, nodram, nosrl, nocarry, nowidelut, abc9; +	int widemux;  	void clear_flags() YS_OVERRIDE  	{ @@ -116,6 +122,7 @@ struct SynthXilinxPass : public ScriptPass  		nocarry = false;  		nowidelut = false;  		abc9 = false; +		widemux = 0;  	}  	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE @@ -186,6 +193,10 @@ struct SynthXilinxPass : public ScriptPass  				nosrl = true;  				continue;  			} +			if (args[argidx] == "-widemux" && argidx+1 < args.size()) { +				widemux = atoi(args[++argidx].c_str()); +				continue; +			}  			if (args[argidx] == "-abc9") {  				abc9 = true;  				continue; @@ -197,6 +208,9 @@ struct SynthXilinxPass : public ScriptPass  		if (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6s")  			log_cmd_error("Invalid Xilinx -family setting: %s\n", family.c_str()); +		if (widemux != 0 && widemux < 5) +			log_cmd_error("-widemux value must be 0 or >= 5.\n"); +  		if (!design->full_selection())  			log_cmd_error("This command only operates on fully selected designs!\n"); @@ -212,9 +226,9 @@ struct SynthXilinxPass : public ScriptPass  	{  		if (check_label("begin")) {  			if (vpr) -				run("read_verilog -lib -D _ABC -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); +				run("read_verilog -lib -icells -D _ABC -D_EXPLICIT_CARRY +/xilinx/cells_sim.v");  			else -				run("read_verilog -lib -D _ABC +/xilinx/cells_sim.v"); +				run("read_verilog -lib -icells -D _ABC +/xilinx/cells_sim.v");  			run("read_verilog -lib +/xilinx/cells_xtra.v"); @@ -224,26 +238,21 @@ struct SynthXilinxPass : public ScriptPass  			run(stringf("hierarchy -check %s", top_opt.c_str()));  		} -		if (check_label("flatten", "(with '-flatten' only)")) { -			if (flatten || help_mode) { -				run("proc"); -				run("flatten"); -			} -		} -  		if (check_label("coarse")) { -			run("synth -run coarse"); +			if (help_mode) +				run("synth -run coarse [-flatten]", "(with '-flatten')"); +			else +				run("synth -run coarse" + std::string(flatten ? "" : " -flatten"), "(with '-flatten')"); + +			if (widemux > 0 || help_mode) +				run("muxpack", "    ('-widemux' only)");  			// shregmap -tech xilinx can cope with $shiftx and $mux  			//   cells for identifying variable-length shift registers,  			//   so attempt to convert $pmux-es to the former -			if (!nosrl || help_mode) -				run("pmux2shiftx", "(skip if '-nosrl')"); - -			// Run a number of peephole optimisations, including one -			//   that optimises $mul cells driving $shiftx's B input -			//   and that aids wide mux analysis -			run("peepopt"); +			// Also: wide multiplexer inference benefits from this too +			if (!(nosrl && widemux == 0) || help_mode) +				run("pmux2shiftx", "(skip if '-nosrl' and '-widemux' < 5)");  		}  		if (check_label("bram", "(skip if '-nobram')")) { @@ -265,32 +274,65 @@ struct SynthXilinxPass : public ScriptPass  			run("memory_map");  			run("dffsr2dff");  			run("dff2dffe"); +			if (help_mode) { +				run("simplemap t:$mux", "         ('-widemux' only)"); +				run("muxcover <internal options>, ('-widemux' only)"); +			} +			else if (widemux > 0) { +				run("simplemap t:$mux"); +				std::string muxcover_args = " -nodecode"; +				switch (widemux) { +					// NB: Cost of mux2 is 100; mux8 should cost between 3 and 4 +					//     of those so that 4:1 muxes and below are implemented +					//     out of mux2s +					case  5: muxcover_args += " -mux8=350 -mux16=400"; break; +					case  6: muxcover_args += " -mux8=450 -mux16=500"; break; +					case  7: muxcover_args += " -mux8=550 -mux16=600"; break; +					case  8: muxcover_args += " -mux8=650 -mux16=700"; break; +					case  9: muxcover_args += " -mux16=750"; break; +					case 10: muxcover_args += " -mux16=850"; break; +					case 11: muxcover_args += " -mux16=950"; break; +					case 12: muxcover_args += " -mux16=1050"; break; +					case 13: muxcover_args += " -mux16=1150"; break; +					case 14: muxcover_args += " -mux16=1250"; break; +					case 15: muxcover_args += " -mux16=1350"; break; +					default: muxcover_args += " -mux16=1450"; break; +				} +				run("muxcover " + muxcover_args); +			}  			run("opt -full");  			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')"); +				run("simplemap t:$dff t:$dffe", "       (skip if '-nosrl')");  				// shregmap with '-tech xilinx' infers variable length shift regs  				run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')");  			} -			std::string techmap_files = " -map +/techmap.v"; +			std::string techmap_args = " -map +/techmap.v"; +			if (help_mode) +				techmap_args += " [-map +/xilinx/mux_map.v]"; +			else if (widemux > 0) +				techmap_args += stringf(" -D MIN_MUX_INPUTS=%d -map +/xilinx/mux_map.v", widemux);  			if (help_mode) -				techmap_files += " [-map +/xilinx/arith_map.v]"; +				techmap_args += " [-map +/xilinx/arith_map.v]";  			else if (!nocarry) { -				techmap_files += " -map +/xilinx/arith_map.v"; +				techmap_args += " -map +/xilinx/arith_map.v";  				if (vpr) -					techmap_files += " -D _EXPLICIT_CARRY"; +					techmap_args += " -D _EXPLICIT_CARRY";  				else if (abc9) -					techmap_files += " -D _CLB_CARRY"; +					techmap_args += " -D _CLB_CARRY";  			} -			run("techmap " + techmap_files); +			run("techmap " + techmap_args);  			run("opt -fast");  		}  		if (check_label("map_cells")) { -			run("techmap -map +/techmap.v -map +/xilinx/cells_map.v"); +			std::string techmap_args = "-map +/techmap.v -D _ABC -map +/xilinx/cells_map.v"; +			if (widemux > 0) +				techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", widemux); +			run("techmap " + techmap_args);  			run("clean");  		}  | 
