mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Add info-file and cover features to write_btor
Signed-off-by: Claire Wolf <claire@symbioticeda.com>
This commit is contained in:
		
							parent
							
								
									a0cc795e85
								
							
						
					
					
						commit
						29e2b2dc05
					
				
					 1 changed files with 113 additions and 9 deletions
				
			
		|  | @ -39,6 +39,7 @@ struct BtorWorker | ||||||
| 	RTLIL::Module *module; | 	RTLIL::Module *module; | ||||||
| 	bool verbose; | 	bool verbose; | ||||||
| 	bool single_bad; | 	bool single_bad; | ||||||
|  | 	bool cover_mode; | ||||||
| 
 | 
 | ||||||
| 	int next_nid = 1; | 	int next_nid = 1; | ||||||
| 	int initstate_nid = -1; | 	int initstate_nid = -1; | ||||||
|  | @ -71,7 +72,10 @@ struct BtorWorker | ||||||
| 	vector<int> bad_properties; | 	vector<int> bad_properties; | ||||||
| 	dict<SigBit, bool> initbits; | 	dict<SigBit, bool> initbits; | ||||||
| 	pool<Wire*> statewires; | 	pool<Wire*> statewires; | ||||||
| 	string indent; | 
 | ||||||
|  | 	string indent, info_filename; | ||||||
|  | 	vector<string> info_lines; | ||||||
|  | 	dict<int, int> info_clocks; | ||||||
| 
 | 
 | ||||||
| 	void btorf(const char *fmt, ...) | 	void btorf(const char *fmt, ...) | ||||||
| 	{ | 	{ | ||||||
|  | @ -81,6 +85,14 @@ struct BtorWorker | ||||||
| 		va_end(ap); | 		va_end(ap); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	void infof(const char *fmt, ...) | ||||||
|  | 	{ | ||||||
|  | 		va_list ap; | ||||||
|  | 		va_start(ap, fmt); | ||||||
|  | 		info_lines.push_back(vstringf(fmt, ap)); | ||||||
|  | 		va_end(ap); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	void btorf_push(const string &id) | 	void btorf_push(const string &id) | ||||||
| 	{ | 	{ | ||||||
| 		if (verbose) { | 		if (verbose) { | ||||||
|  | @ -544,11 +556,26 @@ struct BtorWorker | ||||||
| 			goto okay; | 			goto okay; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (cell->type.in("$dff", "$ff", "$_DFF_P_", "$_DFF_N", "$_FF_")) | 		if (cell->type.in("$dff", "$ff", "$_DFF_P_", "$_DFF_N_", "$_FF_")) | ||||||
| 		{ | 		{ | ||||||
| 			SigSpec sig_d = sigmap(cell->getPort("\\D")); | 			SigSpec sig_d = sigmap(cell->getPort("\\D")); | ||||||
| 			SigSpec sig_q = sigmap(cell->getPort("\\Q")); | 			SigSpec sig_q = sigmap(cell->getPort("\\Q")); | ||||||
| 
 | 
 | ||||||
|  | 			if (!info_filename.empty() && cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_")) | ||||||
|  | 			{ | ||||||
|  | 				SigSpec sig_c = sigmap(cell->getPort(cell->type == "$dff" ? "\\CLK" : "\\C")); | ||||||
|  | 				int nid = get_sig_nid(sig_c); | ||||||
|  | 				bool negedge = false; | ||||||
|  | 
 | ||||||
|  | 				if (cell->type == "$_DFF_N_") | ||||||
|  | 					negedge = true; | ||||||
|  | 
 | ||||||
|  | 				if (cell->type == "$dff" && !cell->getParam("\\CLK_POLARITY").as_bool()) | ||||||
|  | 					negedge = true; | ||||||
|  | 
 | ||||||
|  | 				info_clocks[nid] |= negedge ? 2 : 1; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			IdString symbol; | 			IdString symbol; | ||||||
| 
 | 
 | ||||||
| 			if (sig_q.is_wire()) { | 			if (sig_q.is_wire()) { | ||||||
|  | @ -983,9 +1010,12 @@ struct BtorWorker | ||||||
| 		return nid; | 		return nid; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	BtorWorker(std::ostream &f, RTLIL::Module *module, bool verbose, bool single_bad) : | 	BtorWorker(std::ostream &f, RTLIL::Module *module, bool verbose, bool single_bad, bool cover_mode, string info_filename) : | ||||||
| 			f(f), sigmap(module), module(module), verbose(verbose), single_bad(single_bad) | 			f(f), sigmap(module), module(module), verbose(verbose), single_bad(single_bad), cover_mode(cover_mode), info_filename(info_filename) | ||||||
| 	{ | 	{ | ||||||
|  | 		if (!info_filename.empty()) | ||||||
|  | 			infof("name %s\n", log_id(module)); | ||||||
|  | 
 | ||||||
| 		btorf_push("inputs"); | 		btorf_push("inputs"); | ||||||
| 
 | 
 | ||||||
| 		for (auto wire : module->wires()) | 		for (auto wire : module->wires()) | ||||||
|  | @ -1066,17 +1096,47 @@ struct BtorWorker | ||||||
| 				btorf("%d not %d %d\n", nid_not_a, sid, nid_a); | 				btorf("%d not %d %d\n", nid_not_a, sid, nid_a); | ||||||
| 				btorf("%d and %d %d %d\n", nid_en_and_not_a, sid, nid_en, nid_not_a); | 				btorf("%d and %d %d %d\n", nid_en_and_not_a, sid, nid_en, nid_not_a); | ||||||
| 
 | 
 | ||||||
| 				if (single_bad) { | 				if (single_bad && !cover_mode) { | ||||||
| 					bad_properties.push_back(nid_en_and_not_a); | 					bad_properties.push_back(nid_en_and_not_a); | ||||||
| 				} else { | 				} else { | ||||||
| 					int nid = next_nid++; |  | ||||||
| 					string infostr = log_id(cell); | 					string infostr = log_id(cell); | ||||||
| 					if (infostr[0] == '$' && cell->attributes.count("\\src")) { | 					if (infostr[0] == '$' && cell->attributes.count("\\src")) { | ||||||
| 						infostr = cell->attributes.at("\\src").decode_string().c_str(); | 						infostr = cell->attributes.at("\\src").decode_string().c_str(); | ||||||
| 						std::replace(infostr.begin(), infostr.end(), ' ', '_'); | 						std::replace(infostr.begin(), infostr.end(), ' ', '_'); | ||||||
| 					} | 					} | ||||||
|  | 					if (cover_mode) { | ||||||
|  | 						infof("bad %d %s\n", nid_en_and_not_a, infostr.c_str()); | ||||||
|  | 					} else { | ||||||
|  | 						int nid = next_nid++; | ||||||
| 						btorf("%d bad %d %s\n", nid, nid_en_and_not_a, infostr.c_str()); | 						btorf("%d bad %d %s\n", nid, nid_en_and_not_a, infostr.c_str()); | ||||||
| 					} | 					} | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				btorf_pop(log_id(cell)); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (cell->type == "$cover" && cover_mode) | ||||||
|  | 			{ | ||||||
|  | 				btorf_push(log_id(cell)); | ||||||
|  | 
 | ||||||
|  | 				int sid = get_bv_sid(1); | ||||||
|  | 				int nid_a = get_sig_nid(cell->getPort("\\A")); | ||||||
|  | 				int nid_en = get_sig_nid(cell->getPort("\\EN")); | ||||||
|  | 				int nid_en_and_a = next_nid++; | ||||||
|  | 
 | ||||||
|  | 				btorf("%d and %d %d %d\n", nid_en_and_a, sid, nid_en, nid_a); | ||||||
|  | 
 | ||||||
|  | 				if (single_bad) { | ||||||
|  | 					bad_properties.push_back(nid_en_and_a); | ||||||
|  | 				} else { | ||||||
|  | 					string infostr = log_id(cell); | ||||||
|  | 					if (infostr[0] == '$' && cell->attributes.count("\\src")) { | ||||||
|  | 						infostr = cell->attributes.at("\\src").decode_string().c_str(); | ||||||
|  | 						std::replace(infostr.begin(), infostr.end(), ' ', '_'); | ||||||
|  | 					} | ||||||
|  | 					int nid = next_nid++; | ||||||
|  | 					btorf("%d bad %d %s\n", nid, nid_en_and_a, infostr.c_str()); | ||||||
|  | 				} | ||||||
| 
 | 
 | ||||||
| 				btorf_pop(log_id(cell)); | 				btorf_pop(log_id(cell)); | ||||||
| 			} | 			} | ||||||
|  | @ -1210,6 +1270,35 @@ struct BtorWorker | ||||||
| 				btorf("%d bad %d\n", nid, todo[cursor]); | 				btorf("%d bad %d\n", nid, todo[cursor]); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		if (!info_filename.empty()) | ||||||
|  | 		{ | ||||||
|  | 			for (auto &it : info_clocks) | ||||||
|  | 			{ | ||||||
|  | 				switch (it.second) | ||||||
|  | 				{ | ||||||
|  | 				case 1: | ||||||
|  | 					infof("posedge %d\n", it.first); | ||||||
|  | 					break; | ||||||
|  | 				case 2: | ||||||
|  | 					infof("negedge %d\n", it.first); | ||||||
|  | 					break; | ||||||
|  | 				case 3: | ||||||
|  | 					infof("event %d\n", it.first); | ||||||
|  | 					break; | ||||||
|  | 				default: | ||||||
|  | 					log_abort(); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			std::ofstream f; | ||||||
|  | 			f.open(info_filename.c_str(), std::ofstream::trunc); | ||||||
|  | 			if (f.fail()) | ||||||
|  | 				log_error("Can't open file `%s' for writing: %s\n", info_filename.c_str(), strerror(errno)); | ||||||
|  | 			for (auto &it : info_lines) | ||||||
|  | 				f << it; | ||||||
|  | 			f.close(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -1229,10 +1318,17 @@ struct BtorBackend : public Backend { | ||||||
| 		log("  -s\n"); | 		log("  -s\n"); | ||||||
| 		log("    Output only a single bad property for all asserts\n"); | 		log("    Output only a single bad property for all asserts\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | 		log("  -c\n"); | ||||||
|  | 		log("    Output cover properties using 'bad' statements instead of asserts\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("  -i <filename>\n"); | ||||||
|  | 		log("    Create additional info file with auxiliary information\n"); | ||||||
|  | 		log("\n"); | ||||||
| 	} | 	} | ||||||
| 	void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | 	void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
| 		bool verbose = false, single_bad = false; | 		bool verbose = false, single_bad = false, cover_mode = false; | ||||||
|  | 		string info_filename; | ||||||
| 
 | 
 | ||||||
| 		log_header(design, "Executing BTOR backend.\n"); | 		log_header(design, "Executing BTOR backend.\n"); | ||||||
| 
 | 
 | ||||||
|  | @ -1247,6 +1343,14 @@ struct BtorBackend : public Backend { | ||||||
| 				single_bad = true; | 				single_bad = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			if (args[argidx] == "-c") { | ||||||
|  | 				cover_mode = true; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			if (args[argidx] == "-i" && argidx+1 < args.size()) { | ||||||
|  | 				info_filename = args[++argidx]; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		extra_args(f, filename, args, argidx); | 		extra_args(f, filename, args, argidx); | ||||||
|  | @ -1259,7 +1363,7 @@ struct BtorBackend : public Backend { | ||||||
| 		*f << stringf("; BTOR description generated by %s for module %s.\n", | 		*f << stringf("; BTOR description generated by %s for module %s.\n", | ||||||
| 				yosys_version_str, log_id(topmod)); | 				yosys_version_str, log_id(topmod)); | ||||||
| 
 | 
 | ||||||
| 		BtorWorker(*f, topmod, verbose, single_bad); | 		BtorWorker(*f, topmod, verbose, single_bad, cover_mode, info_filename); | ||||||
| 
 | 
 | ||||||
| 		*f << stringf("; end of yosys output\n"); | 		*f << stringf("; end of yosys output\n"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue