mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Merge branch 'master' of github.com:YosysHQ/yosys
This commit is contained in:
		
						commit
						b236faffa1
					
				
					 11 changed files with 256 additions and 35 deletions
				
			
		|  | @ -36,7 +36,7 @@ struct OptLutWorker | ||||||
| 	dict<RTLIL::Cell*, pool<RTLIL::Cell*>> luts_dlogics; | 	dict<RTLIL::Cell*, pool<RTLIL::Cell*>> luts_dlogics; | ||||||
| 	dict<RTLIL::Cell*, pool<int>> luts_dlogic_inputs; | 	dict<RTLIL::Cell*, pool<int>> luts_dlogic_inputs; | ||||||
| 
 | 
 | ||||||
| 	int combined_count = 0; | 	int eliminated_count = 0, combined_count = 0; | ||||||
| 
 | 
 | ||||||
| 	bool evaluate_lut(RTLIL::Cell *lut, dict<SigBit, bool> inputs) | 	bool evaluate_lut(RTLIL::Cell *lut, dict<SigBit, bool> inputs) | ||||||
| 	{ | 	{ | ||||||
|  | @ -189,8 +189,16 @@ struct OptLutWorker | ||||||
| 
 | 
 | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("Eliminating LUTs.\n"); | 		log("Eliminating LUTs.\n"); | ||||||
| 		for (auto lut : luts) | 		pool<RTLIL::Cell*> worklist = luts; | ||||||
|  | 		while (worklist.size()) | ||||||
| 		{ | 		{ | ||||||
|  | 			if (limit == 0) | ||||||
|  | 			{ | ||||||
|  | 				log("Limit reached.\n"); | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			auto lut = worklist.pop(); | ||||||
| 			SigSpec lut_input = sigmap(lut->getPort("\\A")); | 			SigSpec lut_input = sigmap(lut->getPort("\\A")); | ||||||
| 			pool<int> &lut_dlogic_inputs = luts_dlogic_inputs[lut]; | 			pool<int> &lut_dlogic_inputs = luts_dlogic_inputs[lut]; | ||||||
| 
 | 
 | ||||||
|  | @ -256,13 +264,24 @@ struct OptLutWorker | ||||||
| 				else | 				else | ||||||
| 				{ | 				{ | ||||||
| 					SigSpec lut_output = lut->getPort("\\Y"); | 					SigSpec lut_output = lut->getPort("\\Y"); | ||||||
|  | 					for (auto &port : index.query_ports(lut_output)) | ||||||
|  | 					{ | ||||||
|  | 						if (port.cell != lut && luts.count(port.cell)) | ||||||
|  | 							worklist.insert(port.cell); | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
| 					module->connect(lut_output, value); | 					module->connect(lut_output, value); | ||||||
|  | 					sigmap.add(lut_output, value); | ||||||
| 
 | 
 | ||||||
| 					module->remove(lut); | 					module->remove(lut); | ||||||
| 					luts.erase(lut); | 					luts.erase(lut); | ||||||
| 					luts_arity.erase(lut); | 					luts_arity.erase(lut); | ||||||
| 					luts_dlogics.erase(lut); | 					luts_dlogics.erase(lut); | ||||||
| 					luts_dlogic_inputs.erase(lut); | 					luts_dlogic_inputs.erase(lut); | ||||||
|  | 
 | ||||||
|  | 					eliminated_count++; | ||||||
|  | 					if (limit > 0) | ||||||
|  | 						limit--; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -270,7 +289,7 @@ struct OptLutWorker | ||||||
| 
 | 
 | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("Combining LUTs.\n"); | 		log("Combining LUTs.\n"); | ||||||
| 		pool<RTLIL::Cell*> worklist = luts; | 		worklist = luts; | ||||||
| 		while (worklist.size()) | 		while (worklist.size()) | ||||||
| 		{ | 		{ | ||||||
| 			if (limit == 0) | 			if (limit == 0) | ||||||
|  | @ -568,16 +587,20 @@ struct OptLutPass : public Pass { | ||||||
| 		} | 		} | ||||||
| 		extra_args(args, argidx, design); | 		extra_args(args, argidx, design); | ||||||
| 
 | 
 | ||||||
| 		int total_count = 0; | 		int eliminated_count = 0, combined_count = 0; | ||||||
| 		for (auto module : design->selected_modules()) | 		for (auto module : design->selected_modules()) | ||||||
| 		{ | 		{ | ||||||
| 			OptLutWorker worker(dlogic, module, limit - total_count); | 			OptLutWorker worker(dlogic, module, limit - eliminated_count - combined_count); | ||||||
| 			total_count += worker.combined_count; | 			eliminated_count += worker.eliminated_count; | ||||||
|  | 			combined_count   += worker.combined_count; | ||||||
| 		} | 		} | ||||||
| 		if (total_count) | 		if (eliminated_count) | ||||||
|  | 			design->scratchpad_set_bool("opt.did_something", true); | ||||||
|  | 		if (combined_count) | ||||||
| 			design->scratchpad_set_bool("opt.did_something", true); | 			design->scratchpad_set_bool("opt.did_something", true); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("Combined %d LUTs.\n", total_count); | 		log("Eliminated %d LUTs.\n", eliminated_count); | ||||||
|  | 		log("Combined %d LUTs.\n", combined_count); | ||||||
| 	} | 	} | ||||||
| } OptLutPass; | } OptLutPass; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -43,18 +43,37 @@ struct DffinitPass : public Pass { | ||||||
| 		log("        initial value of 1 or 0. (multi-bit values are not supported in this\n"); | 		log("        initial value of 1 or 0. (multi-bit values are not supported in this\n"); | ||||||
| 		log("        mode.)\n"); | 		log("        mode.)\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | 		log("    -strinit <string for high> <string for low> \n"); | ||||||
|  | 		log("        use string values in the command line to represent a single-bit\n"); | ||||||
|  | 		log("        initial value of 1 or 0. (multi-bit values are not supported in this\n"); | ||||||
|  | 		log("        mode.)\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("    -noreinit\n"); | ||||||
|  | 		log("        fail if the FF cell has already a defined initial value set in other\n"); | ||||||
|  | 		log("        passes and the initial value of the net it drives is not equal to\n"); | ||||||
|  | 		log("        the already defined initial value.\n"); | ||||||
|  | 		log("\n"); | ||||||
| 	} | 	} | ||||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
| 		log_header(design, "Executing DFFINIT pass (set INIT param on FF cells).\n"); | 		log_header(design, "Executing DFFINIT pass (set INIT param on FF cells).\n"); | ||||||
| 
 | 
 | ||||||
| 		dict<IdString, dict<IdString, IdString>> ff_types; | 		dict<IdString, dict<IdString, IdString>> ff_types; | ||||||
| 		bool highlow_mode = false; | 		bool highlow_mode = false, noreinit = false; | ||||||
|  | 		std::string high_string, low_string; | ||||||
| 
 | 
 | ||||||
| 		size_t argidx; | 		size_t argidx; | ||||||
| 		for (argidx = 1; argidx < args.size(); argidx++) { | 		for (argidx = 1; argidx < args.size(); argidx++) { | ||||||
| 			if (args[argidx] == "-highlow") { | 			if (args[argidx] == "-highlow") { | ||||||
| 				highlow_mode = true; | 				highlow_mode = true; | ||||||
|  | 				high_string = "high"; | ||||||
|  | 				low_string = "low"; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			if (args[argidx] == "-strinit" && argidx+2 < args.size()) { | ||||||
|  | 				highlow_mode = true; | ||||||
|  | 				high_string = args[++argidx]; | ||||||
|  | 				low_string = args[++argidx]; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (args[argidx] == "-ff" && argidx+3 < args.size()) { | 			if (args[argidx] == "-ff" && argidx+3 < args.size()) { | ||||||
|  | @ -64,6 +83,10 @@ struct DffinitPass : public Pass { | ||||||
| 				ff_types[cell_name][output_port] = init_param; | 				ff_types[cell_name][output_port] = init_param; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			if (args[argidx] == "-noreinit") { | ||||||
|  | 				noreinit = true; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		extra_args(args, argidx, design); | 		extra_args(args, argidx, design); | ||||||
|  | @ -112,6 +135,10 @@ struct DffinitPass : public Pass { | ||||||
| 							continue; | 							continue; | ||||||
| 						while (GetSize(value.bits) <= i) | 						while (GetSize(value.bits) <= i) | ||||||
| 							value.bits.push_back(State::S0); | 							value.bits.push_back(State::S0); | ||||||
|  | 						if (noreinit && value.bits[i] != State::Sx && value.bits[i] != init_bits.at(sig[i])) | ||||||
|  | 							log_error("Trying to assign a different init value for %s.%s.%s which technically " | ||||||
|  | 									"have a conflicted init value.\n", | ||||||
|  | 									log_id(module), log_id(cell), log_id(it.second)); | ||||||
| 						value.bits[i] = init_bits.at(sig[i]); | 						value.bits[i] = init_bits.at(sig[i]); | ||||||
| 						cleanup_bits.insert(sig[i]); | 						cleanup_bits.insert(sig[i]); | ||||||
| 					} | 					} | ||||||
|  | @ -121,9 +148,9 @@ struct DffinitPass : public Pass { | ||||||
| 							log_error("Multi-bit init value for %s.%s.%s is incompatible with -highlow mode.\n", | 							log_error("Multi-bit init value for %s.%s.%s is incompatible with -highlow mode.\n", | ||||||
| 									log_id(module), log_id(cell), log_id(it.second)); | 									log_id(module), log_id(cell), log_id(it.second)); | ||||||
| 						if (value[0] == State::S1) | 						if (value[0] == State::S1) | ||||||
| 							value = Const("high"); | 							value = Const(high_string); | ||||||
| 						else | 						else | ||||||
| 							value = Const("low"); | 							value = Const(low_string); | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					log("Setting %s.%s.%s (port=%s, net=%s) to %s.\n", log_id(module), log_id(cell), log_id(it.second), | 					log("Setting %s.%s.%s (port=%s, net=%s) to %s.\n", log_id(module), log_id(cell), log_id(it.second), | ||||||
|  |  | ||||||
|  | @ -1,19 +1,19 @@ | ||||||
| module  \$_DFF_N_ (input D, C, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(1'b0)); endmodule | module  \$_DFF_N_ (input D, C, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(1'b0)); endmodule | ||||||
| module  \$_DFF_P_ (input D, C, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C),  .ce(1'b1), .sr(1'b0)); endmodule | module  \$_DFF_P_ (input D, C, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C),  .ce(1'b1), .sr(1'b0)); endmodule | ||||||
| 
 | 
 | ||||||
| module  \$_DFFE_NN_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(E), .sr(1'b0)); endmodule | module  \$_DFFE_NN_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(E), .sr(1'b0)); endmodule | ||||||
| module  \$_DFFE_NP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(E), .sr(1'b0)); endmodule | module  \$_DFFE_NP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(E), .sr(1'b0)); endmodule | ||||||
| module  \$_DFFE_PN_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C),  .ce(E), .sr(1'b0)); endmodule | module  \$_DFFE_PN_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C),  .ce(E), .sr(1'b0)); endmodule | ||||||
| module  \$_DFFE_PP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C),  .ce(E), .sr(1'b0)); endmodule | module  \$_DFFE_PP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C),  .ce(E), .sr(1'b0)); endmodule | ||||||
| 
 | 
 | ||||||
| module  \$_DFF_NN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule | module  \$_DFF_NN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule | ||||||
| module  \$_DFF_NN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"),   .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule | module  \$_DFF_NN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule | ||||||
| module  \$_DFF_NP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"),  .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule | module  \$_DFF_NP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("SR"),  .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule | ||||||
| module  \$_DFF_NP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"),   .SRMUX("SR"),  .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule | module  \$_DFF_NP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("SR"),  .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule | ||||||
| module  \$_DFF_PN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C) , .ce(1'b1), .sr(R)); endmodule | module  \$_DFF_PN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C) , .ce(1'b1), .sr(R)); endmodule | ||||||
| module  \$_DFF_PN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"),   .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C),  .ce(1'b1), .sr(R)); endmodule | module  \$_DFF_PN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C),  .ce(1'b1), .sr(R)); endmodule | ||||||
| module  \$_DFF_PP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"),  .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C),  .ce(1'b1), .sr(R)); endmodule | module  \$_DFF_PP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("SR"),  .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C),  .ce(1'b1), .sr(R)); endmodule | ||||||
| module  \$_DFF_PP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"),   .SRMUX("SR"), . SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C),  .ce(1'b1), .sr(R)); endmodule | module  \$_DFF_PP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("SR"), . SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C),  .ce(1'b1), .sr(R)); endmodule | ||||||
| 
 | 
 | ||||||
| module \$_DLATCH_N_ (E, D, Q); | module \$_DLATCH_N_ (E, D, Q); | ||||||
|   wire [1023:0] _TECHMAP_DO_ = "simplemap; opt"; |   wire [1023:0] _TECHMAP_DO_ = "simplemap; opt"; | ||||||
|  |  | ||||||
|  | @ -170,6 +170,7 @@ struct SynthAnlogicPass : public ScriptPass | ||||||
| 		{ | 		{ | ||||||
| 			run("dffsr2dff"); | 			run("dffsr2dff"); | ||||||
| 			run("techmap -D NO_LUT -map +/anlogic/cells_map.v"); | 			run("techmap -D NO_LUT -map +/anlogic/cells_map.v"); | ||||||
|  | 			run("dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit"); | ||||||
| 			run("opt_expr -mux_undef"); | 			run("opt_expr -mux_undef"); | ||||||
| 			run("simplemap"); | 			run("simplemap"); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -26,5 +26,5 @@ $(eval $(call add_share_file,share,techlibs/common/pmux2mux.v)) | ||||||
| $(eval $(call add_share_file,share,techlibs/common/adff2dff.v)) | $(eval $(call add_share_file,share,techlibs/common/adff2dff.v)) | ||||||
| $(eval $(call add_share_file,share,techlibs/common/dff2ff.v)) | $(eval $(call add_share_file,share,techlibs/common/dff2ff.v)) | ||||||
| $(eval $(call add_share_file,share,techlibs/common/gate2lut.v)) | $(eval $(call add_share_file,share,techlibs/common/gate2lut.v)) | ||||||
|  | $(eval $(call add_share_file,share,techlibs/common/cmp2lut.v)) | ||||||
| $(eval $(call add_share_file,share,techlibs/common/cells.lib)) | $(eval $(call add_share_file,share,techlibs/common/cells.lib)) | ||||||
| 
 |  | ||||||
|  |  | ||||||
							
								
								
									
										105
									
								
								techlibs/common/cmp2lut.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								techlibs/common/cmp2lut.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,105 @@ | ||||||
|  | // Certain arithmetic operations between a signal of width n and a constant can be directly mapped | ||||||
|  | // to a single k-LUT (where n <= k). This is preferable to normal alumacc techmapping process | ||||||
|  | // because for many targets, arithmetic techmapping creates hard logic (such as carry cells) which often | ||||||
|  | // cannot be optimized further. | ||||||
|  | // | ||||||
|  | // TODO: Currently, only comparisons with 1-bit output are mapped. Potentially, all arithmetic cells | ||||||
|  | // with n <= k inputs should be techmapped in this way, because this shortens the critical path | ||||||
|  | // from n to 1 by avoiding carry chains. | ||||||
|  | 
 | ||||||
|  | (* techmap_celltype = "$eq $ne $lt $le $gt $ge" *) | ||||||
|  | module _90_lut_cmp_ (A, B, Y); | ||||||
|  | 
 | ||||||
|  | parameter A_SIGNED = 0; | ||||||
|  | parameter B_SIGNED = 0; | ||||||
|  | parameter A_WIDTH = 0; | ||||||
|  | parameter B_WIDTH = 0; | ||||||
|  | parameter Y_WIDTH = 0; | ||||||
|  | 
 | ||||||
|  | input [A_WIDTH-1:0] A; | ||||||
|  | input [B_WIDTH-1:0] B; | ||||||
|  | output [Y_WIDTH-1:0] Y; | ||||||
|  | 
 | ||||||
|  | parameter _TECHMAP_CELLTYPE_ = ""; | ||||||
|  | 
 | ||||||
|  | parameter _TECHMAP_CONSTMSK_A_ = 0; | ||||||
|  | parameter _TECHMAP_CONSTVAL_A_ = 0; | ||||||
|  | parameter _TECHMAP_CONSTMSK_B_ = 0; | ||||||
|  | parameter _TECHMAP_CONSTVAL_B_ = 0; | ||||||
|  | 
 | ||||||
|  | function automatic integer gen_lut; | ||||||
|  | 	input integer width; | ||||||
|  | 	input integer operation; | ||||||
|  | 	input integer swap; | ||||||
|  | 	input integer sign; | ||||||
|  | 	input integer operand; | ||||||
|  | 	integer n, i_var, i_cst, lhs, rhs, o_bit; | ||||||
|  | 	begin | ||||||
|  | 		gen_lut = width'b0; | ||||||
|  | 		for (n = 0; n < (1 << width); n++) begin | ||||||
|  | 			if (sign) | ||||||
|  | 				i_var = n[width-1:0]; | ||||||
|  | 			else | ||||||
|  | 				i_var = n; | ||||||
|  | 			i_cst = operand; | ||||||
|  | 			if (swap) begin | ||||||
|  | 				lhs = i_cst; | ||||||
|  | 				rhs = i_var; | ||||||
|  | 			end else begin | ||||||
|  | 				lhs = i_var; | ||||||
|  | 				rhs = i_cst; | ||||||
|  | 			end | ||||||
|  | 			if (operation == 0) | ||||||
|  | 				o_bit = (lhs <  rhs); | ||||||
|  | 			if (operation == 1) | ||||||
|  | 				o_bit = (lhs <= rhs); | ||||||
|  | 			if (operation == 2) | ||||||
|  | 				o_bit = (lhs >  rhs); | ||||||
|  | 			if (operation == 3) | ||||||
|  | 				o_bit = (lhs >= rhs); | ||||||
|  | 			if (operation == 4) | ||||||
|  | 				o_bit = (lhs == rhs); | ||||||
|  | 			if (operation == 5) | ||||||
|  | 				o_bit = (lhs != rhs); | ||||||
|  | 			gen_lut = gen_lut | (o_bit << n); | ||||||
|  | 		end | ||||||
|  | 	end | ||||||
|  | endfunction | ||||||
|  | 
 | ||||||
|  | generate | ||||||
|  | 	if (_TECHMAP_CELLTYPE_ == "$lt") | ||||||
|  | 		localparam operation = 0; | ||||||
|  | 	if (_TECHMAP_CELLTYPE_ == "$le") | ||||||
|  | 		localparam operation = 1; | ||||||
|  | 	if (_TECHMAP_CELLTYPE_ == "$gt") | ||||||
|  | 		localparam operation = 2; | ||||||
|  | 	if (_TECHMAP_CELLTYPE_ == "$ge") | ||||||
|  | 		localparam operation = 3; | ||||||
|  | 	if (_TECHMAP_CELLTYPE_ == "$eq") | ||||||
|  | 		localparam operation = 4; | ||||||
|  | 	if (_TECHMAP_CELLTYPE_ == "$ne") | ||||||
|  | 		localparam operation = 5; | ||||||
|  | 
 | ||||||
|  | 	if (A_WIDTH > `LUT_WIDTH || B_WIDTH > `LUT_WIDTH || Y_WIDTH != 1) | ||||||
|  | 		wire _TECHMAP_FAIL_ = 1; | ||||||
|  | 	else if (&_TECHMAP_CONSTMSK_B_) | ||||||
|  | 		\$lut #( | ||||||
|  | 			.WIDTH(A_WIDTH), | ||||||
|  | 			.LUT({ gen_lut(A_WIDTH, operation, 0, A_SIGNED && B_SIGNED, _TECHMAP_CONSTVAL_B_) }) | ||||||
|  | 		) _TECHMAP_REPLACE_ ( | ||||||
|  | 			.A(A), | ||||||
|  | 			.Y(Y) | ||||||
|  | 		); | ||||||
|  | 	else if (&_TECHMAP_CONSTMSK_A_) | ||||||
|  | 		\$lut #( | ||||||
|  | 			.WIDTH(B_WIDTH), | ||||||
|  | 			.LUT({ gen_lut(B_WIDTH, operation, 1, A_SIGNED && B_SIGNED, _TECHMAP_CONSTVAL_A_) }) | ||||||
|  | 		) _TECHMAP_REPLACE_ ( | ||||||
|  | 			.A(B), | ||||||
|  | 			.Y(Y) | ||||||
|  | 		); | ||||||
|  | 	else | ||||||
|  | 		wire _TECHMAP_FAIL_ = 1; | ||||||
|  | endgenerate | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | @ -51,6 +51,9 @@ struct SynthPass : public ScriptPass | ||||||
| 		log("    -encfile <file>\n"); | 		log("    -encfile <file>\n"); | ||||||
| 		log("        passed to 'fsm_recode' via 'fsm'\n"); | 		log("        passed to 'fsm_recode' via 'fsm'\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | 		log("    -lut <k>\n"); | ||||||
|  | 		log("        perform synthesis for a k-LUT architecture.\n"); | ||||||
|  | 		log("\n"); | ||||||
| 		log("    -nofsm\n"); | 		log("    -nofsm\n"); | ||||||
| 		log("        do not run FSM optimization\n"); | 		log("        do not run FSM optimization\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | @ -80,6 +83,7 @@ struct SynthPass : public ScriptPass | ||||||
| 
 | 
 | ||||||
| 	string top_module, fsm_opts, memory_opts; | 	string top_module, fsm_opts, memory_opts; | ||||||
| 	bool autotop, flatten, noalumacc, nofsm, noabc, noshare; | 	bool autotop, flatten, noalumacc, nofsm, noabc, noshare; | ||||||
|  | 	int lut; | ||||||
| 
 | 
 | ||||||
| 	void clear_flags() YS_OVERRIDE | 	void clear_flags() YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
|  | @ -89,6 +93,7 @@ struct SynthPass : public ScriptPass | ||||||
| 
 | 
 | ||||||
| 		autotop = false; | 		autotop = false; | ||||||
| 		flatten = false; | 		flatten = false; | ||||||
|  | 		lut = 0; | ||||||
| 		noalumacc = false; | 		noalumacc = false; | ||||||
| 		nofsm = false; | 		nofsm = false; | ||||||
| 		noabc = false; | 		noabc = false; | ||||||
|  | @ -130,6 +135,10 @@ struct SynthPass : public ScriptPass | ||||||
| 				flatten = true; | 				flatten = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			if (args[argidx] == "-lut") { | ||||||
|  | 				lut = atoi(args[++argidx].c_str()); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 			if (args[argidx] == "-nofsm") { | 			if (args[argidx] == "-nofsm") { | ||||||
| 				nofsm = true; | 				nofsm = true; | ||||||
| 				continue; | 				continue; | ||||||
|  | @ -186,19 +195,23 @@ struct SynthPass : public ScriptPass | ||||||
| 		{ | 		{ | ||||||
| 			run("proc"); | 			run("proc"); | ||||||
| 			if (help_mode || flatten) | 			if (help_mode || flatten) | ||||||
| 				run("flatten", "(if -flatten)"); | 				run("flatten", "  (if -flatten)"); | ||||||
| 			run("opt_expr"); | 			run("opt_expr"); | ||||||
| 			run("opt_clean"); | 			run("opt_clean"); | ||||||
| 			run("check"); | 			run("check"); | ||||||
| 			run("opt"); | 			run("opt"); | ||||||
| 			run("wreduce"); | 			run("wreduce"); | ||||||
|  | 			if (help_mode) | ||||||
|  | 				run("techmap -map +/cmp2lut.v", " (if -lut)"); | ||||||
|  | 			else | ||||||
|  | 				run(stringf("techmap -map +/cmp2lut.v -D LUT_WIDTH=%d", lut)); | ||||||
| 			if (!noalumacc) | 			if (!noalumacc) | ||||||
| 				run("alumacc"); | 				run("alumacc", "  (unless -noalumacc)"); | ||||||
| 			if (!noshare) | 			if (!noshare) | ||||||
| 				run("share"); | 				run("share", "    (unless -noshare)"); | ||||||
| 			run("opt"); | 			run("opt"); | ||||||
| 			if (!nofsm) | 			if (!nofsm) | ||||||
| 				run("fsm" + fsm_opts); | 				run("fsm" + fsm_opts, "      (unless -nofsm)"); | ||||||
| 			run("opt -fast"); | 			run("opt -fast"); | ||||||
| 			run("memory -nomap" + memory_opts); | 			run("memory -nomap" + memory_opts); | ||||||
| 			run("opt_clean"); | 			run("opt_clean"); | ||||||
|  | @ -210,12 +223,33 @@ struct SynthPass : public ScriptPass | ||||||
| 			run("memory_map"); | 			run("memory_map"); | ||||||
| 			run("opt -full"); | 			run("opt -full"); | ||||||
| 			run("techmap"); | 			run("techmap"); | ||||||
|  | 			if (help_mode) | ||||||
|  | 			{ | ||||||
|  | 				run("techmap -map +/gate2lut.v", "(if -noabc and -lut)"); | ||||||
|  | 				run("clean; opt_lut", "           (if -noabc and -lut)"); | ||||||
|  | 			} | ||||||
|  | 			else if (noabc && lut) | ||||||
|  | 			{ | ||||||
|  | 				run(stringf("techmap -map +/gate2lut.v -D LUT_WIDTH=%d", lut)); | ||||||
|  | 				run("clean; opt_lut"); | ||||||
|  | 			} | ||||||
| 			run("opt -fast"); | 			run("opt -fast"); | ||||||
| 
 | 
 | ||||||
| 			if (!noabc) { | 			if (!noabc) { | ||||||
| 		#ifdef YOSYS_ENABLE_ABC | 		#ifdef YOSYS_ENABLE_ABC | ||||||
| 				run("abc -fast"); | 				if (help_mode) | ||||||
| 				run("opt -fast"); | 				{ | ||||||
|  | 					run("abc -fast", "       (unless -noabc, unless -lut)"); | ||||||
|  | 					run("abc -fast -lut k", "(unless -noabc, if -lut)"); | ||||||
|  | 				} | ||||||
|  | 				else | ||||||
|  | 				{ | ||||||
|  | 					if (lut) | ||||||
|  | 						run(stringf("abc -fast -lut %d", lut)); | ||||||
|  | 					else | ||||||
|  | 						run("abc -fast"); | ||||||
|  | 				} | ||||||
|  | 				run("opt -fast", "       (unless -noabc)"); | ||||||
| 		#endif | 		#endif | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -226,7 +226,7 @@ struct SynthIce40Pass : public ScriptPass | ||||||
| 
 | 
 | ||||||
| 		if (check_label("coarse")) | 		if (check_label("coarse")) | ||||||
| 		{ | 		{ | ||||||
| 			run("synth -run coarse"); | 			run("synth -lut 4 -run coarse"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (!nobram && check_label("bram", "(skip if -nobram)")) | 		if (!nobram && check_label("bram", "(skip if -nobram)")) | ||||||
|  |  | ||||||
|  | @ -1,4 +1,6 @@ | ||||||
| simplemap | simplemap | ||||||
| equiv_opt -assert techmap -map +/gate2lut.v -D LUT_WIDTH=4 | equiv_opt -assert techmap -D LUT_WIDTH=4 -map +/cmp2lut.v | ||||||
| design -load postopt | design -load postopt | ||||||
| select -assert-count 1 t:$lut | equiv_opt -assert techmap -D LUT_WIDTH=4 -map +/gate2lut.v | ||||||
|  | design -load postopt | ||||||
|  | select -assert-count 0 t:* t:$lut %d | ||||||
|  |  | ||||||
							
								
								
									
										29
									
								
								tests/lut/map_cmp.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								tests/lut/map_cmp.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | ||||||
|  | module top(...); | ||||||
|  | 	input [3:0] a; | ||||||
|  | 
 | ||||||
|  | 	output o1_1 = 4'b1010 <= a; | ||||||
|  | 	output o1_2 = 4'b1010 <  a; | ||||||
|  | 	output o1_3 = 4'b1010 >= a; | ||||||
|  | 	output o1_4 = 4'b1010 >  a; | ||||||
|  | 	output o1_5 = 4'b1010 == a; | ||||||
|  | 	output o1_6 = 4'b1010 != a; | ||||||
|  | 
 | ||||||
|  | 	output o2_1 = a <= 4'b1010; | ||||||
|  | 	output o2_2 = a <  4'b1010; | ||||||
|  | 	output o2_3 = a >= 4'b1010; | ||||||
|  | 	output o2_4 = a >  4'b1010; | ||||||
|  | 	output o2_5 = a == 4'b1010; | ||||||
|  | 	output o2_6 = a != 4'b1010; | ||||||
|  | 
 | ||||||
|  | 	output o3_1 = 4'sb0101 <= $signed(a); | ||||||
|  | 	output o3_2 = 4'sb0101 <  $signed(a); | ||||||
|  | 	output o3_3 = 4'sb0101 >= $signed(a); | ||||||
|  | 	output o3_4 = 4'sb0101 >  $signed(a); | ||||||
|  | 	output o3_5 = 4'sb0101 == $signed(a); | ||||||
|  | 	output o3_6 = 4'sb0101 != $signed(a); | ||||||
|  | 
 | ||||||
|  | 	output o4_1 = $signed(a) <= 4'sb0000; | ||||||
|  | 	output o4_2 = $signed(a) <  4'sb0000; | ||||||
|  | 	output o4_3 = $signed(a) >= 4'sb0000; | ||||||
|  | 	output o4_4 = $signed(a) >  4'sb0000; | ||||||
|  | endmodule | ||||||
							
								
								
									
										0
									
								
								tests/lut/run-test.sh
									
										
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								tests/lut/run-test.sh
									
										
									
									
									
										
										
										Normal file → Executable file
									
								
							
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue