X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=kernel%2Flog.cc;h=a21ba480a6d6313fe6c0d1c743aba664d9d09770;hb=f975cf39cbedbca0482109b7aa625570a3857ee6;hp=a7820950c9dcdc3f4ea45b240931af5c3d7b02b6;hpb=1e201a9b010badec6f220476dc6bc03a06de5b69;p=yosys.git diff --git a/kernel/log.cc b/kernel/log.cc index a7820950c..a21ba480a 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -41,9 +41,12 @@ YOSYS_NAMESPACE_BEGIN std::vector log_files; std::vector log_streams; std::map> log_hdump; -std::vector log_warn_regexes, log_nowarn_regexes, log_werror_regexes; -std::set log_warnings; +std::vector log_warn_regexes, log_nowarn_regexes, log_werror_regexes; +std::vector> log_expect_log, log_expect_warning, log_expect_error; +std::set log_warnings, log_experimentals, log_experimentals_ignored; int log_warnings_count = 0; +int log_warnings_count_noexpect = 0; +bool log_expect_no_warnings = false; bool log_hdump_all = false; FILE *log_errfile = NULL; SHA1 *log_hasher = NULL; @@ -61,13 +64,22 @@ int log_force_debug = 0; int log_debug_suppressed = 0; vector header_count; -pool log_id_cache; +vector log_id_cache; vector string_buf; int string_buf_index = -1; static struct timeval initial_tv = { 0, 0 }; static bool next_print_log = false; static int log_newline_count = 0; +static bool check_expected_logs = true; +static bool display_error_log_msg = true; + +static void log_id_cache_clear() +{ + for (auto p : log_id_cache) + free(p); + log_id_cache.clear(); +} #if defined(_WIN32) && !defined(__MINGW32__) // this will get time information and return it in timeval, simulating gettimeofday() @@ -155,7 +167,7 @@ void logv(const char *format, va_list ap) { log_warn_regex_recusion_guard = true; - if (log_warn_regexes.empty()) + if (log_warn_regexes.empty() && log_expect_log.empty()) { linebuffer.clear(); } @@ -165,8 +177,13 @@ void logv(const char *format, va_list ap) if (!linebuffer.empty() && linebuffer.back() == '\n') { for (auto &re : log_warn_regexes) - if (std::regex_search(linebuffer, re)) + if (YS_REGEX_NS::regex_search(linebuffer, re)) log_warning("Found log message matching -W regex:\n%s", str.c_str()); + + for (auto &item : log_expect_log) + if (YS_REGEX_NS::regex_search(linebuffer, item.first)) + item.second.current_count++; + linebuffer.clear(); } } @@ -221,7 +238,7 @@ static void logv_warning_with_prefix(const char *prefix, bool suppressed = false; for (auto &re : log_nowarn_regexes) - if (std::regex_search(message, re)) + if (YS_REGEX_NS::regex_search(message, re)) suppressed = true; if (suppressed) @@ -234,9 +251,16 @@ static void logv_warning_with_prefix(const char *prefix, log_make_debug = 0; for (auto &re : log_werror_regexes) - if (std::regex_search(message, re)) + if (YS_REGEX_NS::regex_search(message, re)) log_error("%s", message.c_str()); + bool warning_match = false; + for (auto &item : log_expect_warning) + if (YS_REGEX_NS::regex_search(message, item.first)) { + item.second.current_count++; + warning_match = true; + } + if (log_warnings.count(message)) { log("%s%s", prefix, message.c_str()); @@ -256,6 +280,8 @@ static void logv_warning_with_prefix(const char *prefix, log_warnings.insert(message); } + if (!warning_match) + log_warnings_count_noexpect++; log_warnings_count++; log_make_debug = bak_log_make_debug; } @@ -313,7 +339,8 @@ static void logv_error_with_prefix(const char *prefix, f = stderr; log_last_error = vstringf(format, ap); - log("%s%s", prefix, log_last_error.c_str()); + if (display_error_log_msg) + log("%s%s", prefix, log_last_error.c_str()); log_flush(); log_make_debug = bak_log_make_debug; @@ -321,6 +348,15 @@ static void logv_error_with_prefix(const char *prefix, if (log_error_atexit) log_error_atexit(); + for (auto &item : log_expect_error) + if (YS_REGEX_NS::regex_search(log_last_error, item.first)) + item.second.current_count++; + + if (check_expected_logs) + log_check_expected(); + + YS_DEBUGTRAP_IF_DEBUGGING; + #ifdef EMSCRIPTEN log_files = backup_log_files; throw 0; @@ -370,6 +406,19 @@ void log_warning(const char *format, ...) va_end(ap); } +void log_experimental(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + string s = vstringf(format, ap); + va_end(ap); + + if (log_experimentals_ignored.count(s) == 0 && log_experimentals.count(s) == 0) { + log_warning("Feature '%s' is experimental.\n", s.c_str()); + log_experimentals.insert(s); + } +} + void log_warning_noprefix(const char *format, ...) { va_list ap; @@ -414,7 +463,7 @@ void log_push() void log_pop() { header_count.pop_back(); - log_id_cache.clear(); + log_id_cache_clear(); string_buf.clear(); string_buf_index = -1; log_flush(); @@ -521,7 +570,7 @@ void log_reset_stack() { while (header_count.size() > 1) header_count.pop_back(); - log_id_cache.clear(); + log_id_cache_clear(); string_buf.clear(); string_buf_index = -1; log_flush(); @@ -544,6 +593,10 @@ void log_dump_val_worker(RTLIL::SigSpec v) { log("%s", log_signal(v)); } +void log_dump_val_worker(RTLIL::State v) { + log("%s", log_signal(v)); +} + const char *log_signal(const RTLIL::SigSpec &sig, bool autoint) { std::stringstream buf; @@ -580,8 +633,8 @@ const char *log_const(const RTLIL::Const &value, bool autoint) const char *log_id(RTLIL::IdString str) { - log_id_cache.insert(str); - const char *p = str.c_str(); + log_id_cache.push_back(strdup(str.c_str())); + const char *p = log_id_cache.back(); if (p[0] != '\\') return p; if (p[1] == '$' || p[1] == '\\' || p[1] == 0) @@ -612,6 +665,52 @@ void log_wire(RTLIL::Wire *wire, std::string indent) log("%s", buf.str().c_str()); } +void log_check_expected() +{ + check_expected_logs = false; + + for (auto &item : log_expect_warning) { + if (item.second.current_count == 0) { + log_warn_regexes.clear(); + log_error("Expected warning pattern '%s' not found !\n", item.second.pattern.c_str()); + } + if (item.second.current_count != item.second.expected_count) { + log_warn_regexes.clear(); + log_error("Expected warning pattern '%s' found %d time(s), instead of %d time(s) !\n", + item.second.pattern.c_str(), item.second.current_count, item.second.expected_count); + } + } + + for (auto &item : log_expect_log) { + if (item.second.current_count == 0) { + log_warn_regexes.clear(); + log_error("Expected log pattern '%s' not found !\n", item.second.pattern.c_str()); + } + if (item.second.current_count != item.second.expected_count) { + log_warn_regexes.clear(); + log_error("Expected log pattern '%s' found %d time(s), instead of %d time(s) !\n", + item.second.pattern.c_str(), item.second.current_count, item.second.expected_count); + } + } + + for (auto &item : log_expect_error) + if (item.second.current_count == item.second.expected_count) { + log_warn_regexes.clear(); + log("Expected error pattern '%s' found !!!\n", item.second.pattern.c_str()); + #ifdef EMSCRIPTEN + throw 0; + #elif defined(_MSC_VER) + _exit(0); + #else + _Exit(0); + #endif + } else { + display_error_log_msg = false; + log_warn_regexes.clear(); + log_error("Expected error pattern '%s' not found !\n", item.second.pattern.c_str()); + } +} + // --------------------------------------------------- // This is the magic behind the code coverage counters // ---------------------------------------------------