mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Clean up passes/sat/qbfsat.cc.
				
					
				
			This commit is contained in:
		
							parent
							
								
									437afa1f0c
								
							
						
					
					
						commit
						d07ac2612b
					
				
					 1 changed files with 101 additions and 86 deletions
				
			
		|  | @ -54,8 +54,9 @@ struct QbfSolveOptions { | |||
| 	std::string specialize_soln_file; | ||||
| 	std::string write_soln_soln_file; | ||||
| 	std::string dump_final_smt2_file; | ||||
| 	size_t argidx; | ||||
| 	QbfSolveOptions() : timeout(false), specialize(false), specialize_from_file(false), write_solution(false),	 | ||||
| 				nocleanup(false), dump_final_smt2(false), timeout_sec(-1) {}; | ||||
| 				nocleanup(false), dump_final_smt2(false), timeout_sec(-1), argidx(0) {}; | ||||
| }; | ||||
| 
 | ||||
| void recover_solution(QbfSolutionType &sol) { | ||||
|  | @ -118,6 +119,21 @@ void specialize(RTLIL::Module *module, const QbfSolutionType &ret) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| void allconstify_inputs(RTLIL::Module *module, const std::set<std::string> &input_wires) { | ||||
| 	for(auto &n : input_wires) { | ||||
| 		RTLIL::Wire *input = module->wire(n); | ||||
| 		log_assert(input != nullptr); | ||||
| 
 | ||||
| 		RTLIL::Cell *allconst = module->addCell("$allconst$" + n, "$allconst"); | ||||
| 		allconst->setParam(ID(WIDTH), input->width); | ||||
| 		allconst->setPort(ID::Y, input); | ||||
| 		allconst->set_src_attribute(input->get_src_attribute()); | ||||
| 		input->port_input = false; | ||||
| 		log("Replaced input %s with $allconst cell.\n", n.c_str()); | ||||
| 	} | ||||
| 	module->fixup_ports(); | ||||
| } | ||||
| 
 | ||||
| QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) { | ||||
| 	QbfSolutionType ret; | ||||
| 	std::string yosys_smtbmc_exe = proc_self_dirname() + "yosys-smtbmc"; | ||||
|  | @ -193,6 +209,86 @@ QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) { | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| std::set<std::string> validate_design_and_get_inputs(RTLIL::Module *module) { | ||||
| 	bool found_input = false; | ||||
| 	bool found_hole = false; | ||||
| 	bool found_1bit_output = false; | ||||
| 	std::set<std::string> input_wires; | ||||
| 	for (auto wire : module->wires()) { | ||||
| 		if (wire->port_input) { | ||||
| 			found_input = true; | ||||
| 			input_wires.insert(wire->name.str()); | ||||
| 		} | ||||
| 		if (wire->port_output && wire->width == 1) | ||||
| 			found_1bit_output = true; | ||||
| 	} | ||||
| 	for (auto cell : module->cells()) { | ||||
| 		if (cell->type == "$allconst") | ||||
| 			found_input = true; | ||||
| 		if (cell->type == "$anyconst") | ||||
| 			found_hole = true; | ||||
| 		if (cell->type.in("$assert", "$assume")) | ||||
| 			found_1bit_output = true; | ||||
| 	} | ||||
| 	if (!found_input) | ||||
| 		log_cmd_error("Can't perform QBF-SAT on a miter with no inputs!\n"); | ||||
| 	if (!found_hole) | ||||
| 		log_cmd_error("Did not find any existentially-quantified variables. Use 'sat' instead.\n"); | ||||
| 	if (!found_1bit_output) | ||||
| 		log_cmd_error("Did not find any single-bit outputs, assert()s, or assume()s.  Is this a miter circuit?\n"); | ||||
| 
 | ||||
| 	return input_wires; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| QbfSolveOptions parse_args(const std::vector<std::string> &args) { | ||||
| 	QbfSolveOptions opt; | ||||
| 	for (opt.argidx = 1; opt.argidx < args.size(); opt.argidx++) { | ||||
| 		if (args[opt.argidx] == "-timeout") { | ||||
| 			opt.timeout = true; | ||||
| 			if (args.size() <= opt.argidx + 1) | ||||
| 				log_cmd_error("timeout not specified.\n"); | ||||
| 			else | ||||
| 				opt.timeout_sec = atol(args[++opt.argidx].c_str()); | ||||
| 			continue; | ||||
| 		} | ||||
| 		else if (args[opt.argidx] == "-nocleanup") { | ||||
| 			opt.nocleanup = true; | ||||
| 			continue; | ||||
| 		} | ||||
| 		else if (args[opt.argidx] == "-specialize") { | ||||
| 			opt.specialize = true; | ||||
| 			continue; | ||||
| 		} | ||||
| 		else if (args[opt.argidx] == "-dump-final-smt2") { | ||||
| 			opt.dump_final_smt2 = true; | ||||
| 			if (args.size() <= opt.argidx + 1) | ||||
| 				log_cmd_error("smt2 file not specified.\n"); | ||||
| 			else | ||||
| 				opt.dump_final_smt2_file = args[++opt.argidx]; | ||||
| 			continue; | ||||
| 		} | ||||
| 		else if (args[opt.argidx] == "-specialize-from-file") { | ||||
| 			opt.specialize_from_file = true; | ||||
| 			if (args.size() <= opt.argidx + 1) | ||||
| 				log_cmd_error("solution file not specified.\n"); | ||||
| 			else | ||||
| 				opt.specialize_soln_file = args[++opt.argidx]; | ||||
| 			continue; | ||||
| 		} | ||||
| 		else if (args[opt.argidx] == "-write-solution") { | ||||
| 			opt.write_solution = true; | ||||
| 			if (args.size() <= opt.argidx + 1) | ||||
| 				log_cmd_error("solution file not specified.\n"); | ||||
| 			else | ||||
| 				opt.write_soln_soln_file = args[++opt.argidx]; | ||||
| 			continue; | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	return opt; | ||||
| } | ||||
| 
 | ||||
| void print_proof_failed() | ||||
| { | ||||
|  | @ -260,54 +356,10 @@ struct QbfSatPass : public Pass { | |||
| 	} | ||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||
| 	{ | ||||
| 		QbfSolveOptions opt; | ||||
| 		log_header(design, "Executing QBF-SAT pass (solving QBF-SAT problems in the circuit).\n"); | ||||
| 		QbfSolveOptions opt = parse_args(args); | ||||
| 		extra_args(args, opt.argidx, design); | ||||
| 
 | ||||
| 		size_t argidx; | ||||
| 		for (argidx = 1; argidx < args.size(); argidx++) { | ||||
| 			if (args[argidx] == "-timeout") { | ||||
| 				opt.timeout = true; | ||||
| 				if (args.size() <= argidx + 1) | ||||
| 					log_cmd_error("timeout not specified.\n"); | ||||
| 				else | ||||
| 					opt.timeout_sec = atol(args[++argidx].c_str()); | ||||
| 				continue; | ||||
| 			} | ||||
| 			else if (args[argidx] == "-nocleanup") { | ||||
| 				opt.nocleanup = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			else if (args[argidx] == "-specialize") { | ||||
| 				opt.specialize = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			else if (args[argidx] == "-dump-final-smt2") { | ||||
| 				opt.dump_final_smt2 = true; | ||||
| 				if (args.size() <= argidx + 1) | ||||
| 					log_cmd_error("smt2 file not specified.\n"); | ||||
| 				else | ||||
| 					opt.dump_final_smt2_file = args[++argidx]; | ||||
| 				continue; | ||||
| 			} | ||||
| 			else if (args[argidx] == "-specialize-from-file") { | ||||
| 				opt.specialize_from_file = true; | ||||
| 				if (args.size() <= argidx + 1) | ||||
| 					log_cmd_error("solution file not specified.\n"); | ||||
| 				else | ||||
| 					opt.specialize_soln_file = args[++argidx]; | ||||
| 				continue; | ||||
| 			} | ||||
| 			else if (args[argidx] == "-write-solution") { | ||||
| 				opt.write_solution = true; | ||||
| 				if (args.size() <= argidx + 1) | ||||
| 					log_cmd_error("solution file not specified.\n"); | ||||
| 				else | ||||
| 					opt.write_soln_soln_file = args[++argidx]; | ||||
| 				continue; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
| 
 | ||||
| 		RTLIL::Module *module = NULL; | ||||
| 		for (auto mod : design->selected_modules()) { | ||||
|  | @ -318,50 +370,13 @@ struct QbfSatPass : public Pass { | |||
| 		if (module == NULL) | ||||
| 			log_cmd_error("Can't perform QBF-SAT on an empty selection!\n"); | ||||
| 
 | ||||
| 		bool found_input = false; | ||||
| 		bool found_hole = false; | ||||
| 		bool found_1bit_output = false; | ||||
| 		std::set<std::string> input_wires; | ||||
| 		for (auto wire : module->wires()) { | ||||
| 			if (wire->port_input) { | ||||
| 				found_input = true; | ||||
| 				input_wires.insert(wire->name.str()); | ||||
| 			} | ||||
| 			if (wire->port_output && wire->width == 1) | ||||
| 				found_1bit_output = true; | ||||
| 		} | ||||
| 		for (auto cell : module->cells()) { | ||||
| 			if (cell->type == "$allconst") | ||||
| 				found_input = true; | ||||
| 			if (cell->type == "$anyconst") | ||||
| 				found_hole = true; | ||||
| 			if (cell->type.in("$assert", "$assume")) | ||||
| 				found_1bit_output = true; | ||||
| 		} | ||||
| 		if (!found_input) | ||||
| 			log_cmd_error("Can't perform QBF-SAT on a miter with no inputs!\n"); | ||||
| 		if (!found_hole) | ||||
| 			log_cmd_error("Did not find any existentially-quantified variables. Use 'sat' instead.\n"); | ||||
| 		if (!found_1bit_output) | ||||
| 			log_cmd_error("Did not find any single-bit outputs, assert()s, or assume()s.  Is this a miter circuit?\n"); | ||||
| 
 | ||||
| 		//Save the design to restore after modiyfing the current module.
 | ||||
| 		std::string module_name = module->name.str(); | ||||
| 		Pass::call(design, "design -save _qbfsat_tmp"); | ||||
| 
 | ||||
| 		//Replace input wires with wires assigned $allconst cells.
 | ||||
| 		for(auto &n : input_wires) { | ||||
| 			RTLIL::Wire *input = module->wire(n); | ||||
| 			log_assert(input != nullptr); | ||||
| 
 | ||||
| 			RTLIL::Cell *allconst = module->addCell("$allconst$" + n, "$allconst"); | ||||
| 			allconst->setParam(ID(WIDTH), input->width); | ||||
| 			allconst->setPort(ID::Y, input); | ||||
| 			allconst->set_src_attribute(input->get_src_attribute()); | ||||
| 			input->port_input = false; | ||||
| 			log("Replaced input %s with $allconst cell.\n", n.c_str()); | ||||
| 		} | ||||
| 		module->fixup_ports(); | ||||
| 		std::set<std::string> input_wires = validate_design_and_get_inputs(module); | ||||
| 		allconstify_inputs(module, input_wires); | ||||
| 
 | ||||
| 		QbfSolutionType ret = qbf_solve(module, opt); | ||||
| 		Pass::call(design, "design -load _qbfsat_tmp"); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue