mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-30 19:22:31 +00:00 
			
		
		
		
	Added "abc -luts" option, Improved Xilinx logic mapping
This commit is contained in:
		
							parent
							
								
									9251553592
								
							
						
					
					
						commit
						17372d8abd
					
				
					 2 changed files with 39 additions and 15 deletions
				
			
		|  | @ -592,7 +592,7 @@ struct abc_output_filter | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, | void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, | ||||||
| 		std::string liberty_file, std::string constr_file, bool cleanup, int lut_mode, int lut_mode2, bool dff_mode, std::string clk_str, | 		std::string liberty_file, std::string constr_file, bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str, | ||||||
| 		bool keepff, std::string delay_target, bool fast_mode, const std::vector<RTLIL::Cell*> &cells, bool show_tempdir) | 		bool keepff, std::string delay_target, bool fast_mode, const std::vector<RTLIL::Cell*> &cells, bool show_tempdir) | ||||||
| { | { | ||||||
| 	module = current_module; | 	module = current_module; | ||||||
|  | @ -626,7 +626,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin | ||||||
| 		if (!constr_file.empty()) | 		if (!constr_file.empty()) | ||||||
| 			abc_script += stringf("read_constr -v %s; ", constr_file.c_str()); | 			abc_script += stringf("read_constr -v %s; ", constr_file.c_str()); | ||||||
| 	} else | 	} else | ||||||
| 	if (lut_mode) | 	if (!lut_costs.empty()) | ||||||
| 		abc_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); | 		abc_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); | ||||||
| 	else | 	else | ||||||
| 		abc_script += stringf("read_library %s/stdcells.genlib; ", tempdir_name.c_str()); | 		abc_script += stringf("read_library %s/stdcells.genlib; ", tempdir_name.c_str()); | ||||||
|  | @ -642,7 +642,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin | ||||||
| 					abc_script += script_file[i]; | 					abc_script += script_file[i]; | ||||||
| 		} else | 		} else | ||||||
| 			abc_script += stringf("source %s", script_file.c_str()); | 			abc_script += stringf("source %s", script_file.c_str()); | ||||||
| 	} else if (lut_mode) | 	} else if (!lut_costs.empty()) | ||||||
| 		abc_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; | 		abc_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; | ||||||
| 	else if (!liberty_file.empty()) | 	else if (!liberty_file.empty()) | ||||||
| 		abc_script += constr_file.empty() ? (fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR); | 		abc_script += constr_file.empty() ? (fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR); | ||||||
|  | @ -868,15 +868,13 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin | ||||||
| 			fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*get_cell_cost("$_MUX_")); | 			fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*get_cell_cost("$_MUX_")); | ||||||
| 		fclose(f); | 		fclose(f); | ||||||
| 
 | 
 | ||||||
| 		if (lut_mode) { | 		if (!lut_costs.empty()) { | ||||||
| 			buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str()); | 			buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str()); | ||||||
| 			f = fopen(buffer.c_str(), "wt"); | 			f = fopen(buffer.c_str(), "wt"); | ||||||
| 			if (f == NULL) | 			if (f == NULL) | ||||||
| 				log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); | 				log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); | ||||||
| 			for (int i = 0; i < lut_mode; i++) | 			for (int i = 0; i < GetSize(lut_costs); i++) | ||||||
| 				fprintf(f, "%d 1.00 1.00\n", i+1); | 				fprintf(f, "%d %d.00 1.00\n", i+1, lut_costs.at(i)); | ||||||
| 			for (int i = lut_mode; i < lut_mode2; i++) |  | ||||||
| 				fprintf(f, "%d %d.00 1.00\n", i+1, 2 << (i - lut_mode)); |  | ||||||
| 			fclose(f); | 			fclose(f); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -894,7 +892,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin | ||||||
| 		if (ifs.fail()) | 		if (ifs.fail()) | ||||||
| 			log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); | 			log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); | ||||||
| 
 | 
 | ||||||
| 		bool builtin_lib = liberty_file.empty() && script_file.empty() && !lut_mode; | 		bool builtin_lib = liberty_file.empty() && script_file.empty() && lut_costs.empty(); | ||||||
| 		RTLIL::Design *mapped_design = new RTLIL::Design; | 		RTLIL::Design *mapped_design = new RTLIL::Design; | ||||||
| 		parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_"); | 		parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_"); | ||||||
| 
 | 
 | ||||||
|  | @ -1238,6 +1236,10 @@ struct AbcPass : public Pass { | ||||||
| 		log("        the area cost doubles with each additional input bit. the delay cost\n"); | 		log("        the area cost doubles with each additional input bit. the delay cost\n"); | ||||||
| 		log("        is still constant for all lut widths.\n"); | 		log("        is still constant for all lut widths.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | 		log("    -luts <cost1>,<cost2>,<cost3>,<sizeN>:<cost4-N>,..\n"); | ||||||
|  | 		log("        generate netlist using luts. Use the specified costs for luts with 1,\n"); | ||||||
|  | 		log("        2, 3, .. inputs.\n"); | ||||||
|  | 		log("\n"); | ||||||
| 		// log("    -mux4, -mux8, -mux16\n");
 | 		// log("    -mux4, -mux8, -mux16\n");
 | ||||||
| 		// log("        try to extract 4-input, 8-input, and/or 16-input muxes\n");
 | 		// log("        try to extract 4-input, 8-input, and/or 16-input muxes\n");
 | ||||||
| 		// log("        (ignored when used with -liberty or -lut)\n");
 | 		// log("        (ignored when used with -liberty or -lut)\n");
 | ||||||
|  | @ -1291,7 +1293,7 @@ struct AbcPass : public Pass { | ||||||
| 		std::string script_file, liberty_file, constr_file, clk_str, delay_target; | 		std::string script_file, liberty_file, constr_file, clk_str, delay_target; | ||||||
| 		bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; | 		bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; | ||||||
| 		bool show_tempdir = false; | 		bool show_tempdir = false; | ||||||
| 		int lut_mode = 0, lut_mode2 = 0; | 		vector<int> lut_costs; | ||||||
| 		markgroups = false; | 		markgroups = false; | ||||||
| 
 | 
 | ||||||
| 		map_mux4 = false; | 		map_mux4 = false; | ||||||
|  | @ -1341,6 +1343,7 @@ struct AbcPass : public Pass { | ||||||
| 			if (arg == "-lut" && argidx+1 < args.size()) { | 			if (arg == "-lut" && argidx+1 < args.size()) { | ||||||
| 				string arg = args[++argidx]; | 				string arg = args[++argidx]; | ||||||
| 				size_t pos = arg.find_first_of(':'); | 				size_t pos = arg.find_first_of(':'); | ||||||
|  | 				int lut_mode = 0, lut_mode2 = 0; | ||||||
| 				if (pos != string::npos) { | 				if (pos != string::npos) { | ||||||
| 					lut_mode = atoi(arg.substr(0, pos).c_str()); | 					lut_mode = atoi(arg.substr(0, pos).c_str()); | ||||||
| 					lut_mode2 = atoi(arg.substr(pos+1).c_str()); | 					lut_mode2 = atoi(arg.substr(pos+1).c_str()); | ||||||
|  | @ -1348,6 +1351,27 @@ struct AbcPass : public Pass { | ||||||
| 					lut_mode = atoi(arg.c_str()); | 					lut_mode = atoi(arg.c_str()); | ||||||
| 					lut_mode2 = lut_mode; | 					lut_mode2 = lut_mode; | ||||||
| 				} | 				} | ||||||
|  | 				lut_costs.clear(); | ||||||
|  | 				for (int i = 0; i < lut_mode; i++) | ||||||
|  | 					lut_costs.push_back(1); | ||||||
|  | 				for (int i = lut_mode; i < lut_mode2; i++) | ||||||
|  | 					lut_costs.push_back(2 << (i - lut_mode)); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			if (arg == "-luts" && argidx+1 < args.size()) { | ||||||
|  | 				lut_costs.clear(); | ||||||
|  | 				for (auto &tok : split_tokens(args[++argidx], ",")) { | ||||||
|  | 					auto parts = split_tokens(tok, ":"); | ||||||
|  | 					if (GetSize(parts) == 0 && !lut_costs.empty()) | ||||||
|  | 						lut_costs.push_back(lut_costs.back()); | ||||||
|  | 					else if (GetSize(parts) == 1) | ||||||
|  | 						lut_costs.push_back(atoi(parts.at(0).c_str())); | ||||||
|  | 					else if (GetSize(parts) == 2) | ||||||
|  | 						while (GetSize(lut_costs) < atoi(parts.at(0).c_str())) | ||||||
|  | 							lut_costs.push_back(atoi(parts.at(1).c_str())); | ||||||
|  | 					else | ||||||
|  | 						log_cmd_error("Invalid -luts syntax.\n"); | ||||||
|  | 				} | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (arg == "-mux4") { | 			if (arg == "-mux4") { | ||||||
|  | @ -1414,7 +1438,7 @@ struct AbcPass : public Pass { | ||||||
| 		} | 		} | ||||||
| 		extra_args(args, argidx, design); | 		extra_args(args, argidx, design); | ||||||
| 
 | 
 | ||||||
| 		if (lut_mode != 0 && !liberty_file.empty()) | 		if (!lut_costs.empty() && !liberty_file.empty()) | ||||||
| 			log_cmd_error("Got -lut and -liberty! This two options are exclusive.\n"); | 			log_cmd_error("Got -lut and -liberty! This two options are exclusive.\n"); | ||||||
| 		if (!constr_file.empty() && liberty_file.empty()) | 		if (!constr_file.empty() && liberty_file.empty()) | ||||||
| 			log_cmd_error("Got -constr but no -liberty!\n"); | 			log_cmd_error("Got -constr but no -liberty!\n"); | ||||||
|  | @ -1423,7 +1447,7 @@ struct AbcPass : public Pass { | ||||||
| 			if (mod->processes.size() > 0) | 			if (mod->processes.size() > 0) | ||||||
| 				log("Skipping module %s as it contains processes.\n", log_id(mod)); | 				log("Skipping module %s as it contains processes.\n", log_id(mod)); | ||||||
| 			else if (!dff_mode || !clk_str.empty()) | 			else if (!dff_mode || !clk_str.empty()) | ||||||
| 				abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, lut_mode2, dff_mode, clk_str, keepff, delay_target, fast_mode, mod->selected_cells(), show_tempdir); | 				abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff, delay_target, fast_mode, mod->selected_cells(), show_tempdir); | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				assign_map.set(mod); | 				assign_map.set(mod); | ||||||
|  | @ -1567,7 +1591,7 @@ struct AbcPass : public Pass { | ||||||
| 					clk_sig = assign_map(std::get<1>(it.first)); | 					clk_sig = assign_map(std::get<1>(it.first)); | ||||||
| 					en_polarity = std::get<2>(it.first); | 					en_polarity = std::get<2>(it.first); | ||||||
| 					en_sig = assign_map(std::get<3>(it.first)); | 					en_sig = assign_map(std::get<3>(it.first)); | ||||||
| 					abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, lut_mode2, | 					abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, | ||||||
| 							!clk_sig.empty(), "$", keepff, delay_target, fast_mode, it.second, show_tempdir); | 							!clk_sig.empty(), "$", keepff, delay_target, fast_mode, it.second, show_tempdir); | ||||||
| 					assign_map.set(mod); | 					assign_map.set(mod); | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | @ -97,7 +97,7 @@ struct SynthXilinxPass : public Pass { | ||||||
| 		log("        opt -fast\n"); | 		log("        opt -fast\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    map_luts:\n"); | 		log("    map_luts:\n"); | ||||||
| 		log("        abc -lut 5:8 [-dff]\n"); | 		log("        abc -luts 2:2,3,6:5,10,20 [-dff]\n"); | ||||||
| 		log("        clean\n"); | 		log("        clean\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    map_cells:\n"); | 		log("    map_cells:\n"); | ||||||
|  | @ -204,7 +204,7 @@ struct SynthXilinxPass : public Pass { | ||||||
| 
 | 
 | ||||||
| 		if (check_label(active, run_from, run_to, "map_luts")) | 		if (check_label(active, run_from, run_to, "map_luts")) | ||||||
| 		{ | 		{ | ||||||
| 			Pass::call(design, "abc -lut 6:8" + string(retime ? " -dff" : "")); | 			Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); | ||||||
| 			Pass::call(design, "clean"); | 			Pass::call(design, "clean"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue