mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	abc9_ops: -prep_lut and -write_lut to auto-generate LUT library
This commit is contained in:
		
							parent
							
								
									ab8826ae36
								
							
						
					
					
						commit
						5643c1b8c5
					
				
					 4 changed files with 200 additions and 10 deletions
				
			
		|  | @ -145,6 +145,11 @@ struct Abc9Pass : public ScriptPass | |||
| 		log("        generate netlist using luts. Use the specified costs for luts with 1,\n"); | ||||
| 		log("        2, 3, .. inputs.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -maxlut <width>\n"); | ||||
| 		log("        when auto-generating the lut library, discard all luts equal to or\n"); | ||||
| 		log("        greater than this size (applicable when neither -lut nor -luts is\n"); | ||||
| 		log("        specified).\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -dff\n"); | ||||
| 		log("        also pass $_ABC9_FF_ cells through to ABC. modules with many clock\n"); | ||||
| 		log("        domains are marked as such and automatically partitioned by ABC.\n"); | ||||
|  | @ -175,6 +180,8 @@ struct Abc9Pass : public ScriptPass | |||
| 
 | ||||
| 	std::stringstream exe_cmd; | ||||
| 	bool dff_mode, cleanup; | ||||
| 	bool lut_mode; | ||||
| 	int maxlut; | ||||
| 	std::string box_file; | ||||
| 
 | ||||
| 	void clear_flags() YS_OVERRIDE | ||||
|  | @ -183,6 +190,8 @@ struct Abc9Pass : public ScriptPass | |||
| 		exe_cmd << "abc9_exe"; | ||||
| 		dff_mode = false; | ||||
| 		cleanup = true; | ||||
| 		lut_mode = false; | ||||
| 		maxlut = 0; | ||||
| 		box_file.clear(); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -204,9 +213,11 @@ struct Abc9Pass : public ScriptPass | |||
| 		for (argidx = 1; argidx < args.size(); argidx++) { | ||||
| 			std::string arg = args[argidx]; | ||||
| 			if ((arg == "-exe" || arg == "-script" || arg == "-D" || | ||||
| 						/* arg == "-S" || */ arg == "-lut" || arg == "-luts" || | ||||
| 						/*arg == "-S" ||*/ arg == "-lut" || arg == "-luts" || | ||||
| 						/*arg == "-box" ||*/ arg == "-W") && | ||||
| 					argidx+1 < args.size()) { | ||||
| 				if (arg == "-lut" || arg == "-luts") | ||||
| 					lut_mode = true; | ||||
| 				exe_cmd << " " << arg << " " << args[++argidx]; | ||||
| 				continue; | ||||
| 			} | ||||
|  | @ -228,6 +239,10 @@ struct Abc9Pass : public ScriptPass | |||
| 				box_file = args[++argidx]; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (arg == "-maxlut" && argidx+1 < args.size()) { | ||||
| 				maxlut = atoi(args[++argidx].c_str()); | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (arg == "-run" && argidx+1 < args.size()) { | ||||
| 				size_t pos = args[argidx+1].find(':'); | ||||
| 				if (pos == std::string::npos) | ||||
|  | @ -240,6 +255,9 @@ struct Abc9Pass : public ScriptPass | |||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
| 
 | ||||
| 		if (maxlut && lut_mode) | ||||
| 			log_cmd_error("abc9 '-maxlut' option only applicable without '-lut' nor '-luts'.\n"); | ||||
| 
 | ||||
| 		log_assert(design); | ||||
| 		if (design->selected_modules().empty()) { | ||||
| 			log_warning("No modules selected for ABC9 techmapping.\n"); | ||||
|  | @ -263,6 +281,10 @@ struct Abc9Pass : public ScriptPass | |||
| 				run("abc9_ops -mark_scc -prep_delays -prep_xaiger [-dff]", "(option for -dff)"); | ||||
| 			else | ||||
| 				run("abc9_ops -mark_scc -prep_delays -prep_xaiger" + std::string(dff_mode ? " -dff" : ""), "(option for -dff)"); | ||||
| 			if (help_mode) | ||||
| 				run("abc9_ops -prep_lut <maxlut>", "(skip if -lut or -luts)"); | ||||
| 			else if (!lut_mode) | ||||
| 				run(stringf("abc9_ops -prep_lut %d", maxlut)); | ||||
| 			run("select -set abc9_holes A:abc9_holes"); | ||||
| 			run("flatten -wb @abc9_holes"); | ||||
| 			run("techmap @abc9_holes"); | ||||
|  | @ -276,9 +298,10 @@ struct Abc9Pass : public ScriptPass | |||
| 		if (check_label("map")) { | ||||
| 			if (help_mode) { | ||||
| 				run("foreach module in selection"); | ||||
| 				run("    abc9_ops -write_lut <abc-temp-dir>/input.lut", "(skip if '-lut' or '-luts')"); | ||||
| 				run("    abc9_ops -write_box [<value from -box>|(null)] <abc-temp-dir>/input.box"); | ||||
| 				run("    write_xaiger -map <abc-temp-dir>/input.sym <abc-temp-dir>/input.xaig"); | ||||
| 				run("    abc9_exe [options] -cwd <abc-temp-dir> -box <abc-temp-dir>/input.box"); | ||||
| 				run("    abc9_exe [options] -cwd <abc-temp-dir> [-lut <abc-temp-dir>/input.lut] -box <abc-temp-dir>/input.box"); | ||||
| 				run("    read_aiger -xaiger -wideports -module_name <module-name>$abc9 -map <abc-temp-dir>/input.sym <abc-temp-dir>/output.aig"); | ||||
| 				run("    abc9_ops -reintegrate"); | ||||
| 			} | ||||
|  | @ -304,6 +327,8 @@ struct Abc9Pass : public ScriptPass | |||
| 						tempdir_name[0] = tempdir_name[4] = '_'; | ||||
| 					tempdir_name = make_temp_dir(tempdir_name); | ||||
| 
 | ||||
| 					if (!lut_mode) | ||||
| 						run(stringf("abc9_ops -write_lut %s/input.lut", tempdir_name.c_str())); | ||||
| 					if (box_file.empty()) | ||||
| 						run(stringf("abc9_ops -write_box (null) %s/input.box", tempdir_name.c_str())); | ||||
| 					else | ||||
|  | @ -319,7 +344,12 @@ struct Abc9Pass : public ScriptPass | |||
| 							active_design->scratchpad_get_int("write_xaiger.num_inputs"), | ||||
| 							num_outputs); | ||||
| 					if (num_outputs) { | ||||
| 						run(stringf("%s -cwd %s -box %s/input.box", exe_cmd.str().c_str(), tempdir_name.c_str(), tempdir_name.c_str())); | ||||
| 						std::string abc9_exe_cmd; | ||||
| 						abc9_exe_cmd += stringf("%s -cwd %s", exe_cmd.str().c_str(), tempdir_name.c_str()); | ||||
| 						if (!lut_mode) | ||||
| 							abc9_exe_cmd += stringf(" -lut %s/input.lut", tempdir_name.c_str()); | ||||
| 						abc9_exe_cmd += stringf(" -box %s/input.box", tempdir_name.c_str()); | ||||
| 						run(abc9_exe_cmd); | ||||
| 						run(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod), tempdir_name.c_str(), tempdir_name.c_str())); | ||||
| 						run("abc9_ops -reintegrate"); | ||||
| 					} | ||||
|  |  | |||
|  | @ -562,6 +562,56 @@ void prep_delays(RTLIL::Design *design) | |||
| 	design->scratchpad_set_string("abc9_ops.box.flops", ss.str()); | ||||
| } | ||||
| 
 | ||||
| void prep_lut(RTLIL::Design *design, int maxlut) | ||||
| { | ||||
| 	std::stringstream ss; | ||||
| 	std::vector<std::pair<int, std::string>> table; | ||||
| 	for (auto module : design->modules()) { | ||||
| 		auto it = module->attributes.find(ID(abc9_lut)); | ||||
| 		if (it == module->attributes.end()) | ||||
| 			continue; | ||||
| 		SigBit o; | ||||
| 		std::vector<int> specify; | ||||
| 		for (auto cell : module->cells()) { | ||||
| 			if (cell->type != ID($specify2)) | ||||
| 				continue; | ||||
| 			log_assert(cell->getParam(ID(SRC_WIDTH)) == 1); | ||||
| 			log_assert(cell->getParam(ID(DST_WIDTH)) == 1); | ||||
| 			SigBit d = cell->getPort(ID(DST)); | ||||
| 			if (o == SigBit()) | ||||
| 				o = d; | ||||
| 			else | ||||
| 				log_assert(o == d); | ||||
| 			int rise_max = cell->getParam(ID(T_RISE_MAX)).as_int(); | ||||
| 			int fall_max = cell->getParam(ID(T_FALL_MAX)).as_int(); | ||||
| 			specify.push_back(std::max(rise_max,fall_max)); | ||||
| 		} | ||||
| 		if (maxlut && GetSize(specify) > maxlut) | ||||
| 			continue; | ||||
| 		std::sort(specify.begin(), specify.end()); | ||||
| 		ss.str(""); | ||||
| 		ss << "# " << module->name.str() << std::endl; | ||||
| 		ss << GetSize(specify) << " " << it->second.as_int(); | ||||
| 		for (auto i : specify) | ||||
| 			ss << " " << i; | ||||
| 		ss << std::endl; | ||||
| 		table.emplace_back(GetSize(specify), ss.str()); | ||||
| 	} | ||||
| 	// ABC expects ascending size
 | ||||
| 	std::sort(table.begin(), table.end()); | ||||
| 	ss.str(""); | ||||
| 	for (auto &i : table) | ||||
| 		ss << i.second; | ||||
| 	design->scratchpad_set_string("abc9_ops.lut_library", ss.str()); | ||||
| } | ||||
| 
 | ||||
| void write_lut(RTLIL::Module *module, const std::string &dst) { | ||||
| 	std::ofstream ofs(dst); | ||||
| 	log_assert(ofs.is_open()); | ||||
| 	ofs << module->design->scratchpad_get_string("abc9_ops.lut_library"); | ||||
| 	ofs.close(); | ||||
| } | ||||
| 
 | ||||
| void write_box(RTLIL::Module *module, const std::string &src, const std::string &dst) { | ||||
| 	std::ofstream ofs(dst); | ||||
| 	log_assert(ofs.is_open()); | ||||
|  | @ -1002,6 +1052,12 @@ struct Abc9OpsPass : public Pass { | |||
| 		log("        compute the clock domain and initial value of each flop in the design.\n"); | ||||
| 		log("        process the '$holes' module to support clock-enable functionality.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -prep_lut <maxlut>\n"); | ||||
| 		log("        pre-compute the lut library.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -write_lut <dst>\n"); | ||||
| 		log("        TODO.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -write_box (<src>|(null)) <dst>\n"); | ||||
| 		log("        copy the existing box file from <src> (skip if '(null)') and append any\n"); | ||||
| 		log("        new box definitions.\n"); | ||||
|  | @ -1021,8 +1077,11 @@ struct Abc9OpsPass : public Pass { | |||
| 		bool mark_scc_mode = false; | ||||
| 		bool prep_dff_mode = false; | ||||
| 		bool prep_xaiger_mode = false; | ||||
| 		bool prep_lut_mode = false; | ||||
| 		bool reintegrate_mode = false; | ||||
| 		bool dff_mode = false; | ||||
| 		std::string write_lut_dst; | ||||
| 		int maxlut = 0; | ||||
| 		std::string write_box_src, write_box_dst; | ||||
| 
 | ||||
| 		size_t argidx; | ||||
|  | @ -1048,6 +1107,19 @@ struct Abc9OpsPass : public Pass { | |||
| 				prep_delays_mode = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (arg == "-prep_lut" && argidx+1 < args.size()) { | ||||
| 				prep_lut_mode = true; | ||||
| 				maxlut = atoi(args[++argidx].c_str()); | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (arg == "-write_lut" && argidx+1 < args.size()) { | ||||
| 				write_lut_dst = args[++argidx]; | ||||
| 				rewrite_filename(write_lut_dst); | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (arg == "-maxlut" && argidx+1 < args.size()) { | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (arg == "-write_box" && argidx+2 < args.size()) { | ||||
| 				write_box_src = args[++argidx]; | ||||
| 				write_box_dst = args[++argidx]; | ||||
|  | @ -1067,16 +1139,21 @@ struct Abc9OpsPass : public Pass { | |||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
| 
 | ||||
| 		if (!(check_mode || mark_scc_mode || prep_delays_mode || prep_xaiger_mode || prep_dff_mode || !write_box_src.empty() || reintegrate_mode)) | ||||
| 			log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff}, -write_box, -reintegrate must be specified.\n"); | ||||
| 		if (!(check_mode || mark_scc_mode || prep_delays_mode || prep_xaiger_mode || prep_dff_mode || prep_lut_mode || !write_lut_dst.empty() || !write_box_dst.empty() || reintegrate_mode)) | ||||
| 			log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff,lut}, -write_{lut,box}, -reintegrate must be specified.\n"); | ||||
| 
 | ||||
| 		if (dff_mode && !prep_xaiger_mode) | ||||
| 			log_cmd_error("'-dff' option is only relevant for -prep_xaiger.\n"); | ||||
| 
 | ||||
| 		if (maxlut && !write_lut_dst.empty()) | ||||
| 			log_cmd_error("'-maxlut' option is only relevant for -prep_lut.\n"); | ||||
| 
 | ||||
| 		if (check_mode) | ||||
| 			check(design); | ||||
| 		if (prep_delays_mode) | ||||
| 			prep_delays(design); | ||||
| 		if (prep_lut_mode) | ||||
| 			prep_lut(design, maxlut); | ||||
| 
 | ||||
| 		for (auto mod : design->selected_modules()) { | ||||
| 			if (mod->get_bool_attribute("\\abc9_holes")) | ||||
|  | @ -1090,7 +1167,9 @@ struct Abc9OpsPass : public Pass { | |||
| 			if (!design->selected_whole_module(mod)) | ||||
| 				log_error("Can't handle partially selected module %s!\n", log_id(mod)); | ||||
| 
 | ||||
| 			if (!write_box_src.empty()) | ||||
| 			if (!write_lut_dst.empty()) | ||||
| 				write_lut(mod, write_lut_dst); | ||||
| 			if (!write_box_dst.empty()) | ||||
| 				write_box(mod, write_box_src, write_box_dst); | ||||
| 			if (mark_scc_mode) | ||||
| 				mark_scc(mod); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue