mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master' into xc7dsp
This commit is contained in:
		
						commit
						cea7441d8a
					
				
					 34 changed files with 738 additions and 275 deletions
				
			
		| 
						 | 
				
			
			@ -56,7 +56,6 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o
 | 
			
		|||
  localparam [DEPTH-1:0] INIT_R = brev(INIT);
 | 
			
		||||
 | 
			
		||||
  parameter _TECHMAP_CONSTMSK_L_ = 0;
 | 
			
		||||
  parameter _TECHMAP_CONSTVAL_L_ = 0;
 | 
			
		||||
 | 
			
		||||
  wire CE;
 | 
			
		||||
  generate
 | 
			
		||||
| 
						 | 
				
			
			@ -119,26 +118,33 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o
 | 
			
		|||
      else
 | 
			
		||||
        \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(T6), .S0(L[5]), .S1(L[6]), .O(Q));
 | 
			
		||||
    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));
 | 
			
		||||
    // For fixed length, if just 1 over a convenient value, decompose
 | 
			
		||||
    else if (DEPTH <= 129 && &_TECHMAP_CONSTMSK_L_) begin
 | 
			
		||||
      wire T;
 | 
			
		||||
      \$__XILINX_SHREG_ #(.DEPTH(DEPTH-1), .INIT(INIT[DEPTH-1:1]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl      (.C(C), .D(D), .L({32{1'b1}}), .E(E), .Q(T));
 | 
			
		||||
      \$__XILINX_SHREG_ #(.DEPTH(1),       .INIT(INIT[0]),         .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_last (.C(C), .D(T), .L(L), .E(E), .Q(Q));
 | 
			
		||||
    end
 | 
			
		||||
    // For variable length, if just 1 over a convenient value, then bump up one more
 | 
			
		||||
    else if (DEPTH < 129 && ~&_TECHMAP_CONSTMSK_L_)
 | 
			
		||||
      \$__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));
 | 
			
		||||
    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;
 | 
			
		||||
      localparam depth0 = 128;
 | 
			
		||||
      localparam num_srl128 = DEPTH / depth0;
 | 
			
		||||
      localparam depthN = DEPTH % depth0;
 | 
			
		||||
      wire [num_srl128 + (depthN > 0 ? 1 : 0) - 1:0] T;
 | 
			
		||||
      wire [num_srl128 + (depthN > 0 ? 1 : 0) :0] S;
 | 
			
		||||
      assign S[0] = D;
 | 
			
		||||
      genvar i;
 | 
			
		||||
      for (i = 0; i < num_srl128; i++)
 | 
			
		||||
        \$__XILINX_SHREG_ #(.DEPTH(depth0), .INIT(INIT[DEPTH-1-i*depth0-:depth0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl      (.C(C), .D(S[i]),          .L(L[$clog2(depth0)-1:0]), .E(E), .Q(T[i]), .SO(S[i+1]));
 | 
			
		||||
 | 
			
		||||
      if (depthN > 0)
 | 
			
		||||
        \$__XILINX_SHREG_ #(.DEPTH(depthN), .INIT(INIT[depthN-1:0]),               .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_last (.C(C), .D(S[num_srl128]), .L(L[$clog2(depth0)-1:0]), .E(E), .Q(T[num_srl128]));
 | 
			
		||||
 | 
			
		||||
      if (&_TECHMAP_CONSTMSK_L_)
 | 
			
		||||
        assign Q = T[num_srl128 + (depthN > 0 ? 1 : 0) - 1];
 | 
			
		||||
      else
 | 
			
		||||
        assign Q = T[L[DEPTH-1:$clog2(depth0)]];
 | 
			
		||||
    end
 | 
			
		||||
  endgenerate
 | 
			
		||||
endmodule
 | 
			
		||||
| 
						 | 
				
			
			@ -193,45 +199,89 @@ module \$__XILINX_SHIFTX (A, B, Y);
 | 
			
		|||
    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));
 | 
			
		||||
    else if (A_WIDTH == 2) begin
 | 
			
		||||
      MUXF7 fpga_hard_mux (.I0(A[0]), .I1(A[1]), .S(B[0]), .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));
 | 
			
		||||
    else if (A_WIDTH <= 4) begin
 | 
			
		||||
      wire [4-1:0] Ax;
 | 
			
		||||
      if (A_WIDTH == 4)
 | 
			
		||||
        assign Ax = A;
 | 
			
		||||
      else
 | 
			
		||||
        // Rather than extend with 1'bx which gets flattened to 1'b0
 | 
			
		||||
        // causing the "don't care" status to get lost, extend with
 | 
			
		||||
        // the same driver of F7B.I0 so that we can optimise F7B away
 | 
			
		||||
        // later
 | 
			
		||||
        assign Ax = {A[1], A};
 | 
			
		||||
      \$__XILINX_MUXF78 fpga_hard_mux (.I0(Ax[0]), .I1(Ax[2]), .I2(Ax[1]), .I3(Ax[3]), .S0(B[1]), .S1(B[0]), .O(Y));
 | 
			
		||||
    end
 | 
			
		||||
    // Note that the following decompositions are 'backwards' in that
 | 
			
		||||
    // the LSBs are placed on the hard resources, and the soft resources
 | 
			
		||||
    // are used for MSBs.
 | 
			
		||||
    // This has the effect of more effectively utilising the hard mux;
 | 
			
		||||
    // take for example a 5:1 multiplexer, currently this would map as:
 | 
			
		||||
    //
 | 
			
		||||
    //     A[0] \___  __                             A[0] \__  __
 | 
			
		||||
    //     A[4] /   \|  \       whereas the more     A[1] /  \|  \
 | 
			
		||||
    //     A[1] _____|   |      obvious mapping      A[2] \___|   |
 | 
			
		||||
    //     A[2] _____|   |--    of MSBs to hard      A[3] /   |   |__
 | 
			
		||||
    //     A[3]______|   |      resources would      A[4] ____|   |
 | 
			
		||||
    //               |__/       lead to:             1'bx ____|   |
 | 
			
		||||
    //                ||                                      |__/
 | 
			
		||||
    //                ||                                       ||
 | 
			
		||||
    //              B[1:0]                                   B[1:2]
 | 
			
		||||
    //
 | 
			
		||||
    // Expectation would be that the 'forward' mapping (right) is more
 | 
			
		||||
    // area efficient (consider a 9:1 multiplexer using 2x4:1 multiplexers
 | 
			
		||||
    // on its I0 and I1 inputs, and A[8] and 1'bx on its I2 and I3 inputs)
 | 
			
		||||
    // but that the 'backwards' mapping (left) is more delay efficient
 | 
			
		||||
    // since smaller LUTs are faster than wider ones.
 | 
			
		||||
    else if (A_WIDTH <= 8) begin
 | 
			
		||||
      wire [8-1:0] Ax = {{{8-A_WIDTH}{1'bx}}, A};
 | 
			
		||||
      wire T0 = B[2] ? Ax[4] : Ax[0];
 | 
			
		||||
      wire T1 = B[2] ? Ax[5] : Ax[1];
 | 
			
		||||
      wire T2 = B[2] ? Ax[6] : Ax[2];
 | 
			
		||||
      wire T3 = B[2] ? Ax[7] : Ax[3];
 | 
			
		||||
      \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T1), .I3(T3), .S0(B[1]), .S1(B[0]), .O(Y));
 | 
			
		||||
    end
 | 
			
		||||
    else if (A_WIDTH <= 16) begin
 | 
			
		||||
      wire [16-1:0] Ax = {{{16-A_WIDTH}{1'bx}}, A};
 | 
			
		||||
      wire T0 = B[2] ? B[3] ? Ax[12] : Ax[4]
 | 
			
		||||
                     : B[3] ? Ax[ 8] : Ax[0];
 | 
			
		||||
      wire T1 = B[2] ? B[3] ? Ax[13] : Ax[5]
 | 
			
		||||
                     : B[3] ? Ax[ 9] : Ax[1];
 | 
			
		||||
      wire T2 = B[2] ? B[3] ? Ax[14] : Ax[6]
 | 
			
		||||
                     : B[3] ? Ax[10] : Ax[2];
 | 
			
		||||
      wire T3 = B[2] ? B[3] ? Ax[15] : Ax[7]
 | 
			
		||||
                     : B[3] ? Ax[11] : Ax[3];
 | 
			
		||||
      \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T1), .I3(T3), .S0(B[1]), .S1(B[0]), .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;
 | 
			
		||||
      localparam num_mux16 = (A_WIDTH+15) / 16;
 | 
			
		||||
      localparam clog2_num_mux16 = $clog2(num_mux16);
 | 
			
		||||
      wire [num_mux16-1:0] T;
 | 
			
		||||
      wire [num_mux16*16-1:0] Ax = {{(num_mux16*16-A_WIDTH){1'bx}}, A};
 | 
			
		||||
      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));
 | 
			
		||||
        \$__XILINX_SHIFTX  #(
 | 
			
		||||
          .A_SIGNED(A_SIGNED),
 | 
			
		||||
          .B_SIGNED(B_SIGNED),
 | 
			
		||||
          .A_WIDTH(16),
 | 
			
		||||
          .B_WIDTH(4),
 | 
			
		||||
          .Y_WIDTH(Y_WIDTH)
 | 
			
		||||
        ) fpga_mux (
 | 
			
		||||
          .A(Ax[i*16+:16]),
 | 
			
		||||
          .B(B[3:0]),
 | 
			
		||||
          .Y(T[i])
 | 
			
		||||
        );
 | 
			
		||||
      \$__XILINX_SHIFTX  #(
 | 
			
		||||
          .A_SIGNED(A_SIGNED),
 | 
			
		||||
          .B_SIGNED(B_SIGNED),
 | 
			
		||||
          .A_WIDTH(num_mux16),
 | 
			
		||||
          .B_WIDTH(clog2_num_mux16),
 | 
			
		||||
          .Y_WIDTH(Y_WIDTH)
 | 
			
		||||
      ) _TECHMAP_REPLACE_ (
 | 
			
		||||
          .A(T),
 | 
			
		||||
          .B(B[B_WIDTH-1-:clog2_num_mux16]),
 | 
			
		||||
          .Y(Y));
 | 
			
		||||
    end
 | 
			
		||||
  endgenerate
 | 
			
		||||
endmodule
 | 
			
		||||
| 
						 | 
				
			
			@ -251,15 +301,32 @@ module _90__XILINX_SHIFTX (A, B, 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 \$_MUX_ (A, B, S, Y);
 | 
			
		||||
  input A, B, S;
 | 
			
		||||
  output Y;
 | 
			
		||||
  generate
 | 
			
		||||
    if (`MIN_MUX_INPUTS == 2)
 | 
			
		||||
      \$__XILINX_SHIFTX  #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(2), .B_WIDTH(1), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({B,A}), .B(S), .Y(Y));
 | 
			
		||||
    else
 | 
			
		||||
      wire _TECHMAP_FAIL_ = 1;
 | 
			
		||||
  endgenerate
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module \$_MUX4_ (A, B, C, D, S, T, Y);
 | 
			
		||||
  input A, B, C, D, S, T;
 | 
			
		||||
  output Y;
 | 
			
		||||
  \$__XILINX_SHIFTX  #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(4), .B_WIDTH(2), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({D,C,B,A}), .B({T,S}), .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;
 | 
			
		||||
  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;
 | 
			
		||||
  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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
 *  yosys -- Yosys Open SYnthesis Suite
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 | 
			
		||||
 *            (C) 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
 | 
			
		||||
| 
						 | 
				
			
			@ -25,8 +26,8 @@
 | 
			
		|||
USING_YOSYS_NAMESPACE
 | 
			
		||||
PRIVATE_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
#define XC7_WIRE_DELAY "300" // Number with which ABC will map a 6-input gate
 | 
			
		||||
                             // to one LUT6 (instead of a LUT5 + LUT2)
 | 
			
		||||
#define XC7_WIRE_DELAY 300 // Number with which ABC will map a 6-input gate
 | 
			
		||||
                           // to one LUT6 (instead of a LUT5 + LUT2)
 | 
			
		||||
 | 
			
		||||
struct SynthXilinxPass : public ScriptPass
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -81,8 +82,8 @@ struct SynthXilinxPass : public ScriptPass
 | 
			
		|||
		log("        do not use DSP48E1s to implement multipliers and associated logic\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("        enable inference of hard multiplexer resources (MUXF[78]) for muxes at or\n");
 | 
			
		||||
		log("        above this number of inputs (minimum value 2, recommended value >= 5).\n");
 | 
			
		||||
		log("        default: 0 (no inference)\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -run <from_label>:<to_label>\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -198,7 +199,7 @@ struct SynthXilinxPass : public ScriptPass
 | 
			
		|||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-widemux" && argidx+1 < args.size()) {
 | 
			
		||||
				widemux = atoi(args[++argidx].c_str());
 | 
			
		||||
				widemux = std::stoi(args[++argidx]);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-abc9") {
 | 
			
		||||
| 
						 | 
				
			
			@ -214,14 +215,17 @@ struct SynthXilinxPass : public ScriptPass
 | 
			
		|||
		extra_args(args, argidx, design);
 | 
			
		||||
 | 
			
		||||
		if (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6s")
 | 
			
		||||
			log_cmd_error("Invalid Xilinx -family setting: %s\n", family.c_str());
 | 
			
		||||
			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 (widemux != 0 && widemux < 2)
 | 
			
		||||
			log_cmd_error("-widemux value must be 0 or >= 2.\n");
 | 
			
		||||
 | 
			
		||||
		if (!design->full_selection())
 | 
			
		||||
			log_cmd_error("This command only operates on fully selected designs!\n");
 | 
			
		||||
 | 
			
		||||
		if (abc9 && retime)
 | 
			
		||||
			log_cmd_error("-retime option not currently compatible with -abc9!\n");
 | 
			
		||||
 | 
			
		||||
		log_header(design, "Executing SYNTH_XILINX pass.\n");
 | 
			
		||||
		log_push();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -254,24 +258,12 @@ struct SynthXilinxPass : public ScriptPass
 | 
			
		|||
			run("opt_clean");
 | 
			
		||||
			run("check");
 | 
			
		||||
			run("opt");
 | 
			
		||||
			run("wreduce");
 | 
			
		||||
			if (help_mode)
 | 
			
		||||
				run("wreduce [-keepdc]", "(option for '-widemux')");
 | 
			
		||||
			else
 | 
			
		||||
				run("wreduce" + std::string(widemux > 0 ? " -keepdc" : ""));
 | 
			
		||||
			run("peepopt");
 | 
			
		||||
			run("opt_clean");
 | 
			
		||||
			run("share");
 | 
			
		||||
			run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4");
 | 
			
		||||
			run("opt_expr");
 | 
			
		||||
			run("opt_clean");
 | 
			
		||||
			if (!nodsp || help_mode) {
 | 
			
		||||
				run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 -D DSP_NAME=$__MUL25X18");
 | 
			
		||||
				run("clean");
 | 
			
		||||
				run("techmap -map +/xilinx/dsp_map.v");
 | 
			
		||||
			}
 | 
			
		||||
			run("alumacc");
 | 
			
		||||
			run("opt");
 | 
			
		||||
			run("fsm");
 | 
			
		||||
			run("opt -fast");
 | 
			
		||||
			run("memory -nomap");
 | 
			
		||||
			run("opt_clean");
 | 
			
		||||
 | 
			
		||||
			if (widemux > 0 || help_mode)
 | 
			
		||||
				run("muxpack", "    ('-widemux' only)");
 | 
			
		||||
| 
						 | 
				
			
			@ -280,8 +272,26 @@ struct SynthXilinxPass : public ScriptPass
 | 
			
		|||
			//   cells for identifying variable-length shift registers,
 | 
			
		||||
			//   so attempt to convert $pmux-es to the former
 | 
			
		||||
			// Also: wide multiplexer inference benefits from this too
 | 
			
		||||
			if (!(nosrl && widemux == 0) || help_mode)
 | 
			
		||||
				run("pmux2shiftx", "(skip if '-nosrl' and '-widemux' < 5)");
 | 
			
		||||
			if (!(nosrl && widemux == 0) || help_mode) {
 | 
			
		||||
				run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')");
 | 
			
		||||
				run("clean", "      (skip if '-nosrl' and '-widemux=0')");
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6");
 | 
			
		||||
 | 
			
		||||
			if (!nodsp || help_mode) {
 | 
			
		||||
				run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 -D DSP_NAME=$__MUL25X18");
 | 
			
		||||
				run("clean");
 | 
			
		||||
				run("techmap -map +/xilinx/dsp_map.v");
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			run("alumacc");
 | 
			
		||||
			run("share");
 | 
			
		||||
			run("opt");
 | 
			
		||||
			run("fsm");
 | 
			
		||||
			run("opt -fast");
 | 
			
		||||
			run("memory -nomap");
 | 
			
		||||
			run("opt_clean");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (check_label("bram", "(skip if '-nobram')")) {
 | 
			
		||||
| 
						 | 
				
			
			@ -299,7 +309,11 @@ struct SynthXilinxPass : public ScriptPass
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		if (check_label("fine")) {
 | 
			
		||||
			run("opt -fast -full");
 | 
			
		||||
			if (widemux > 0)
 | 
			
		||||
				run("opt -fast -mux_bool -undriven -fine"); // Necessary to omit -mux_undef otherwise muxcover
 | 
			
		||||
									    // performs less efficiently
 | 
			
		||||
			else
 | 
			
		||||
				run("opt -fast -full");
 | 
			
		||||
			run("memory_map");
 | 
			
		||||
			run("dffsr2dff");
 | 
			
		||||
			run("dff2dffe");
 | 
			
		||||
| 
						 | 
				
			
			@ -309,23 +323,24 @@ struct SynthXilinxPass : public ScriptPass
 | 
			
		|||
			}
 | 
			
		||||
			else if (widemux > 0) {
 | 
			
		||||
				run("simplemap t:$mux");
 | 
			
		||||
				std::string muxcover_args = " -nodecode";
 | 
			
		||||
				constexpr int cost_mux2 = 100;
 | 
			
		||||
				std::string muxcover_args = stringf(" -nodecode -mux2=%d", cost_mux2);
 | 
			
		||||
				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;
 | 
			
		||||
					case  2: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2+1, cost_mux2+2, cost_mux2+3); break;
 | 
			
		||||
					case  3:
 | 
			
		||||
					case  4: muxcover_args += stringf(" -mux4=%d -mux8=%d -mux16=%d", cost_mux2*(widemux-1)-2, cost_mux2*(widemux-1)-1, cost_mux2*(widemux-1)); break;
 | 
			
		||||
					case  5:
 | 
			
		||||
					case  6:
 | 
			
		||||
					case  7:
 | 
			
		||||
					case  8: muxcover_args += stringf(" -mux8=%d -mux16=%d", cost_mux2*(widemux-1)-1, cost_mux2*(widemux-1)); break;
 | 
			
		||||
					case  9:
 | 
			
		||||
					case 10:
 | 
			
		||||
					case 11:
 | 
			
		||||
					case 12:
 | 
			
		||||
					case 13:
 | 
			
		||||
					case 14:
 | 
			
		||||
					case 15:
 | 
			
		||||
					default: muxcover_args += stringf(" -mux16=%d", cost_mux2*(widemux-1)-1); break;
 | 
			
		||||
				}
 | 
			
		||||
				run("muxcover " + muxcover_args);
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -368,14 +383,14 @@ struct SynthXilinxPass : public ScriptPass
 | 
			
		|||
		if (check_label("map_luts")) {
 | 
			
		||||
			run("opt_expr -mux_undef");
 | 
			
		||||
			if (help_mode)
 | 
			
		||||
				run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(skip if 'nowidelut', only for '-retime')");
 | 
			
		||||
				run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(option for 'nowidelut', option for '-retime')");
 | 
			
		||||
			else if (abc9) {
 | 
			
		||||
				if (family != "xc7")
 | 
			
		||||
					log_warning("'synth_xilinx -abc9' currently supports '-family xc7' only.\n");
 | 
			
		||||
				if (nowidelut)
 | 
			
		||||
					run("abc9 -lut +/xilinx/abc_xc7_nowide.lut -box +/xilinx/abc_xc7.box -W " + std::string(XC7_WIRE_DELAY) + string(retime ? " -dff" : ""));
 | 
			
		||||
					run("abc9 -lut +/xilinx/abc_xc7_nowide.lut -box +/xilinx/abc_xc7.box -W " + std::to_string(XC7_WIRE_DELAY));
 | 
			
		||||
				else
 | 
			
		||||
					run("abc9 -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W " + std::string(XC7_WIRE_DELAY) + string(retime ? " -dff" : ""));
 | 
			
		||||
					run("abc9 -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W " + std::to_string(XC7_WIRE_DELAY));
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				if (nowidelut)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue