mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master' into xaig_dff
This commit is contained in:
		
						commit
						052060f109
					
				
					 39 changed files with 1000 additions and 247 deletions
				
			
		|  | @ -2,7 +2,7 @@ | |||
|  *  yosys -- Yosys Open SYnthesis Suite | ||||
|  * | ||||
|  *  Copyright (C) 2012 Clifford Wolf <clifford@clifford.at> | ||||
|  *  Copyright (C) 2018 Clifford Wolf <dave@ds0.me> | ||||
|  *  Copyright (C) 2018 David Shah <dave@ds0.me> | ||||
|  * | ||||
|  *  Permission to use, copy, modify, and/or distribute this software for any | ||||
|  *  purpose with or without fee is hereby granted, provided that the above | ||||
|  | @ -199,6 +199,9 @@ struct SynthEcp5Pass : public ScriptPass | |||
| 		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_ECP5 pass.\n"); | ||||
| 		log_push(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -227,6 +227,9 @@ struct SynthIce40Pass : public ScriptPass | |||
| 		if (device_opt != "hx" && device_opt != "lp" && device_opt !="u") | ||||
| 			log_cmd_error("Invalid or no device specified: '%s'\n", device_opt.c_str()); | ||||
| 
 | ||||
| 		if (abc == "abc9" && retime) | ||||
| 			log_cmd_error("-retime option not currently compatible with -abc9!\n"); | ||||
| 
 | ||||
| 		log_header(design, "Executing SYNTH_ICE40 pass.\n"); | ||||
| 		log_push(); | ||||
| 
 | ||||
|  | @ -296,7 +299,7 @@ struct SynthIce40Pass : public ScriptPass | |||
| 				run("techmap"); | ||||
| 			else | ||||
| 				run("techmap -map +/techmap.v -map +/ice40/arith_map.v"); | ||||
| 			if ((retime || help_mode) && abc != "abc9") | ||||
| 			if (retime || help_mode) | ||||
| 				run(abc + " -dff", "(only if -retime)"); | ||||
| 			run("ice40_opt"); | ||||
| 		} | ||||
|  |  | |||
|  | @ -48,6 +48,8 @@ struct SynthIntelPass : public ScriptPass { | |||
| 		log("    -vqm <file>\n"); | ||||
| 		log("        write the design to the specified Verilog Quartus Mapping File. Writing of an\n"); | ||||
| 		log("        output file is omitted if this parameter is not specified.\n"); | ||||
| 		log("        Note that this backend has not been tested and is likely incompatible\n"); | ||||
| 		log("        with recent versions of Quartus.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -vpr <file>\n"); | ||||
| 		log("        write BLIF files for VPR flow experiments. The synthesized BLIF output file is not\n"); | ||||
|  | @ -108,6 +110,7 @@ struct SynthIntelPass : public ScriptPass { | |||
| 			} | ||||
| 			if (args[argidx] == "-vqm" && argidx + 1 < args.size()) { | ||||
| 				vout_file = args[++argidx]; | ||||
| 				log_warning("The Quartus backend has not been tested recently and is likely incompatible with modern versions of Quartus.\n"); | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-vpr" && argidx + 1 < args.size()) { | ||||
|  |  | |||
|  | @ -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_ff.v)) | ||||
| $(eval $(call add_share_file,share/xilinx,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 | ||||
| 294 297 311 317 390 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,21 +39,21 @@ 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 - -    -   -   -   -   -   -   - - | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 | ||||
|  | @ -94,11 +93,8 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o | |||
|       \$__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 | ||||
|       else | ||||
|         \$__XILINX_MUXF78 fpga_hard_mux (.I0(T0), .I1(T2), .I2(T4), .I3(1'bx), .S0(L[5]), .S1(L[6]), .O(Q)); | ||||
|     end else | ||||
|     if (DEPTH > 97 && DEPTH < 128) begin | ||||
|       wire T0, T1, T2, T3, T4, T5, T6, T7, T8; | ||||
|  | @ -108,11 +104,8 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o | |||
|       \$__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 | ||||
|       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 == 128) begin | ||||
|       wire T0, T1, T2, T3, T4, T5, T6; | ||||
|  | @ -122,33 +115,253 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o | |||
|       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 | ||||
|       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 | ||||
|     // 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)); | ||||
|     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; | ||||
|       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 | ||||
| 
 | ||||
| `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 A_WIDTH_trimmed; | ||||
|     input integer start; | ||||
|   begin | ||||
|     A_WIDTH_trimmed = start; | ||||
|     while (A_WIDTH_trimmed > 0 && _TECHMAP_CONSTMSK_A_[A_WIDTH_trimmed-1] && _TECHMAP_CONSTVAL_A_[A_WIDTH_trimmed-1] === 1'bx) | ||||
|       A_WIDTH_trimmed = A_WIDTH_trimmed - 1; | ||||
|   end | ||||
|   endfunction | ||||
| 
 | ||||
|   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 | ||||
|     else if (_TECHMAP_CONSTMSK_A_[A_WIDTH-1] && _TECHMAP_CONSTVAL_A_[A_WIDTH-1] === 1'bx) begin | ||||
|       localparam A_WIDTH_new = A_WIDTH_trimmed(A_WIDTH-1); | ||||
|       \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B), .Y(Y)); | ||||
|     end | ||||
|     else if (A_WIDTH < `MIN_MUX_INPUTS) begin | ||||
|       wire _TECHMAP_FAIL_ = 1; | ||||
|     end | ||||
|     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 <= 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 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(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 | ||||
| 
 | ||||
| (* 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 \$_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; | ||||
|   \$__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 | ||||
|  |  | |||
|  | @ -169,11 +169,19 @@ 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 | ||||
| 
 | ||||
| (* abc_box_id = 3, abc_carry="CI,CO", lib_whitebox *) | ||||
| (* abc_box_id = 4, abc_carry="CI,CO", lib_whitebox *) | ||||
| module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S); | ||||
|   assign O = S ^ {CO[2:0], CI | CYINIT}; | ||||
|   assign CO[0] = S[0] ? CI | CYINIT : DI[0]; | ||||
|  | @ -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, | ||||
|  |  | |||
							
								
								
									
										71
									
								
								techlibs/xilinx/mux_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								techlibs/xilinx/mux_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -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 | ||||
|  | @ -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 | ||||
| { | ||||
|  | @ -77,6 +78,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 (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"); | ||||
| 		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 +105,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 +123,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 +194,10 @@ struct SynthXilinxPass : public ScriptPass | |||
| 				nosrl = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-widemux" && argidx+1 < args.size()) { | ||||
| 				widemux = std::stoi(args[++argidx]); | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-abc9") { | ||||
| 				abc9 = true; | ||||
| 				continue; | ||||
|  | @ -195,11 +207,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 < 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(); | ||||
| 
 | ||||
|  | @ -212,9 +230,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,21 +242,41 @@ 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"); | ||||
| 			run("proc"); | ||||
| 			if (help_mode || flatten) | ||||
| 				run("flatten", "(if -flatten)"); | ||||
| 			run("opt_expr"); | ||||
| 			run("opt_clean"); | ||||
| 			run("check"); | ||||
| 			run("opt"); | ||||
| 			if (help_mode) | ||||
| 				run("wreduce [-keepdc]", "(option for '-widemux')"); | ||||
| 			else | ||||
| 				run("wreduce" + std::string(widemux > 0 ? " -keepdc" : "")); | ||||
| 			run("peepopt"); | ||||
| 			run("opt_clean"); | ||||
| 
 | ||||
| 			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')"); | ||||
| 			// Also: wide multiplexer inference benefits from this too
 | ||||
| 			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"); | ||||
| 			run("alumacc"); | ||||
| 			run("share"); | ||||
| 			run("opt"); | ||||
| 			run("fsm"); | ||||
| 			run("opt -fast"); | ||||
| 			run("memory -nomap"); | ||||
| 			run("opt_clean"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("bram", "(skip if '-nobram')")) { | ||||
|  | @ -256,54 +294,89 @@ 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"); | ||||
| 			if (help_mode) { | ||||
| 				run("simplemap t:$mux", "         ('-widemux' only)"); | ||||
| 				run("muxcover <internal options>, ('-widemux' only)"); | ||||
| 			} | ||||
| 			else if (widemux > 0) { | ||||
| 				run("simplemap t:$mux"); | ||||
| 				constexpr int cost_mux2 = 100; | ||||
| 				std::string muxcover_args = stringf(" -nodecode -mux2=%d", cost_mux2); | ||||
| 				switch (widemux) { | ||||
| 					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); | ||||
| 			} | ||||
| 			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_files += " [-map +/xilinx/arith_map.v]"; | ||||
| 				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_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")) { | ||||
| 			if (abc9) | ||||
| 				run("techmap -map +/techmap.v -map +/xilinx/cells_map.v -D _ABC -map +/xilinx/ff_map.v"); | ||||
| 			else | ||||
| 				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"); | ||||
| 		} | ||||
| 
 | ||||
| 		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"); | ||||
| 				run("read_verilog -icells -lib +/xilinx/abc_ff.v"); | ||||
| 				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