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); | 					log_assert(wire); | ||||||
| 					input_sig.append(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())
 | 				// TODO: Compute LUT mask from AIG in less than O(2 ** input_sig.size())
 | ||||||
| 				ce.clear(); | 				ce.clear(); | ||||||
| 				ce.compute_deps(output_sig, input_sig.to_sigbit_pool()); | 				ce.compute_deps(output_sig, input_sig.to_sigbit_pool()); | ||||||
|  |  | ||||||
|  | @ -851,6 +851,8 @@ public: | ||||||
| 
 | 
 | ||||||
| 	RTLIL::SigSpec repeat(int num) const; | 	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; | ||||||
| 	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); } | 	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(WIDTH), 4); | ||||||
| 					lut->setParam(ID(LUT), cell->getParam(ID(LUT))); | 					lut->setParam(ID(LUT), cell->getParam(ID(LUT))); | ||||||
| 					auto I3 = cell->getPort(cell->getParam(ID(I3_IS_CI)).as_bool() ? ID(CI) : ID(I3)); | 					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))); | 					lut->setPort(ID(Y), cell->getPort(ID(O))); | ||||||
| 
 | 
 | ||||||
| 					Const src; | 					Const src; | ||||||
|  |  | ||||||
|  | @ -73,102 +73,80 @@ module \$lut (A, Y); | ||||||
|     input [WIDTH-1:0] A; |     input [WIDTH-1:0] A; | ||||||
|     output Y; |     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 |     generate | ||||||
|         if (WIDTH == 1) begin |         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])); |                 .A(1'b0), .B(1'b0), .C(1'b0), .D(A[0])); | ||||||
|         end else |         end else | ||||||
|         if (WIDTH == 2) begin |         if (WIDTH == 2) begin | ||||||
|             LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y), |             localparam [15:0] INIT = {{4{LUT[3]}}, {4{LUT[2]}}, {4{LUT[1]}}, {4{LUT[0]}}}; | ||||||
|                 .A(1'b0), .B(1'b0), .C(A[1]), .D(A[0])); |             LUT4 #(.INIT(INIT)) _TECHMAP_REPLACE_ (.Z(Y), | ||||||
|  |                 .A(1'b0), .B(1'b0), .C(A[0]), .D(A[1])); | ||||||
|         end else |         end else | ||||||
|         if (WIDTH == 3) begin |         if (WIDTH == 3) begin | ||||||
|             LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y), |             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]}}}; | ||||||
|                 .A(1'b0), .B(A[2]), .C(A[1]), .D(A[0])); |             LUT4 #(.INIT(INIT)) _TECHMAP_REPLACE_ (.Z(Y), | ||||||
|  |                 .A(1'b0), .B(A[0]), .C(A[1]), .D(A[2])); | ||||||
|         end else |         end else | ||||||
|         if (WIDTH == 4) begin |         if (WIDTH == 4) begin | ||||||
|             LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y), |             LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y), | ||||||
|                 .A(A[3]), .B(A[2]), .C(A[1]), .D(A[0])); |                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||||
|         `ifndef NO_PFUMUX |         `ifndef NO_PFUMUX | ||||||
|         end else |         end else | ||||||
|         if (WIDTH == 5) begin |         if (WIDTH == 5) begin | ||||||
|             wire f0, f1; |             wire f0, f1; | ||||||
|             LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0), |             LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0), | ||||||
|                 .A(A[4]), .B(A[3]), .C(A[2]), .D(A[1])); |                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||||
|             LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1), |             LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1), | ||||||
|                 .A(A[4]), .B(A[3]), .C(A[2]), .D(A[1])); |                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||||
|             PFUMX mux5(.ALUT(f1), .BLUT(f0), .C0(A[0]), .Z(Y)); |             PFUMX mux5(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(Y)); | ||||||
|         end else |         end else | ||||||
|         if (WIDTH == 6) begin |         if (WIDTH == 6) begin | ||||||
|             wire f0, f1, f2, f3, g0, g1; |             wire f0, f1, f2, f3, g0, g1; | ||||||
|             LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0), |             LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0), | ||||||
|                 .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2])); |                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||||
|             LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1), |             LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1), | ||||||
|                 .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2])); |                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||||
| 
 | 
 | ||||||
|             LUT4 #(.INIT(P_LUT[47:32])) lut2 (.Z(f2), |             LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2), | ||||||
|                 .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2])); |                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||||
|             LUT4 #(.INIT(P_LUT[63:48])) lut3 (.Z(f3), |             LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3), | ||||||
|                 .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2])); |                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||||
| 
 | 
 | ||||||
|             PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[1]), .Z(g0)); |             PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0)); | ||||||
|             PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[1]), .Z(g1)); |             PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1)); | ||||||
|             L6MUX21 mux6 (.D0(g0), .D1(g1), .SD(A[0]), .Z(Y)); |             L6MUX21 mux6 (.D0(g0), .D1(g1), .SD(A[5]), .Z(Y)); | ||||||
|         end else |         end else | ||||||
|         if (WIDTH == 7) begin |         if (WIDTH == 7) begin | ||||||
|             wire f0, f1, f2, f3, f4, f5, f6, f7, g0, g1, g2, g3, h0, h1; |             wire f0, f1, f2, f3, f4, f5, f6, f7, g0, g1, g2, g3, h0, h1; | ||||||
|             LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0), |             LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0), | ||||||
|                 .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); |                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||||
|             LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1), |             LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1), | ||||||
|                 .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); |                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||||
| 
 | 
 | ||||||
|             LUT4 #(.INIT(P_LUT[47:32])) lut2 (.Z(f2), |             LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2), | ||||||
|                 .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); |                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||||
|             LUT4 #(.INIT(P_LUT[63:48])) lut3 (.Z(f3), |             LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3), | ||||||
|                 .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); |                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||||
| 
 | 
 | ||||||
|             LUT4 #(.INIT(P_LUT[79:64])) lut4 (.Z(f4), |             LUT4 #(.INIT(LUT[79:64])) lut4 (.Z(f4), | ||||||
|                 .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); |                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||||
|             LUT4 #(.INIT(P_LUT[95:80])) lut5 (.Z(f5), |             LUT4 #(.INIT(LUT[95:80])) lut5 (.Z(f5), | ||||||
|                 .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); |                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||||
| 
 | 
 | ||||||
|             LUT4 #(.INIT(P_LUT[111: 96])) lut6 (.Z(f6), |             LUT4 #(.INIT(LUT[111: 96])) lut6 (.Z(f6), | ||||||
|                 .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); |                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||||
|             LUT4 #(.INIT(P_LUT[127:112])) lut7 (.Z(f7), |             LUT4 #(.INIT(LUT[127:112])) lut7 (.Z(f7), | ||||||
|                 .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3])); |                 .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); | ||||||
| 
 | 
 | ||||||
|             PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[2]), .Z(g0)); |             PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0)); | ||||||
|             PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[2]), .Z(g1)); |             PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1)); | ||||||
|             PFUMX mux52(.ALUT(f5), .BLUT(f4), .C0(A[2]), .Z(g2)); |             PFUMX mux52(.ALUT(f5), .BLUT(f4), .C0(A[4]), .Z(g2)); | ||||||
|             PFUMX mux53(.ALUT(f7), .BLUT(f6), .C0(A[2]), .Z(g3)); |             PFUMX mux53(.ALUT(f7), .BLUT(f6), .C0(A[4]), .Z(g3)); | ||||||
|             L6MUX21 mux60 (.D0(g0), .D1(g1), .SD(A[1]), .Z(h0)); |             L6MUX21 mux60 (.D0(g0), .D1(g1), .SD(A[5]), .Z(h0)); | ||||||
|             L6MUX21 mux61 (.D0(g2), .D1(g3), .SD(A[1]), .Z(h1)); |             L6MUX21 mux61 (.D0(g2), .D1(g3), .SD(A[5]), .Z(h1)); | ||||||
|             L6MUX21 mux7  (.D0(h0), .D1(h1), .SD(A[0]), .Z(Y)); |             L6MUX21 mux7  (.D0(h0), .D1(h1), .SD(A[6]), .Z(Y)); | ||||||
|         `endif |         `endif | ||||||
|         end else begin |         end else begin | ||||||
|             wire _TECHMAP_FAIL_ = 1; |             wire _TECHMAP_FAIL_ = 1; | ||||||
|  |  | ||||||
|  | @ -42,19 +42,18 @@ module \$lut (A, Y); | ||||||
|         .I0(1'b0), .I1(1'b0), .I2(1'b0), .I3(A[0])); |         .I0(1'b0), .I1(1'b0), .I2(1'b0), .I3(A[0])); | ||||||
|     end else |     end else | ||||||
|     if (WIDTH == 2) begin |     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), |       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 |     end else | ||||||
|     if (WIDTH == 3) begin |     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), |       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 |     end else | ||||||
|     if (WIDTH == 4) begin |     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(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||||
|       SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y), |         .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3])); | ||||||
|         .I0(A[3]), .I1(A[2]), .I2(A[1]), .I3(A[0])); |  | ||||||
|     end else begin |     end else begin | ||||||
|       wire _TECHMAP_FAIL_ = 1; |       wire _TECHMAP_FAIL_ = 1; | ||||||
|     end |     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("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)); | 						log_id(module), log_id(cell), log_signal(replacement_output)); | ||||||
| 				cell->type = "$lut"; | 				cell->type = "$lut"; | ||||||
| 				auto I3 = cell->getPort(cell->getParam(ID(I3_IS_CI)).as_bool() ? ID(CI) : ID(I3)); | 				auto I3 = get_bit_or_zero(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 }); | 				cell->setPort("\\A", { I3, inbit[1], inbit[0], get_bit_or_zero(cell->getPort("\\I0")) }); | ||||||
| 				cell->setPort("\\Y", cell->getPort("\\O")); | 				cell->setPort("\\Y", cell->getPort("\\O")); | ||||||
| 				cell->unsetPort("\\B"); | 				cell->unsetPort("\\B"); | ||||||
| 				cell->unsetPort("\\CI"); | 				cell->unsetPort("\\CI"); | ||||||
|  |  | ||||||
|  | @ -29,90 +29,65 @@ module \$lut (A, Y); | ||||||
|   input [WIDTH-1:0] A; |   input [WIDTH-1:0] A; | ||||||
|   output Y; |   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 |   generate | ||||||
|     if (WIDTH == 1) begin |     if (WIDTH == 1) begin | ||||||
|       if (P_LUT == 2'b01) begin |       if (LUT == 2'b01) begin | ||||||
|         INV _TECHMAP_REPLACE_ (.O(Y), .I(A[0])); |         INV _TECHMAP_REPLACE_ (.O(Y), .I(A[0])); | ||||||
|       end else begin |       end else begin | ||||||
|         LUT1 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), |         LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||||
|           .I0(A[0])); |           .I0(A[0])); | ||||||
|       end |       end | ||||||
|     end else |     end else | ||||||
|     if (WIDTH == 2) begin |     if (WIDTH == 2) begin | ||||||
|       LUT2 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), |       LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||||
|         .I0(A[1]), .I1(A[0])); |         .I0(A[0]), .I1(A[1])); | ||||||
|     end else |     end else | ||||||
|     if (WIDTH == 3) begin |     if (WIDTH == 3) begin | ||||||
|       LUT3 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), |       LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||||
|         .I0(A[2]), .I1(A[1]), .I2(A[0])); |         .I0(A[0]), .I1(A[1]), .I2(A[2])); | ||||||
|     end else |     end else | ||||||
|     if (WIDTH == 4) begin |     if (WIDTH == 4) begin | ||||||
|       LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), |       LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||||
|         .I0(A[3]), .I1(A[2]), .I2(A[1]), |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|         .I3(A[0])); |         .I3(A[3])); | ||||||
|     end else |     end else | ||||||
|     if (WIDTH == 5) begin |     if (WIDTH == 5) begin | ||||||
|       LUT5 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), |       LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||||
|         .I0(A[4]), .I1(A[3]), .I2(A[2]), |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|         .I3(A[1]), .I4(A[0])); |         .I3(A[3]), .I4(A[4])); | ||||||
|     end else |     end else | ||||||
|     if (WIDTH == 6) begin |     if (WIDTH == 6) begin | ||||||
|       LUT6 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y), |       LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), | ||||||
|         .I0(A[5]), .I1(A[4]), .I2(A[3]), |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|         .I3(A[2]), .I4(A[1]), .I5(A[0])); |         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||||
|     end else |     end else | ||||||
|     if (WIDTH == 7) begin |     if (WIDTH == 7) begin | ||||||
|       wire T0, T1; |       wire T0, T1; | ||||||
|       LUT6 #(.INIT(P_LUT[63:0])) fpga_lut_0 (.O(T0), |       LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), | ||||||
|         .I0(A[6]), .I1(A[5]), .I2(A[4]), |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|         .I3(A[3]), .I4(A[2]), .I5(A[1])); |         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||||
|       LUT6 #(.INIT(P_LUT[127:64])) fpga_lut_1 (.O(T1), |       LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), | ||||||
|         .I0(A[6]), .I1(A[5]), .I2(A[4]), |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|         .I3(A[3]), .I4(A[2]), .I5(A[1])); |         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||||
|       MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[0])); |       MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6])); | ||||||
|     end else |     end else | ||||||
|     if (WIDTH == 8) begin |     if (WIDTH == 8) begin | ||||||
|       wire T0, T1, T2, T3, T4, T5; |       wire T0, T1, T2, T3, T4, T5; | ||||||
|       LUT6 #(.INIT(P_LUT[63:0])) fpga_lut_0 (.O(T0), |       LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0), | ||||||
|         .I0(A[7]), .I1(A[6]), .I2(A[5]), |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|         .I3(A[4]), .I4(A[3]), .I5(A[2])); |         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||||
|       LUT6 #(.INIT(P_LUT[127:64])) fpga_lut_1 (.O(T1), |       LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1), | ||||||
|         .I0(A[7]), .I1(A[6]), .I2(A[5]), |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|         .I3(A[4]), .I4(A[3]), .I5(A[2])); |         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||||
|       LUT6 #(.INIT(P_LUT[191:128])) fpga_lut_2 (.O(T2), |       LUT6 #(.INIT(LUT[191:128])) fpga_lut_2 (.O(T2), | ||||||
|         .I0(A[7]), .I1(A[6]), .I2(A[5]), |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|         .I3(A[4]), .I4(A[3]), .I5(A[2])); |         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||||
|       LUT6 #(.INIT(P_LUT[255:192])) fpga_lut_3 (.O(T3), |       LUT6 #(.INIT(LUT[255:192])) fpga_lut_3 (.O(T3), | ||||||
|         .I0(A[7]), .I1(A[6]), .I2(A[5]), |         .I0(A[0]), .I1(A[1]), .I2(A[2]), | ||||||
|         .I3(A[4]), .I4(A[3]), .I5(A[2])); |         .I3(A[3]), .I4(A[4]), .I5(A[5])); | ||||||
|       MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[1])); |       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[1])); |       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[0])); |       MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7])); | ||||||
|     end else begin |     end else begin | ||||||
|       wire _TECHMAP_FAIL_ = 1; |       wire _TECHMAP_FAIL_ = 1; | ||||||
|     end |     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 | ||||||
| select -assert-count 1 t:SB_CARRY a:keep %i | select -assert-count 1 t:SB_CARRY a:keep %i | ||||||
| select -assert-count 1 t:SB_CARRY c:carry %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