mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Merge pull request #1660 from YosysHQ/eddie/abc9_unpermute_luts
Unpermute LUT ordering for ice40/ecp5/xilinx
This commit is contained in:
		
						commit
						7939727d14
					
				
					 9 changed files with 201 additions and 143 deletions
				
			
		|  | @ -422,6 +422,8 @@ void AigerReader::parse_xaiger() | |||
| 					log_assert(wire); | ||||
| 					input_sig.append(wire); | ||||
| 				} | ||||
| 				// Reverse input order as fastest input is returned first
 | ||||
| 				input_sig.reverse(); | ||||
| 				// TODO: Compute LUT mask from AIG in less than O(2 ** input_sig.size())
 | ||||
| 				ce.clear(); | ||||
| 				ce.compute_deps(output_sig, input_sig.to_sigbit_pool()); | ||||
|  |  | |||
|  | @ -851,6 +851,8 @@ public: | |||
| 
 | ||||
| 	RTLIL::SigSpec repeat(int num) const; | ||||
| 
 | ||||
| 	void reverse() { inline_unpack(); std::reverse(bits_.begin(), bits_.end()); } | ||||
| 
 | ||||
| 	bool operator <(const RTLIL::SigSpec &other) const; | ||||
| 	bool operator ==(const RTLIL::SigSpec &other) const; | ||||
| 	inline bool operator !=(const RTLIL::SigSpec &other) const { return !(*this == other); } | ||||
|  |  | |||
|  | @ -127,7 +127,7 @@ struct Ice40WrapCarryPass : public Pass { | |||
| 					lut->setParam(ID(WIDTH), 4); | ||||
| 					lut->setParam(ID(LUT), cell->getParam(ID(LUT))); | ||||
| 					auto I3 = cell->getPort(cell->getParam(ID(I3_IS_CI)).as_bool() ? ID(CI) : ID(I3)); | ||||
| 					lut->setPort(ID(A), {cell->getPort(ID(I0)), cell->getPort(ID(A)), cell->getPort(ID(B)), I3 }); | ||||
| 					lut->setPort(ID(A), { I3, cell->getPort(ID(B)), cell->getPort(ID(A)), cell->getPort(ID(I0)) }); | ||||
| 					lut->setPort(ID(Y), cell->getPort(ID(O))); | ||||
| 
 | ||||
| 					Const src; | ||||
|  |  | |||
|  | @ -73,102 +73,80 @@ module \$lut (A, Y); | |||
|     input [WIDTH-1:0] A; | ||||
|     output Y; | ||||
| 
 | ||||
|     // Need to swap input ordering, and fix init accordingly, | ||||
|     // to match ABC's expectation of LUT inputs in non-decreasing | ||||
|     // delay order | ||||
|     localparam P_WIDTH = WIDTH < 4 ? 4 : WIDTH; | ||||
|     function [P_WIDTH-1:0] permute_index; | ||||
|         input [P_WIDTH-1:0] i; | ||||
|         integer j; | ||||
|         begin | ||||
|             permute_index = 0; | ||||
|             for (j = 0; j < P_WIDTH; j = j + 1) | ||||
|                 permute_index[P_WIDTH-1 - j] = i[j]; | ||||
|         end | ||||
|     endfunction | ||||
| 
 | ||||
|     function [2**P_WIDTH-1:0] permute_init; | ||||
|         integer i; | ||||
|         begin | ||||
|             permute_init = 0; | ||||
|             for (i = 0; i < 2**P_WIDTH; i = i + 1) | ||||
|                 permute_init[i] = LUT[permute_index(i)]; | ||||
|         end | ||||
|     endfunction | ||||
| 
 | ||||
|     parameter [2**P_WIDTH-1:0] P_LUT = permute_init(); | ||||
| 
 | ||||
|     generate | ||||
|         if (WIDTH == 1) begin | ||||
|             LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y), | ||||
|             localparam [15:0] INIT = {{8{LUT[1]}}, {8{LUT[0]}}}; | ||||
|             LUT4 #(.INIT(INIT)) _TECHMAP_REPLACE_ (.Z(Y), | ||||
|                 .A(1'b0), .B(1'b0), .C(1'b0), .D(A[0])); | ||||
|         end else | ||||
|         if (WIDTH == 2) begin | ||||
|             LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y), | ||||
|                 .A(1'b0), .B(1'b0), .C(A[1]), .D(A[0])); | ||||
|             localparam [15:0] INIT = {{4{LUT[3]}}, {4{LUT[2]}}, {4{LUT[1]}}, {4{LUT[0]}}}; | ||||
|             LUT4 #(.INIT(INIT)) _TECHMAP_REPLACE_ (.Z(Y), | ||||
|                 .A(1'b0), .B(1'b0), .C(A[0]), .D(A[1])); | ||||
|         end else | ||||
|         if (WIDTH == 3) begin | ||||
|             LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y), | ||||
|                 .A(1'b0), .B(A[2]), .C(A[1]), .D(A[0])); | ||||
|             localparam [15:0] INIT = {{2{LUT[7]}}, {2{LUT[6]}}, {2{LUT[5]}}, {2{LUT[4]}}, {2{LUT[3]}}, {2{LUT[2]}}, {2{LUT[1]}}, {2{LUT[0]}}}; | ||||
|             LUT4 #(.INIT(INIT)) _TECHMAP_REPLACE_ (.Z(Y), | ||||
|                 .A(1'b0), .B(A[0]), .C(A[1]), .D(A[2])); | ||||
|         end else | ||||
|         if (WIDTH == 4) begin | ||||
|             LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y), | ||||
|                 .A(A[3]), .B(A[2]), .C(A[1]), .D(A[0])); | ||||
|             LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y), | ||||
|                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||
|         `ifndef NO_PFUMUX | ||||
|         end else | ||||
|         if (WIDTH == 5) begin | ||||
|             wire f0, f1; | ||||
|             LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0), | ||||
|                 .A(A[4]), .B(A[3]), .C(A[2]), .D(A[1])); | ||||
|             LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1), | ||||
|                 .A(A[4]), .B(A[3]), .C(A[2]), .D(A[1])); | ||||
|             PFUMX mux5(.ALUT(f1), .BLUT(f0), .C0(A[0]), .Z(Y)); | ||||
|             LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0), | ||||
|                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||
|             LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1), | ||||
|                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||
|             PFUMX mux5(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(Y)); | ||||
|         end else | ||||
|         if (WIDTH == 6) begin | ||||
|             wire f0, f1, f2, f3, g0, g1; | ||||
|             LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0), | ||||
|                 .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2])); | ||||
|             LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1), | ||||
|                 .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2])); | ||||
|             LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0), | ||||
|                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||
|             LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1), | ||||
|                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||
| 
 | ||||
|             LUT4 #(.INIT(P_LUT[47:32])) lut2 (.Z(f2), | ||||
|                 .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2])); | ||||
|             LUT4 #(.INIT(P_LUT[63:48])) lut3 (.Z(f3), | ||||
|                 .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2])); | ||||
|             LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2), | ||||
|                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||
|             LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3), | ||||
|                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||
| 
 | ||||
|             PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[1]), .Z(g0)); | ||||
|             PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[1]), .Z(g1)); | ||||
|             L6MUX21 mux6 (.D0(g0), .D1(g1), .SD(A[0]), .Z(Y)); | ||||
|             PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0)); | ||||
|             PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1)); | ||||
|             L6MUX21 mux6 (.D0(g0), .D1(g1), .SD(A[5]), .Z(Y)); | ||||
|         end else | ||||
|         if (WIDTH == 7) begin | ||||
|             wire f0, f1, f2, f3, f4, f5, f6, f7, g0, g1, g2, g3, h0, h1; | ||||
|             LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0), | ||||
|                 .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); | ||||
|             LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1), | ||||
|                 .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); | ||||
|             LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0), | ||||
|                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||
|             LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1), | ||||
|                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||
| 
 | ||||
|             LUT4 #(.INIT(P_LUT[47:32])) lut2 (.Z(f2), | ||||
|                 .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); | ||||
|             LUT4 #(.INIT(P_LUT[63:48])) lut3 (.Z(f3), | ||||
|                 .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); | ||||
|             LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2), | ||||
|                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||
|             LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3), | ||||
|                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||
| 
 | ||||
|             LUT4 #(.INIT(P_LUT[79:64])) lut4 (.Z(f4), | ||||
|                 .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); | ||||
|             LUT4 #(.INIT(P_LUT[95:80])) lut5 (.Z(f5), | ||||
|                 .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); | ||||
|             LUT4 #(.INIT(LUT[79:64])) lut4 (.Z(f4), | ||||
|                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||
|             LUT4 #(.INIT(LUT[95:80])) lut5 (.Z(f5), | ||||
|                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||
| 
 | ||||
|             LUT4 #(.INIT(P_LUT[111: 96])) lut6 (.Z(f6), | ||||
|                 .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); | ||||
|             LUT4 #(.INIT(P_LUT[127:112])) lut7 (.Z(f7), | ||||
|                 .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); | ||||
|             LUT4 #(.INIT(LUT[111: 96])) lut6 (.Z(f6), | ||||
|                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||
|             LUT4 #(.INIT(LUT[127:112])) lut7 (.Z(f7), | ||||
|                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||
| 
 | ||||
|             PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[2]), .Z(g0)); | ||||
|             PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[2]), .Z(g1)); | ||||
|             PFUMX mux52(.ALUT(f5), .BLUT(f4), .C0(A[2]), .Z(g2)); | ||||
|             PFUMX mux53(.ALUT(f7), .BLUT(f6), .C0(A[2]), .Z(g3)); | ||||
|             L6MUX21 mux60 (.D0(g0), .D1(g1), .SD(A[1]), .Z(h0)); | ||||
|             L6MUX21 mux61 (.D0(g2), .D1(g3), .SD(A[1]), .Z(h1)); | ||||
|             L6MUX21 mux7  (.D0(h0), .D1(h1), .SD(A[0]), .Z(Y)); | ||||
|             PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0)); | ||||
|             PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1)); | ||||
|             PFUMX mux52(.ALUT(f5), .BLUT(f4), .C0(A[4]), .Z(g2)); | ||||
|             PFUMX mux53(.ALUT(f7), .BLUT(f6), .C0(A[4]), .Z(g3)); | ||||
|             L6MUX21 mux60 (.D0(g0), .D1(g1), .SD(A[5]), .Z(h0)); | ||||
|             L6MUX21 mux61 (.D0(g2), .D1(g3), .SD(A[5]), .Z(h1)); | ||||
|             L6MUX21 mux7  (.D0(h0), .D1(h1), .SD(A[6]), .Z(Y)); | ||||
|         `endif | ||||
|         end else begin | ||||
|             wire _TECHMAP_FAIL_ = 1; | ||||
|  |  | |||
|  | @ -42,19 +42,18 @@ module \$lut (A, Y); | |||
|         .I0(1'b0), .I1(1'b0), .I2(1'b0), .I3(A[0])); | ||||
|     end else | ||||
|     if (WIDTH == 2) begin | ||||
|       localparam [15:0] INIT = {{4{LUT[3]}}, {4{LUT[1]}}, {4{LUT[2]}}, {4{LUT[0]}}}; | ||||
|       localparam [15:0] INIT = {{4{LUT[3]}}, {4{LUT[2]}}, {4{LUT[1]}}, {4{LUT[0]}}}; | ||||
|       SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y), | ||||
|         .I0(1'b0), .I1(1'b0), .I2(A[1]), .I3(A[0])); | ||||
|         .I0(1'b0), .I1(1'b0), .I2(A[0]), .I3(A[1])); | ||||
|     end else | ||||
|     if (WIDTH == 3) begin | ||||
|       localparam [15:0] INIT = {{2{LUT[7]}}, {2{LUT[3]}}, {2{LUT[5]}}, {2{LUT[1]}}, {2{LUT[6]}}, {2{LUT[2]}}, {2{LUT[4]}}, {2{LUT[0]}}}; | ||||
|       localparam [15:0] INIT = {{2{LUT[7]}}, {2{LUT[6]}}, {2{LUT[5]}}, {2{LUT[4]}}, {2{LUT[3]}}, {2{LUT[2]}}, {2{LUT[1]}}, {2{LUT[0]}}}; | ||||
|       SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y), | ||||
|         .I0(1'b0), .I1(A[2]), .I2(A[1]), .I3(A[0])); | ||||
|         .I0(1'b0), .I1(A[0]), .I2(A[1]), .I3(A[2])); | ||||
|     end else | ||||
|     if (WIDTH == 4) begin | ||||
|       localparam [15:0] INIT = {LUT[15], LUT[7], LUT[11], LUT[3], LUT[13], LUT[5], LUT[9], LUT[1], LUT[14], LUT[6], LUT[10], LUT[2], LUT[12], LUT[4], LUT[8], LUT[0]}; | ||||
|       SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y), | ||||
|         .I0(A[3]), .I1(A[2]), .I2(A[1]), .I3(A[0])); | ||||
|       SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3])); | ||||
|     end else begin | ||||
|       wire _TECHMAP_FAIL_ = 1; | ||||
|     end | ||||
|  |  | |||
|  | @ -139,8 +139,8 @@ static void run_ice40_opts(Module *module) | |||
| 				log("Optimized $__ICE40_CARRY_WRAPPER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n", | ||||
| 						log_id(module), log_id(cell), log_signal(replacement_output)); | ||||
| 				cell->type = "$lut"; | ||||
| 				auto I3 = cell->getPort(cell->getParam(ID(I3_IS_CI)).as_bool() ? ID(CI) : ID(I3)); | ||||
| 				cell->setPort("\\A", { cell->getPort("\\I0"), inbit[0], inbit[1], I3 }); | ||||
| 				auto I3 = get_bit_or_zero(cell->getPort(cell->getParam(ID(I3_IS_CI)).as_bool() ? ID(CI) : ID(I3))); | ||||
| 				cell->setPort("\\A", { I3, inbit[1], inbit[0], get_bit_or_zero(cell->getPort("\\I0")) }); | ||||
| 				cell->setPort("\\Y", cell->getPort("\\O")); | ||||
| 				cell->unsetPort("\\B"); | ||||
| 				cell->unsetPort("\\CI"); | ||||
|  |  | |||
|  | @ -29,90 +29,65 @@ module \$lut (A, Y); | |||
|   input [WIDTH-1:0] A; | ||||
|   output Y; | ||||
| 
 | ||||
|   // Need to swap input ordering, and fix init accordingly, | ||||
|   // to match ABC's expectation of LUT inputs in non-decreasing | ||||
|   // delay order | ||||
|   function [WIDTH-1:0] permute_index; | ||||
|       input [WIDTH-1:0] i; | ||||
|       integer j; | ||||
|       begin | ||||
|           permute_index = 0; | ||||
|           for (j = 0; j < WIDTH; j = j + 1) | ||||
|               permute_index[WIDTH-1 - j] = i[j]; | ||||
|       end | ||||
|   endfunction | ||||
| 
 | ||||
|   function [2**WIDTH-1:0] permute_init; | ||||
|       input [2**WIDTH-1:0] orig; | ||||
|       integer i; | ||||
|       begin | ||||
|           permute_init = 0; | ||||
|           for (i = 0; i < 2**WIDTH; i = i + 1) | ||||
|               permute_init[i] = orig[permute_index(i)]; | ||||
|       end | ||||
|   endfunction | ||||
| 
 | ||||
|   parameter [2**WIDTH-1:0] P_LUT = permute_init(LUT); | ||||
| 
 | ||||
|   generate | ||||
|     if (WIDTH == 1) begin | ||||
|       if (P_LUT == 2'b01) begin | ||||
|       if (LUT == 2'b01) begin | ||||
|         INV _TECHMAP_REPLACE_ (.O(Y), .I(A[0])); | ||||
|       end else begin | ||||
|         LUT1 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||
|         LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||
|           .I0(A[0])); | ||||
|       end | ||||
|     end else | ||||
|     if (WIDTH == 2) begin | ||||
|       LUT2 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||
|         .I0(A[1]), .I1(A[0])); | ||||
|       LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||
|         .I0(A[0]), .I1(A[1])); | ||||
|     end else | ||||
|     if (WIDTH == 3) begin | ||||
|       LUT3 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||
|         .I0(A[2]), .I1(A[1]), .I2(A[0])); | ||||
|       LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2])); | ||||
|     end else | ||||
|     if (WIDTH == 4) begin | ||||
|       LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||
|         .I0(A[3]), .I1(A[2]), .I2(A[1]), | ||||
|         .I3(A[0])); | ||||
|       LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||
|         .I3(A[3])); | ||||
|     end else | ||||
|     if (WIDTH == 5) begin | ||||
|       LUT5 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||
|         .I0(A[4]), .I1(A[3]), .I2(A[2]), | ||||
|         .I3(A[1]), .I4(A[0])); | ||||
|       LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||
|         .I3(A[3]), .I4(A[4])); | ||||
|     end else | ||||
|     if (WIDTH == 6) begin | ||||
|       LUT6 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||
|         .I0(A[5]), .I1(A[4]), .I2(A[3]), | ||||
|         .I3(A[2]), .I4(A[1]), .I5(A[0])); | ||||
|       LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||
|         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||
|     end else | ||||
|     if (WIDTH == 7) begin | ||||
|       wire T0, T1; | ||||
|       LUT6 #(.INIT(P_LUT[63:0])) fpga_lut_0 (.O(T0), | ||||
|         .I0(A[6]), .I1(A[5]), .I2(A[4]), | ||||
|         .I3(A[3]), .I4(A[2]), .I5(A[1])); | ||||
|       LUT6 #(.INIT(P_LUT[127:64])) fpga_lut_1 (.O(T1), | ||||
|         .I0(A[6]), .I1(A[5]), .I2(A[4]), | ||||
|         .I3(A[3]), .I4(A[2]), .I5(A[1])); | ||||
|       MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[0])); | ||||
|       LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), | ||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||
|         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||
|       LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), | ||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||
|         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||
|       MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6])); | ||||
|     end else | ||||
|     if (WIDTH == 8) begin | ||||
|       wire T0, T1, T2, T3, T4, T5; | ||||
|       LUT6 #(.INIT(P_LUT[63:0])) fpga_lut_0 (.O(T0), | ||||
|         .I0(A[7]), .I1(A[6]), .I2(A[5]), | ||||
|         .I3(A[4]), .I4(A[3]), .I5(A[2])); | ||||
|       LUT6 #(.INIT(P_LUT[127:64])) fpga_lut_1 (.O(T1), | ||||
|         .I0(A[7]), .I1(A[6]), .I2(A[5]), | ||||
|         .I3(A[4]), .I4(A[3]), .I5(A[2])); | ||||
|       LUT6 #(.INIT(P_LUT[191:128])) fpga_lut_2 (.O(T2), | ||||
|         .I0(A[7]), .I1(A[6]), .I2(A[5]), | ||||
|         .I3(A[4]), .I4(A[3]), .I5(A[2])); | ||||
|       LUT6 #(.INIT(P_LUT[255:192])) fpga_lut_3 (.O(T3), | ||||
|         .I0(A[7]), .I1(A[6]), .I2(A[5]), | ||||
|         .I3(A[4]), .I4(A[3]), .I5(A[2])); | ||||
|       MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[1])); | ||||
|       MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[1])); | ||||
|       MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[0])); | ||||
|       LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), | ||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||
|         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||
|       LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), | ||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||
|         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||
|       LUT6 #(.INIT(LUT[191:128])) fpga_lut_2 (.O(T2), | ||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||
|         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||
|       LUT6 #(.INIT(LUT[255:192])) fpga_lut_3 (.O(T3), | ||||
|         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||
|         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||
|       MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6])); | ||||
|       MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6])); | ||||
|       MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7])); | ||||
|     end else begin | ||||
|       wire _TECHMAP_FAIL_ = 1; | ||||
|     end | ||||
|  |  | |||
							
								
								
									
										72
									
								
								tests/arch/ice40/bug1597.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								tests/arch/ice40/bug1597.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,72 @@ | |||
| read_verilog <<EOT | ||||
| module top ( | ||||
|     input CLK, PIN_1, PIN_2, PIN_3, PIN_4, PIN_5, | ||||
|         PIN_6, PIN_7, PIN_8, PIN_9, PIN_10, PIN_11, PIN_12, PIN_13, PIN_25, | ||||
|     output USBPU, PIN_14, PIN_15, PIN_16, PIN_17, PIN_18, | ||||
|         PIN_19, PIN_20, PIN_21, PIN_22, PIN_23, PIN_24, | ||||
| ); | ||||
|     assign USBPU = 0; | ||||
| 
 | ||||
|     wire[5:0] parOut; | ||||
|     wire[5:0] chrg; | ||||
| 
 | ||||
|     assign PIN_14 = parOut[0]; | ||||
|     assign PIN_15 = parOut[1]; | ||||
|     assign PIN_16 = parOut[2]; | ||||
|     assign PIN_17 = parOut[3]; | ||||
|     assign PIN_18 = parOut[4]; | ||||
|     assign PIN_19 = parOut[5]; | ||||
|     assign chrg[0] = PIN_3; | ||||
|     assign chrg[1] = PIN_4; | ||||
|     assign chrg[2] = PIN_5; | ||||
|     assign chrg[3] = PIN_6; | ||||
|     assign chrg[4] = PIN_7; | ||||
|     assign chrg[5] = PIN_8; | ||||
| 
 | ||||
|     SSCounter6o sc6(PIN_1, CLK, PIN_2, PIN_9, chrg, parOut); | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| module SSCounter6 (input wire rst, clk, adv, jmp, input wire [5:0] in, output reg[5:0] out); | ||||
|     always @(posedge clk, posedge rst) | ||||
|         if (rst) out <= 0; | ||||
|         else if (adv || jmp) out <= jmp ? in : out + 1; | ||||
| endmodule | ||||
| 
 | ||||
| // Optimized 6 bit counter, it should takes 7 cells. | ||||
| /* b[5:1]                       /* b[0] | ||||
| 1010101010101010 in             1010101010101010 in | ||||
| 1100110011001100 jmp            1100110011001100 jmp | ||||
| 1111000011110000 loop           1111000011110000 loop | ||||
| 1111111100000000 carry          1111111100000000 - | ||||
| ----------------------          ---------------------- | ||||
| 1000101110111000 out            1000101110001011 out | ||||
|    8   B   B   8                   8   B   8   B | ||||
| */ | ||||
| module SSCounter6o (input wire rst, clk, adv, jmp, input wire [5:0] in, output wire[5:0] out); | ||||
|     wire[4:0] co; | ||||
|     wire[5:0] lo; | ||||
|     wire ien; | ||||
|     SB_LUT4 #(.LUT_INIT(16'hFFF0)) lien (ien, 0, 0, adv, jmp); | ||||
|     SB_CARRY c0 (co[0], jmp, out[0], 1), | ||||
|              c1 (co[1], jmp, out[1], co[0]), | ||||
|              c2 (co[2], jmp, out[2], co[1]), | ||||
|              c3 (co[3], jmp, out[3], co[2]), | ||||
|              c4 (co[4], jmp, out[4], co[3]); | ||||
|     SB_DFFER d0 (out[0], clk, ien, rst, lo[0]), | ||||
|              d1 (out[1], clk, ien, rst, lo[1]), | ||||
|              d2 (out[2], clk, ien, rst, lo[2]), | ||||
|              d3 (out[3], clk, ien, rst, lo[3]), | ||||
|              d4 (out[4], clk, ien, rst, lo[4]), | ||||
|              d5 (out[5], clk, ien, rst, lo[5]); | ||||
|     SB_LUT4 #(.LUT_INIT(16'h8B8B)) l0 (lo[0], in[0], jmp, out[0], 0); | ||||
|     SB_LUT4 #(.LUT_INIT(16'h8BB8)) l1 (lo[1], in[1], jmp, out[1], co[0]); | ||||
|     SB_LUT4 #(.LUT_INIT(16'h8BB8)) l2 (lo[2], in[2], jmp, out[2], co[1]); | ||||
|     SB_LUT4 #(.LUT_INIT(16'h8BB8)) l3 (lo[3], in[3], jmp, out[3], co[2]); | ||||
|     SB_LUT4 #(.LUT_INIT(16'h8BB8)) l4 (lo[4], in[4], jmp, out[4], co[3]); | ||||
|     SB_LUT4 #(.LUT_INIT(16'h8BB8)) l5 (lo[5], in[5], jmp, out[5], co[4]); | ||||
| endmodule | ||||
| EOT | ||||
| hierarchy -top top | ||||
| flatten | ||||
| equiv_opt -multiclock -map +/ice40/cells_sim.v synth_ice40 | ||||
|  | @ -86,3 +86,33 @@ select -assert-count 1 t:SB_LUT4 | |||
| select -assert-count 1 t:SB_CARRY | ||||
| select -assert-count 1 t:SB_CARRY a:keep %i | ||||
| select -assert-count 1 t:SB_CARRY c:carry %i | ||||
| 
 | ||||
| 
 | ||||
| design -reset | ||||
| read_verilog -icells <<EOT | ||||
| module top(input I3, I2, I1, I0, output O, O2); | ||||
| 	SB_LUT4 #( | ||||
| 		.LUT_INIT(8'b 1001_0110) | ||||
| 	) u0 ( | ||||
| 		.I0(I0), | ||||
| 		.I1(I1), | ||||
| 		.I2(I2), | ||||
| 		.I3(), | ||||
| 		.O(O) | ||||
| 	); | ||||
| 	wire CO; | ||||
| 	\$__ICE40_CARRY_WRAPPER #( | ||||
| 		.LUT(~8'b 1001_0110), | ||||
| 		.I3_IS_CI(1'b0) | ||||
| 	) u1 ( | ||||
| 		.A(1'b0), | ||||
| 		.B(1'b0), | ||||
| 		.CI(1'b0), | ||||
| 		.I0(), | ||||
| 		.I3(), | ||||
| 		.CO(CO), | ||||
| 		.O(O2) | ||||
| 	); | ||||
| endmodule | ||||
| EOT | ||||
| ice40_opt | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue