mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Make log() use the FmtString infrastructure.
				
					
				
			Now `log()` supports `std::string`. We have to fix a few places where the format parameter was not a compile time constant. This is mostly trivial.
This commit is contained in:
		
							parent
							
								
									3f69a768f4
								
							
						
					
					
						commit
						d34ac0c87d
					
				
					 10 changed files with 74 additions and 45 deletions
				
			
		|  | @ -3478,8 +3478,8 @@ struct CxxrtlWorker { | |||
| }; | ||||
| 
 | ||||
| struct CxxrtlBackend : public Backend { | ||||
| 	static const int DEFAULT_OPT_LEVEL = 6; | ||||
| 	static const int DEFAULT_DEBUG_LEVEL = 4; | ||||
| 	static constexpr int DEFAULT_OPT_LEVEL = 6; | ||||
| 	static constexpr int DEFAULT_DEBUG_LEVEL = 4; | ||||
| 
 | ||||
| 	CxxrtlBackend() : Backend("cxxrtl", "convert design to C++ RTL simulation") { } | ||||
| 	void help() override | ||||
|  |  | |||
|  | @ -437,6 +437,7 @@ public: | |||
| 	{ | ||||
| 		return format_emit_toplevel(fmt, has_escapes, specs, args...); | ||||
| 	} | ||||
| 	std::string_view format_string() const { return fmt; } | ||||
| private: | ||||
| 	std::string_view fmt; | ||||
| 	bool has_escapes = false; | ||||
|  |  | |||
|  | @ -102,17 +102,16 @@ int gettimeofday(struct timeval *tv, struct timezone *tz) | |||
| } | ||||
| #endif | ||||
| 
 | ||||
| static void logv(const char *format, va_list ap) | ||||
| { | ||||
| 	while (format[0] == '\n' && format[1] != 0) { | ||||
| 		log("\n"); | ||||
| 		format++; | ||||
| static void logv_string(std::string_view format, std::string str) { | ||||
| 	size_t remove_leading = 0; | ||||
| 	while (format.size() > 1 && format[0] == '\n') { | ||||
| 		logv_string("\n", "\n"); | ||||
| 		format = format.substr(1); | ||||
| 		++remove_leading; | ||||
| 	} | ||||
| 	if (remove_leading > 0) { | ||||
| 		str = str.substr(remove_leading); | ||||
| 	} | ||||
| 
 | ||||
| 	if (log_make_debug && !ys_debug(1)) | ||||
| 		return; | ||||
| 
 | ||||
| 	std::string str = vstringf(format, ap); | ||||
| 
 | ||||
| 	if (str.empty()) | ||||
| 		return; | ||||
|  | @ -145,13 +144,13 @@ static void logv(const char *format, va_list ap) | |||
| 			time_str += stringf("[%05d.%06d] ", int(tv.tv_sec), int(tv.tv_usec)); | ||||
| 		} | ||||
| 
 | ||||
| 		if (format[0] && format[strlen(format)-1] == '\n') | ||||
| 		if (!format.empty() && format[format.size() - 1] == '\n') | ||||
| 			next_print_log = true; | ||||
| 
 | ||||
| 		// Special case to detect newlines in Python log output, since
 | ||||
| 		// the binding always calls `log("%s", payload)` and the newline
 | ||||
| 		// is then in the first formatted argument
 | ||||
| 		if (!strcmp(format, "%s") && str.back() == '\n') | ||||
| 		if (format == "%s" && str.back() == '\n') | ||||
| 			next_print_log = true; | ||||
| 
 | ||||
| 		for (auto f : log_files) | ||||
|  | @ -204,6 +203,20 @@ static void logv(const char *format, va_list ap) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void logv(const char *format, va_list ap) | ||||
| { | ||||
| 	if (log_make_debug && !ys_debug(1)) | ||||
| 		return; | ||||
| 	logv_string(format, vstringf(format, ap)); | ||||
| } | ||||
| 
 | ||||
| void log_formatted_string(std::string_view format, std::string str) | ||||
| { | ||||
| 	if (log_make_debug && !ys_debug(1)) | ||||
| 		return; | ||||
| 	logv_string(format, std::move(str)); | ||||
| } | ||||
| 
 | ||||
| static void logv_header(RTLIL::Design *design, const char *format, va_list ap) | ||||
| { | ||||
| 	bool pop_errfile = false; | ||||
|  | @ -412,14 +425,6 @@ void log_file_error(const string &filename, int lineno, | |||
| 	logv_file_error(filename, lineno, format, ap); | ||||
| } | ||||
| 
 | ||||
| void log(const char *format, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
| 	va_start(ap, format); | ||||
| 	logv(format, ap); | ||||
| 	va_end(ap); | ||||
| } | ||||
| 
 | ||||
| void log_header(RTLIL::Design *design, const char *format, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
|  |  | |||
							
								
								
									
										35
									
								
								kernel/log.h
									
										
									
									
									
								
							
							
						
						
									
										35
									
								
								kernel/log.h
									
										
									
									
									
								
							|  | @ -121,7 +121,7 @@ extern int log_debug_suppressed; | |||
| 
 | ||||
| [[noreturn]] void logv_file_error(const string &filename, int lineno, const char *format, va_list ap); | ||||
| 
 | ||||
| void log(const char *format, ...)  YS_ATTRIBUTE(format(printf, 1, 2)); | ||||
| 
 | ||||
| void log_header(RTLIL::Design *design, const char *format, ...) YS_ATTRIBUTE(format(printf, 2, 3)); | ||||
| void log_warning(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); | ||||
| void log_experimental(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2)); | ||||
|  | @ -145,6 +145,15 @@ static inline bool ys_debug(int = 0) { return false; } | |||
| #endif | ||||
| #  define log_debug(...) do { if (ys_debug(1)) log(__VA_ARGS__); } while (0) | ||||
| 
 | ||||
| void log_formatted_string(std::string_view format, std::string str); | ||||
| template <typename... Args> | ||||
| inline void log(FmtString<TypeIdentity<Args>...> fmt, const Args &... args) | ||||
| { | ||||
| 	if (log_make_debug && !ys_debug(1)) | ||||
| 		return; | ||||
| 	log_formatted_string(fmt.format_string(), fmt.format(args...)); | ||||
| } | ||||
| 
 | ||||
| static inline void log_suppressed() { | ||||
| 	if (log_debug_suppressed && !log_make_debug) { | ||||
| 		log("<suppressed ~%d debug messages>\n", log_debug_suppressed); | ||||
|  | @ -346,8 +355,22 @@ static inline void log_dump_val_worker(unsigned long int v) { log("%lu", v); } | |||
| static inline void log_dump_val_worker(long long int v) { log("%lld", v); } | ||||
| static inline void log_dump_val_worker(unsigned long long int v) { log("%lld", v); } | ||||
| #endif | ||||
| static inline void log_dump_val_worker(char c) { log(c >= 32 && c < 127 ? "'%c'" : "'\\x%02x'", c); } | ||||
| static inline void log_dump_val_worker(unsigned char c) { log(c >= 32 && c < 127 ? "'%c'" : "'\\x%02x'", c); } | ||||
| static inline void log_dump_val_worker(char c) | ||||
| { | ||||
| 	if (c >= 32 && c < 127) { | ||||
| 		log("'%c'", c); | ||||
| 	} else { | ||||
| 		log("'\\x%02x'", c); | ||||
| 	} | ||||
| } | ||||
| static inline void log_dump_val_worker(unsigned char c) | ||||
| { | ||||
| 	if (c >= 32 && c < 127) { | ||||
| 		log("'%c'", c); | ||||
| 	} else { | ||||
| 		log("'\\x%02x'", c); | ||||
| 	} | ||||
| } | ||||
| static inline void log_dump_val_worker(bool v) { log("%s", v ? "true" : "false"); } | ||||
| static inline void log_dump_val_worker(double v) { log("%f", v); } | ||||
| static inline void log_dump_val_worker(char *v) { log("%s", v); } | ||||
|  | @ -369,7 +392,7 @@ static inline void log_dump_val_worker(dict<K, T> &v) { | |||
| 	log("{"); | ||||
| 	bool first = true; | ||||
| 	for (auto &it : v) { | ||||
| 		log(first ? " " : ", "); | ||||
| 		log("%s ", first ? "" : ","); | ||||
| 		log_dump_val_worker(it.first); | ||||
| 		log(": "); | ||||
| 		log_dump_val_worker(it.second); | ||||
|  | @ -383,7 +406,7 @@ static inline void log_dump_val_worker(pool<K> &v) { | |||
| 	log("{"); | ||||
| 	bool first = true; | ||||
| 	for (auto &it : v) { | ||||
| 		log(first ? " " : ", "); | ||||
| 		log("%s ", first ? "" : ","); | ||||
| 		log_dump_val_worker(it); | ||||
| 		first = false; | ||||
| 	} | ||||
|  | @ -395,7 +418,7 @@ static inline void log_dump_val_worker(std::vector<K> &v) { | |||
| 	log("{"); | ||||
| 	bool first = true; | ||||
| 	for (auto &it : v) { | ||||
| 		log(first ? " " : ", "); | ||||
| 		log("%s ", first ? "" : ","); | ||||
| 		log_dump_val_worker(it); | ||||
| 		first = false; | ||||
| 	} | ||||
|  |  | |||
|  | @ -101,13 +101,13 @@ struct LogPass : public Pass { | |||
| 			text += args[argidx] + ' '; | ||||
| 		if (!text.empty()) text.resize(text.size()-1); | ||||
| 
 | ||||
| 		const char *fmtline = newline ? "%s\n" : "%s"; | ||||
| 		const char *line_end = newline ? "\n" : ""; | ||||
| 
 | ||||
| 		if (to_stdout) fprintf(stdout, fmtline, text.c_str()); | ||||
| 		if (to_stderr) fprintf(stderr, fmtline, text.c_str()); | ||||
| 		if (to_stdout) fprintf(stdout, "%s%s", text.c_str(), line_end); | ||||
| 		if (to_stderr) fprintf(stderr, "%s%s", text.c_str(), line_end); | ||||
| 		if (to_log) { | ||||
| 			if (!header) log(fmtline, text.c_str()); | ||||
| 			else log_header(design, fmtline, text.c_str()); | ||||
| 			if (!header) log("%s%s", text.c_str(), line_end); | ||||
| 			else log_header(design, "%s%s", text.c_str(), line_end); | ||||
| 		} | ||||
| 	} | ||||
| } LogPass; | ||||
|  |  | |||
|  | @ -1017,7 +1017,7 @@ struct StatPass : public Pass { | |||
| 
 | ||||
| 		if (json_mode) { | ||||
| 			log("\n"); | ||||
| 			log(top_mod == nullptr ? "   }\n" : "   },\n"); | ||||
| 			log("%s", top_mod == nullptr ? "   }\n" : "   },\n"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (top_mod != nullptr) { | ||||
|  |  | |||
|  | @ -331,7 +331,7 @@ struct EquivSimpleWorker | |||
| 			construct_ezsat(input_bits, step); | ||||
| 
 | ||||
| 			if (!ez->solve(ez_context)) { | ||||
| 				log(cfg.verbose ? "    Proved equivalence! Marking $equiv cell as proven.\n" : " success!\n"); | ||||
| 				log("%s", cfg.verbose ? "    Proved equivalence! Marking $equiv cell as proven.\n" : " success!\n"); | ||||
| 				// Replace $equiv cell with a short
 | ||||
| 				cell->setPort(ID::B, cell->getPort(ID::A)); | ||||
| 				ez->assume(ez->NOT(ez_context)); | ||||
|  |  | |||
|  | @ -634,10 +634,10 @@ struct SatHelper | |||
| 						    "---------------------------------------------------------------------------------------------------" | ||||
| 						    "---------------------------------------------------------------------------------------------------"; | ||||
| 				if (last_timestep == -2) { | ||||
| 					log(max_timestep > 0 ? "  Time " : "  "); | ||||
| 					log("%s", max_timestep > 0 ? "  Time " : "  "); | ||||
| 					log("%-*s %11s %9s %*s\n", maxModelName+5, "Signal Name", "Dec", "Hex", maxModelWidth+3, "Bin"); | ||||
| 				} | ||||
| 				log(max_timestep > 0 ? "  ---- " : "  "); | ||||
| 				log("%s", max_timestep > 0 ? "  ---- " : "  "); | ||||
| 				log("%*.*s %11.11s %9.9s %*.*s\n", maxModelName+5, maxModelName+5, | ||||
| 						hline, hline, hline, maxModelWidth+3, maxModelWidth+3, hline); | ||||
| 				last_timestep = info.timestep; | ||||
|  |  | |||
|  | @ -135,7 +135,7 @@ static bool parse_next_state(const LibertyAst *cell, const LibertyAst *attr, std | |||
| 	if (ff == nullptr || ff->args.size() != 2) | ||||
| 		return false; | ||||
| 	auto ff_output = ff->args.at(0); | ||||
| 	 | ||||
| 
 | ||||
| 	// This test is redundant with the one in enable_pin, but we're in a
 | ||||
| 	// position that gives better diagnostics here.
 | ||||
| 	if (!pin_names.count(ff_output)) { | ||||
|  | @ -166,23 +166,23 @@ static bool parse_next_state(const LibertyAst *cell, const LibertyAst *attr, std | |||
| 		// the ff output Q is in a known bit location, so we now just have to compare the LUT mask to known values to find the enable pin and polarity.
 | ||||
| 		if (lut == 0xD8) { | ||||
| 			data_name = pins[1]; | ||||
| 			enable_name = pins[0];	 | ||||
| 			enable_name = pins[0]; | ||||
| 			return true; | ||||
| 		} | ||||
| 		if (lut == 0xB8) { | ||||
| 			data_name = pins[0]; | ||||
| 			enable_name = pins[1];	 | ||||
| 			enable_name = pins[1]; | ||||
| 			return true; | ||||
| 		} | ||||
| 		enable_not_inverted = false; | ||||
| 		if (lut == 0xE4) { | ||||
| 			data_name = pins[1]; | ||||
| 			enable_name = pins[0];	 | ||||
| 			enable_name = pins[0]; | ||||
| 			return true; | ||||
| 		} | ||||
| 		if (lut == 0xE2) { | ||||
| 			data_name = pins[0]; | ||||
| 			enable_name = pins[1];	 | ||||
| 			enable_name = pins[1]; | ||||
| 			return true; | ||||
| 		} | ||||
| 		// this does not match an enable flop.
 | ||||
|  | @ -553,11 +553,11 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module) | |||
| 			new_cell->setPort("\\" + port.first, sig); | ||||
| 		} | ||||
| 
 | ||||
| 		stats[stringf("  mapped %%d %s cells to %s cells.\n", cell_type, new_cell->type)]++; | ||||
| 		stats[stringf("%s cells to %s cells", cell_type, new_cell->type)]++; | ||||
| 	} | ||||
| 
 | ||||
| 	for (auto &stat: stats) | ||||
| 		log(stat.first.c_str(), stat.second); | ||||
| 		log("  mapped %d %s.\n", stat.second, stat.first); | ||||
| } | ||||
| 
 | ||||
| struct DfflibmapPass : public Pass { | ||||
|  |  | |||
|  | @ -620,7 +620,7 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: | |||
| 
 | ||||
| 	for (int i = 0; i < 64; i++) | ||||
| 	{ | ||||
| 		log(verbose ? "\n" : "."); | ||||
| 		log("%s", verbose ? "\n" : "."); | ||||
| 		gold_ce.clear(); | ||||
| 		gate_ce.clear(); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue