mirror of https://github.com/YosysHQ/yosys.git
log: convert all to sinks
This commit is contained in:
parent
bd5c524dc6
commit
cbbd8c0dfd
|
|
@ -321,8 +321,11 @@ AstNode::~AstNode()
|
||||||
void AstNode::dumpAst(FILE *f, std::string indent) const
|
void AstNode::dumpAst(FILE *f, std::string indent) const
|
||||||
{
|
{
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
for (auto f : log_files)
|
for (auto &s : log_sinks) {
|
||||||
dumpAst(f, indent);
|
f = s->file_handle();
|
||||||
|
if (f)
|
||||||
|
dumpAst(f, indent);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -425,8 +428,11 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
|
||||||
std::vector<AstNode*> rem_children1, rem_children2;
|
std::vector<AstNode*> rem_children1, rem_children2;
|
||||||
|
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
for (auto f : log_files)
|
for (auto &s : log_sinks) {
|
||||||
dumpVlog(f, indent);
|
f = s->file_handle();
|
||||||
|
if (f)
|
||||||
|
dumpVlog(f, indent);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1386,8 +1386,11 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
|
||||||
// everything should have been handled above -> print error if not.
|
// everything should have been handled above -> print error if not.
|
||||||
default:
|
default:
|
||||||
AstNode *current_scope_ast = current_ast_mod == nullptr ? current_ast : current_ast_mod;
|
AstNode *current_scope_ast = current_ast_mod == nullptr ? current_ast : current_ast_mod;
|
||||||
for (auto f : log_files)
|
for (auto &s : log_sinks) {
|
||||||
current_scope_ast->dumpAst(f, "verilog-ast> ");
|
auto f = s->file_handle();
|
||||||
|
if (f)
|
||||||
|
current_scope_ast->dumpAst(f, "verilog-ast> ");
|
||||||
|
}
|
||||||
input_error("Don't know how to detect sign and width for %s node!\n", type2str(type));
|
input_error("Don't know how to detect sign and width for %s node!\n", type2str(type));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -2362,8 +2365,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
||||||
|
|
||||||
// everything should have been handled above -> print error if not.
|
// everything should have been handled above -> print error if not.
|
||||||
default:
|
default:
|
||||||
for (auto f : log_files)
|
for (auto &s : log_sinks) {
|
||||||
current_ast_mod->dumpAst(f, "verilog-ast> ");
|
auto f = s->file_handle();
|
||||||
|
if (f)
|
||||||
|
current_ast_mod->dumpAst(f, "verilog-ast> ");
|
||||||
|
}
|
||||||
input_error("Don't know how to generate RTLIL code for %s node!\n", type2str(type));
|
input_error("Don't know how to generate RTLIL code for %s node!\n", type2str(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2791,8 +2791,10 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
|
||||||
auto buf = children[0]->clone();
|
auto buf = children[0]->clone();
|
||||||
while (buf->simplify(true, stage, width_hint, sign_hint)) { }
|
while (buf->simplify(true, stage, width_hint, sign_hint)) { }
|
||||||
if (buf->type != AST_CONSTANT) {
|
if (buf->type != AST_CONSTANT) {
|
||||||
// for (auto f : log_files)
|
// for (auto &s : log_sinks) {
|
||||||
// dumpAst(f, "verilog-ast> ");
|
// auto f = s->file_handle();
|
||||||
|
// if (f)
|
||||||
|
// dumpAst(f, "verilog-ast> ");
|
||||||
input_error("Condition for generate if is not constant!\n");
|
input_error("Condition for generate if is not constant!\n");
|
||||||
}
|
}
|
||||||
if (buf->asBool() != 0) {
|
if (buf->asBool() != 0) {
|
||||||
|
|
@ -2828,8 +2830,10 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
|
||||||
auto buf = children[0]->clone();
|
auto buf = children[0]->clone();
|
||||||
while (buf->simplify(true, stage, width_hint, sign_hint)) { }
|
while (buf->simplify(true, stage, width_hint, sign_hint)) { }
|
||||||
if (buf->type != AST_CONSTANT) {
|
if (buf->type != AST_CONSTANT) {
|
||||||
// for (auto f : log_files)
|
// for (auto &s : log_sinks) {
|
||||||
// dumpAst(f, "verilog-ast> ");
|
// auto f = s->file_handle();
|
||||||
|
// if (f)
|
||||||
|
// dumpAst(f, "verilog-ast> ");
|
||||||
input_error("Condition for generate case is not constant!\n");
|
input_error("Condition for generate case is not constant!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2862,8 +2866,10 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
|
||||||
buf->set_in_param_flag(true);
|
buf->set_in_param_flag(true);
|
||||||
while (buf->simplify(true, stage, width_hint, sign_hint)) { }
|
while (buf->simplify(true, stage, width_hint, sign_hint)) { }
|
||||||
if (buf->type != AST_CONSTANT) {
|
if (buf->type != AST_CONSTANT) {
|
||||||
// for (auto f : log_files)
|
// for (auto &s : log_sinks) {
|
||||||
// dumpAst(f, "verilog-ast> ");
|
// auto f = s->file_handle();
|
||||||
|
// if (f)
|
||||||
|
// dumpAst(f, "verilog-ast> ");
|
||||||
input_error("Expression in generate case is not constant!\n");
|
input_error("Expression in generate case is not constant!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,7 @@ int main(int argc, char **argv)
|
||||||
bool run_tcl_shell = false;
|
bool run_tcl_shell = false;
|
||||||
bool mode_v = false;
|
bool mode_v = false;
|
||||||
bool mode_q = false;
|
bool mode_q = false;
|
||||||
|
FILE *log_errfile = NULL;
|
||||||
|
|
||||||
cxxopts::Options options(argv[0], "Yosys Open SYnthesis Suite");
|
cxxopts::Options options(argv[0], "Yosys Open SYnthesis Suite");
|
||||||
options.set_width(SIZE_MAX);
|
options.set_width(SIZE_MAX);
|
||||||
|
|
@ -314,12 +315,11 @@ int main(int argc, char **argv)
|
||||||
for (const auto& key : {"l", "L"}) {
|
for (const auto& key : {"l", "L"}) {
|
||||||
if (result.count(key)) {
|
if (result.count(key)) {
|
||||||
for (const auto& filename : result[key].as<std::vector<std::string>>()) {
|
for (const auto& filename : result[key].as<std::vector<std::string>>()) {
|
||||||
if (FILE* f = fopen(filename.c_str(), "wt")) {
|
try {
|
||||||
log_files.push_back(f);
|
log_sinks.push_back(std::make_unique<FileLogSink>(filename, key[0] == 'L', false));
|
||||||
if (key[0] == 'L') setvbuf(f, NULL, _IOLBF, 0);
|
} catch (const std::runtime_error &e) {
|
||||||
} else {
|
std::cerr << e.what();
|
||||||
std::cerr << "Can't open log file `" << filename << "' for writing!\n";
|
exit(1);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -405,8 +405,9 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (log_errfile == NULL) {
|
if (log_errfile == NULL) {
|
||||||
log_files.push_back(stdout);
|
log_sinks.push_back(std::make_unique<ConsoleLogSink>());
|
||||||
log_error_stderr = true;
|
} else {
|
||||||
|
log_sinks.push_back(std::make_unique<StderrLogSink>());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (print_banner)
|
if (print_banner)
|
||||||
|
|
@ -609,7 +610,7 @@ int main(int argc, char **argv)
|
||||||
log_spacer();
|
log_spacer();
|
||||||
|
|
||||||
if (mode_v && !mode_q)
|
if (mode_v && !mode_q)
|
||||||
log_files.push_back(stderr);
|
log_stderr_force = true;
|
||||||
|
|
||||||
if (log_warnings_count)
|
if (log_warnings_count)
|
||||||
log("Warnings: %d unique messages, %d total\n", GetSize(log_warnings), log_warnings_count);
|
log("Warnings: %d unique messages, %d total\n", GetSize(log_warnings), log_warnings_count);
|
||||||
|
|
|
||||||
187
kernel/log.cc
187
kernel/log.cc
|
|
@ -38,9 +38,8 @@
|
||||||
|
|
||||||
YOSYS_NAMESPACE_BEGIN
|
YOSYS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
std::vector<FILE*> log_files;
|
std::vector<std::unique_ptr<LogSink>> log_sinks;
|
||||||
std::vector<std::ostream*> log_streams;
|
|
||||||
std::vector<std::string> log_scratchpads;
|
|
||||||
std::map<std::string, std::set<std::string>> log_hdump;
|
std::map<std::string, std::set<std::string>> log_hdump;
|
||||||
std::vector<std::regex> log_warn_regexes, log_nowarn_regexes, log_werror_regexes;
|
std::vector<std::regex> log_warn_regexes, log_nowarn_regexes, log_werror_regexes;
|
||||||
dict<std::string, LogExpectedItem> log_expect_log, log_expect_warning, log_expect_error;
|
dict<std::string, LogExpectedItem> log_expect_log, log_expect_warning, log_expect_error;
|
||||||
|
|
@ -50,7 +49,6 @@ int log_warnings_count = 0;
|
||||||
int log_warnings_count_noexpect = 0;
|
int log_warnings_count_noexpect = 0;
|
||||||
bool log_expect_no_warnings = false;
|
bool log_expect_no_warnings = false;
|
||||||
bool log_hdump_all = false;
|
bool log_hdump_all = false;
|
||||||
FILE *log_errfile = NULL;
|
|
||||||
SHA1 *log_hasher = NULL;
|
SHA1 *log_hasher = NULL;
|
||||||
|
|
||||||
bool log_time = false;
|
bool log_time = false;
|
||||||
|
|
@ -58,7 +56,7 @@ bool log_error_stderr = false;
|
||||||
bool log_cmd_error_throw = false;
|
bool log_cmd_error_throw = false;
|
||||||
bool log_quiet_warnings = false;
|
bool log_quiet_warnings = false;
|
||||||
int log_verbose_level;
|
int log_verbose_level;
|
||||||
string log_last_error;
|
|
||||||
void (*log_error_atexit)() = NULL;
|
void (*log_error_atexit)() = NULL;
|
||||||
void (*log_verific_callback)(int msg_type, const char *message_id, const char* file_path, unsigned int left_line, unsigned int left_col, unsigned int right_line, unsigned int right_col, const char *msg) = NULL;
|
void (*log_verific_callback)(int msg_type, const char *message_id, const char* file_path, unsigned int left_line, unsigned int left_col, unsigned int right_line, unsigned int right_col, const char *msg) = NULL;
|
||||||
|
|
||||||
|
|
@ -66,6 +64,8 @@ int log_make_debug = 0;
|
||||||
int log_force_debug = 0;
|
int log_force_debug = 0;
|
||||||
int log_debug_suppressed = 0;
|
int log_debug_suppressed = 0;
|
||||||
|
|
||||||
|
bool log_stderr_force = false;
|
||||||
|
|
||||||
vector<int> header_count;
|
vector<int> header_count;
|
||||||
vector<char*> log_id_cache;
|
vector<char*> log_id_cache;
|
||||||
|
|
||||||
|
|
@ -73,14 +73,83 @@ static std::optional<std::chrono::steady_clock::time_point> initial_time;
|
||||||
static bool next_print_log = false;
|
static bool next_print_log = false;
|
||||||
static int log_newline_count = 0;
|
static int log_newline_count = 0;
|
||||||
|
|
||||||
static void log_id_cache_clear()
|
FileLogSink::FileLogSink(const std::string &filename, bool line_buffered, bool append)
|
||||||
|
: file(fopen(filename.c_str(), append ? "at" : "wt"))
|
||||||
{
|
{
|
||||||
for (auto p : log_id_cache)
|
if (!file)
|
||||||
free(p);
|
throw std::runtime_error("Can't open log file `" + filename + "' for writing!\n");
|
||||||
log_id_cache.clear();
|
|
||||||
|
if (line_buffered)
|
||||||
|
setvbuf(file, nullptr, _IOLBF, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void log_default_callback(LogMessage msg)
|
FileLogSink::~FileLogSink()
|
||||||
|
{
|
||||||
|
flush();
|
||||||
|
if (file)
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileLogSink::log(const LogMessage &msg)
|
||||||
|
{
|
||||||
|
fputs(msg.legacy_msg.c_str(), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileLogSink::flush()
|
||||||
|
{
|
||||||
|
fflush(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleLogSink::log(const LogMessage &msg)
|
||||||
|
{
|
||||||
|
FILE *file = msg.severity == LogSeverity::LOG_ERROR ? stderr : stdout;
|
||||||
|
fputs(msg.legacy_msg.c_str(), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleLogSink::flush()
|
||||||
|
{
|
||||||
|
fflush(stdout);
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StderrLogSink::should_log(const LogMessage &msg) const
|
||||||
|
{
|
||||||
|
return msg.severity == LogSeverity::LOG_ERROR ||
|
||||||
|
(msg.severity == LogSeverity::LOG_WARNING && !log_quiet_warnings) ||
|
||||||
|
/* (msg.severity == LogSeverity::LOG_HEADER && int(header_count.size()) <= log_verbose_level) || */
|
||||||
|
log_stderr_force;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StderrLogSink::log(const LogMessage &msg)
|
||||||
|
{
|
||||||
|
fputs(msg.legacy_msg.c_str(), stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StderrLogSink::flush()
|
||||||
|
{
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScratchPadLogSink::ScratchPadLogSink(std::string scratchpad)
|
||||||
|
: scratchpad(std::move(scratchpad))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScratchPadLogSink::log(const LogMessage &msg)
|
||||||
|
{
|
||||||
|
RTLIL::Design *design = yosys_get_design();
|
||||||
|
if (!design)
|
||||||
|
return;
|
||||||
|
|
||||||
|
design->scratchpad[scratchpad].append(msg.legacy_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogMessage::LogMessage(LogSeverity severity, std::string_view prefix, std::string_view format, std::string_view message) :
|
||||||
|
severity(severity),
|
||||||
|
prefix(prefix),
|
||||||
|
format(format),
|
||||||
|
message(message),
|
||||||
|
timestamp(std::chrono::steady_clock::now())
|
||||||
{
|
{
|
||||||
std::string time_str;
|
std::string time_str;
|
||||||
if (log_time)
|
if (log_time)
|
||||||
|
|
@ -94,31 +163,24 @@ static void log_default_callback(LogMessage msg)
|
||||||
time_str += stringf("[%05d.%06d] ", int(us.count() / 1'000'000),int(us.count() % 1'000'000));
|
time_str += stringf("[%05d.%06d] ", int(us.count() / 1'000'000),int(us.count() % 1'000'000));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!msg.format.empty() && msg.format.back() == '\n')
|
if (!format.empty() && format.back() == '\n')
|
||||||
next_print_log = true;
|
next_print_log = true;
|
||||||
|
|
||||||
// Special case to detect newlines in Python log output, since
|
// Special case to detect newlines in Python log output, since
|
||||||
// the binding always calls `log("%s", payload)` and the newline
|
// the binding always calls `log("%s", payload)` and the newline
|
||||||
// is then in the first formatted argument
|
// is then in the first formatted argument
|
||||||
if (msg.format == "%s" && msg.message.back() == '\n')
|
if (format == "%s" && message.back() == '\n')
|
||||||
next_print_log = true;
|
next_print_log = true;
|
||||||
}
|
}
|
||||||
|
legacy_msg = stringf("%s%s%s", time_str, prefix, message);
|
||||||
std::string str = stringf("%s%s%s", time_str, msg.prefix, msg.message);
|
|
||||||
for (auto f : log_files) {
|
|
||||||
fputs(str.c_str(), f);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto f : log_streams)
|
|
||||||
*f << str;
|
|
||||||
|
|
||||||
RTLIL::Design *design = yosys_get_design();
|
|
||||||
if (design != nullptr)
|
|
||||||
for (auto &scratchpad : log_scratchpads)
|
|
||||||
design->scratchpad[scratchpad].append(str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void (*log_callback)(LogMessage msg) = log_default_callback;
|
static void log_id_cache_clear()
|
||||||
|
{
|
||||||
|
for (auto p : log_id_cache)
|
||||||
|
free(p);
|
||||||
|
log_id_cache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
static void logv_string(std::string_view prefix, std::string_view format, std::string str_in, LogSeverity severity) {
|
static void logv_string(std::string_view prefix, std::string_view format, std::string str_in, LogSeverity severity) {
|
||||||
size_t remove_leading = 0;
|
size_t remove_leading = 0;
|
||||||
|
|
@ -145,7 +207,11 @@ static void logv_string(std::string_view prefix, std::string_view format, std::s
|
||||||
if (log_hasher)
|
if (log_hasher)
|
||||||
log_hasher->update(str);
|
log_hasher->update(str);
|
||||||
|
|
||||||
log_callback(LogMessage(severity, prefix, format, str_in));
|
auto msg = LogMessage(severity, prefix, format, str_in);
|
||||||
|
for (auto &sink : log_sinks) {
|
||||||
|
if (sink->should_log(msg))
|
||||||
|
sink->log(msg);
|
||||||
|
}
|
||||||
|
|
||||||
static std::string linebuffer;
|
static std::string linebuffer;
|
||||||
static bool log_warn_regex_recusion_guard = false;
|
static bool log_warn_regex_recusion_guard = false;
|
||||||
|
|
@ -192,15 +258,12 @@ void log_formatted_header(RTLIL::Design *design, std::string_view format, std::s
|
||||||
{
|
{
|
||||||
log_assert(!Multithreading::active());
|
log_assert(!Multithreading::active());
|
||||||
|
|
||||||
bool pop_errfile = false;
|
|
||||||
|
|
||||||
log_spacer();
|
log_spacer();
|
||||||
if (header_count.size() > 0)
|
if (header_count.size() > 0)
|
||||||
header_count.back()++;
|
header_count.back()++;
|
||||||
|
|
||||||
if (int(header_count.size()) <= log_verbose_level && log_errfile != NULL) {
|
if (int(header_count.size()) <= log_verbose_level) {
|
||||||
log_files.push_back(log_errfile);
|
log_stderr_force = true;
|
||||||
pop_errfile = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string header_id;
|
std::string header_id;
|
||||||
|
|
@ -224,9 +287,7 @@ void log_formatted_header(RTLIL::Design *design, std::string_view format, std::s
|
||||||
if (yosys_xtrace)
|
if (yosys_xtrace)
|
||||||
log("#X# -- end of dump --\n");
|
log("#X# -- end of dump --\n");
|
||||||
}
|
}
|
||||||
|
log_stderr_force = false;
|
||||||
if (pop_errfile)
|
|
||||||
log_files.pop_back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_formatted_warning(std::string_view prefix, std::string message)
|
void log_formatted_warning(std::string_view prefix, std::string message)
|
||||||
|
|
@ -267,20 +328,13 @@ void log_formatted_warning(std::string_view prefix, std::string message)
|
||||||
|
|
||||||
if (log_warnings.count(message))
|
if (log_warnings.count(message))
|
||||||
{
|
{
|
||||||
log_formatted_string(prefix, "%s", message, LogSeverity::LOG_WARNING);
|
log_formatted_string(prefix, "%s", message, LogSeverity::LOG_INFO);
|
||||||
log_flush();
|
log_flush();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (log_errfile != NULL && !log_quiet_warnings)
|
|
||||||
log_files.push_back(log_errfile);
|
|
||||||
|
|
||||||
log_formatted_string(prefix, "%s", message, LogSeverity::LOG_WARNING);
|
log_formatted_string(prefix, "%s", message, LogSeverity::LOG_WARNING);
|
||||||
log_flush();
|
log_flush();
|
||||||
|
|
||||||
if (log_errfile != NULL && !log_quiet_warnings)
|
|
||||||
log_files.pop_back();
|
|
||||||
|
|
||||||
log_warnings.insert(message);
|
log_warnings.insert(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -311,36 +365,23 @@ void log_suppressed() {
|
||||||
}
|
}
|
||||||
|
|
||||||
[[noreturn]]
|
[[noreturn]]
|
||||||
static void log_error_with_prefix(std::string_view prefix, std::string str)
|
static void log_error_with_prefix(std::string_view prefix, std::string message)
|
||||||
{
|
{
|
||||||
int bak_log_make_debug = log_make_debug;
|
int bak_log_make_debug = log_make_debug;
|
||||||
log_make_debug = 0;
|
log_make_debug = 0;
|
||||||
log_suppressed();
|
log_suppressed();
|
||||||
|
|
||||||
if (log_errfile != NULL)
|
log_formatted_string(prefix, "%s", message, LogSeverity::LOG_ERROR);
|
||||||
log_files.push_back(log_errfile);
|
|
||||||
|
|
||||||
if (log_error_stderr) {
|
|
||||||
log_flush(); // Make sure we flush stdout before replacing it with stderr
|
|
||||||
for (auto &f : log_files)
|
|
||||||
if (f == stdout)
|
|
||||||
f = stderr;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_last_error = std::move(str);
|
|
||||||
std::string message(prefix);
|
|
||||||
message += log_last_error;
|
|
||||||
log_formatted_string(prefix, "%s", log_last_error, LogSeverity::LOG_ERROR);
|
|
||||||
log_flush();
|
log_flush();
|
||||||
|
|
||||||
log_make_debug = bak_log_make_debug;
|
log_make_debug = bak_log_make_debug;
|
||||||
|
|
||||||
for (auto &[_, item] : log_expect_error)
|
for (auto &[_, item] : log_expect_error)
|
||||||
if (std::regex_search(log_last_error, item.pattern))
|
if (std::regex_search(message, item.pattern))
|
||||||
item.current_count++;
|
item.current_count++;
|
||||||
|
|
||||||
for (auto &[_, item] : log_expect_prefix_error)
|
for (auto &[_, item] : log_expect_prefix_error)
|
||||||
if (std::regex_search(message, item.pattern))
|
if (std::regex_search(string(prefix) + message, item.pattern))
|
||||||
item.current_count++;
|
item.current_count++;
|
||||||
|
|
||||||
log_check_expected();
|
log_check_expected();
|
||||||
|
|
@ -394,29 +435,16 @@ void log_yosys_abort_message(std::string_view file, int line, std::string_view f
|
||||||
log_error("Abort in %s:%d (%s): %s\n", file, line, func, message);
|
log_error("Abort in %s:%d (%s): %s\n", file, line, func, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_formatted_cmd_error(std::string str)
|
void log_formatted_cmd_error(std::string message)
|
||||||
{
|
{
|
||||||
if (log_cmd_error_throw) {
|
if (log_cmd_error_throw) {
|
||||||
log_last_error = str;
|
log_formatted_string("ERROR: ", "%s", message, LogSeverity::LOG_ERROR);
|
||||||
|
|
||||||
// Make sure the error message gets through any selective silencing
|
|
||||||
// of log output
|
|
||||||
bool pop_errfile = false;
|
|
||||||
if (log_errfile != NULL) {
|
|
||||||
log_files.push_back(log_errfile);
|
|
||||||
pop_errfile = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_formatted_string("ERROR: ", "%s", log_last_error, LogSeverity::LOG_ERROR);
|
|
||||||
log_flush();
|
log_flush();
|
||||||
|
|
||||||
if (pop_errfile)
|
|
||||||
log_files.pop_back();
|
|
||||||
|
|
||||||
throw log_cmd_error_exception();
|
throw log_cmd_error_exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
log_formatted_error(str);
|
log_formatted_error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_spacer()
|
void log_spacer()
|
||||||
|
|
@ -544,11 +572,8 @@ void log_reset_stack()
|
||||||
|
|
||||||
void log_flush()
|
void log_flush()
|
||||||
{
|
{
|
||||||
for (auto f : log_files)
|
for (auto &sink : log_sinks)
|
||||||
fflush(f);
|
sink->flush();
|
||||||
|
|
||||||
for (auto f : log_streams)
|
|
||||||
f->flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_dump_val_worker(RTLIL::IdString v) {
|
void log_dump_val_worker(RTLIL::IdString v) {
|
||||||
|
|
|
||||||
81
kernel/log.h
81
kernel/log.h
|
|
@ -96,22 +96,83 @@ enum LogSeverity {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LogMessage {
|
struct LogMessage {
|
||||||
LogMessage(LogSeverity severity, std::string_view prefix, std::string_view format, std::string_view message) :
|
LogMessage(LogSeverity severity, std::string_view prefix, std::string_view format, std::string_view message);
|
||||||
severity(severity),
|
|
||||||
prefix(prefix),
|
|
||||||
format(format),
|
|
||||||
message(message),
|
|
||||||
timestamp(std::chrono::steady_clock::now()) {}
|
|
||||||
LogSeverity severity;
|
LogSeverity severity;
|
||||||
std::string prefix;
|
std::string prefix;
|
||||||
std::string format;
|
std::string format;
|
||||||
std::string message;
|
std::string message;
|
||||||
std::chrono::steady_clock::time_point timestamp;
|
std::chrono::steady_clock::time_point timestamp;
|
||||||
|
//TODO: remove
|
||||||
|
std::string legacy_msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::vector<FILE*> log_files;
|
class LogSink
|
||||||
extern std::vector<std::ostream*> log_streams;
|
{
|
||||||
extern std::vector<std::string> log_scratchpads;
|
public:
|
||||||
|
virtual ~LogSink() = default;
|
||||||
|
|
||||||
|
virtual bool should_log(const LogMessage &) const { return true; }
|
||||||
|
virtual void log(const LogMessage &msg) = 0;
|
||||||
|
virtual void flush() {}
|
||||||
|
// TODO: Remove when AST/read_verilog removed
|
||||||
|
virtual FILE *file_handle() { return nullptr; }
|
||||||
|
};
|
||||||
|
|
||||||
|
extern std::vector<std::unique_ptr<LogSink>> log_sinks;
|
||||||
|
|
||||||
|
class LogSinkRef : public LogSink
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit LogSinkRef(LogSink *sink) : sink(sink) {}
|
||||||
|
bool should_log(const LogMessage &msg) const override { return sink->should_log(msg); }
|
||||||
|
void log(const LogMessage &msg) override { sink->log(msg); }
|
||||||
|
void flush() override { sink->flush(); }
|
||||||
|
FILE *file_handle() override { return sink->file_handle(); }
|
||||||
|
private:
|
||||||
|
LogSink *sink;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FileLogSink : public LogSink
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit FileLogSink(const std::string &filename, bool line_buffered, bool append);
|
||||||
|
~FileLogSink() override;
|
||||||
|
void log(const LogMessage &msg) override;
|
||||||
|
void flush() override;
|
||||||
|
FILE *file_handle() override { return file; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
FILE *file;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConsoleLogSink : public LogSink
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void log(const LogMessage &msg) override;
|
||||||
|
void flush() override;
|
||||||
|
FILE *file_handle() override { return stdout; };
|
||||||
|
};
|
||||||
|
|
||||||
|
class StderrLogSink : public LogSink
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool should_log(const LogMessage &msg) const override;
|
||||||
|
void log(const LogMessage &msg) override;
|
||||||
|
void flush() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScratchPadLogSink : public LogSink
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ScratchPadLogSink(std::string scratchpad);
|
||||||
|
void log(const LogMessage &msg) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string scratchpad;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern bool log_stderr_force;
|
||||||
|
|
||||||
extern std::map<std::string, std::set<std::string>> log_hdump;
|
extern std::map<std::string, std::set<std::string>> log_hdump;
|
||||||
extern std::vector<std::regex> log_warn_regexes, log_nowarn_regexes, log_werror_regexes;
|
extern std::vector<std::regex> log_warn_regexes, log_nowarn_regexes, log_werror_regexes;
|
||||||
extern std::set<std::string> log_warnings, log_experimentals, log_experimentals_ignored;
|
extern std::set<std::string> log_warnings, log_experimentals, log_experimentals_ignored;
|
||||||
|
|
@ -119,7 +180,6 @@ extern int log_warnings_count;
|
||||||
extern int log_warnings_count_noexpect;
|
extern int log_warnings_count_noexpect;
|
||||||
extern bool log_expect_no_warnings;
|
extern bool log_expect_no_warnings;
|
||||||
extern bool log_hdump_all;
|
extern bool log_hdump_all;
|
||||||
extern FILE *log_errfile;
|
|
||||||
extern SHA1 *log_hasher;
|
extern SHA1 *log_hasher;
|
||||||
|
|
||||||
extern bool log_time;
|
extern bool log_time;
|
||||||
|
|
@ -127,7 +187,6 @@ extern bool log_error_stderr;
|
||||||
extern bool log_cmd_error_throw;
|
extern bool log_cmd_error_throw;
|
||||||
extern bool log_quiet_warnings;
|
extern bool log_quiet_warnings;
|
||||||
extern int log_verbose_level;
|
extern int log_verbose_level;
|
||||||
extern string log_last_error;
|
|
||||||
extern void (*log_error_atexit)();
|
extern void (*log_error_atexit)();
|
||||||
|
|
||||||
extern int log_make_debug;
|
extern int log_make_debug;
|
||||||
|
|
|
||||||
|
|
@ -753,6 +753,16 @@ static struct CellHelpMessages {
|
||||||
SimHelper get(string name) { return cell_help[get_cell_name(name)]; }
|
SimHelper get(string name) { return cell_help[get_cell_name(name)]; }
|
||||||
} cell_help_messages;
|
} cell_help_messages;
|
||||||
|
|
||||||
|
class HelpMsgLogSink : public LogSink
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit HelpMsgLogSink(std::ostream *buf) : buf(buf) {}
|
||||||
|
void log(const LogMessage &msg) override { *buf << msg.message; }
|
||||||
|
void flush() override { buf->flush(); }
|
||||||
|
private:
|
||||||
|
std::ostream *buf;
|
||||||
|
};
|
||||||
|
|
||||||
struct HelpPass : public Pass {
|
struct HelpPass : public Pass {
|
||||||
HelpPass() : Pass("help", "display help messages") { }
|
HelpPass() : Pass("help", "display help messages") { }
|
||||||
void help() override
|
void help() override
|
||||||
|
|
@ -805,9 +815,9 @@ struct HelpPass : public Pass {
|
||||||
|
|
||||||
// dump command help
|
// dump command help
|
||||||
std::ostringstream buf;
|
std::ostringstream buf;
|
||||||
log_streams.push_back(&buf);
|
log_sinks.push_back(std::make_unique<HelpMsgLogSink>(&buf));
|
||||||
pass->help();
|
pass->help();
|
||||||
log_streams.pop_back();
|
log_sinks.pop_back();
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << buf.str();
|
ss << buf.str();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -286,11 +286,7 @@ void yosys_shutdown()
|
||||||
yosys_design = NULL;
|
yosys_design = NULL;
|
||||||
RTLIL::OwningIdString::collect_garbage();
|
RTLIL::OwningIdString::collect_garbage();
|
||||||
|
|
||||||
for (auto f : log_files)
|
log_sinks.clear();
|
||||||
if (f != stderr)
|
|
||||||
fclose(f);
|
|
||||||
log_errfile = NULL;
|
|
||||||
log_files.clear();
|
|
||||||
|
|
||||||
#ifdef YOSYS_ENABLE_TCL
|
#ifdef YOSYS_ENABLE_TCL
|
||||||
if (yosys_tcl_interp != NULL) {
|
if (yosys_tcl_interp != NULL) {
|
||||||
|
|
|
||||||
|
|
@ -58,41 +58,35 @@ struct TeePass : public Pass {
|
||||||
}
|
}
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
{
|
{
|
||||||
std::vector<FILE*> backup_log_files, files_to_close;
|
|
||||||
std::vector<std::ostream*> backup_log_streams;
|
|
||||||
std::vector<std::string> backup_log_scratchpads;
|
|
||||||
int backup_log_verbose_level = log_verbose_level;
|
int backup_log_verbose_level = log_verbose_level;
|
||||||
backup_log_streams = log_streams;
|
auto backup_log_sinks = std::move(log_sinks);
|
||||||
backup_log_files = log_files;
|
log_sinks.reserve(backup_log_sinks.size());
|
||||||
backup_log_scratchpads = log_scratchpads;
|
for (const auto &sink : backup_log_sinks)
|
||||||
|
log_sinks.push_back(std::make_unique<LogSinkRef>(sink.get()));
|
||||||
|
|
||||||
size_t argidx;
|
size_t argidx;
|
||||||
for (argidx = 1; argidx < args.size(); argidx++)
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
{
|
{
|
||||||
if (args[argidx] == "-q" && files_to_close.empty()) {
|
if (args[argidx] == "-q") {
|
||||||
log_files.clear();
|
log_sinks.clear();
|
||||||
log_streams.clear();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((args[argidx] == "-o" || args[argidx] == "-a") && argidx+1 < args.size()) {
|
if ((args[argidx] == "-o" || args[argidx] == "-a") && argidx+1 < args.size()) {
|
||||||
const char *open_mode = args[argidx] == "-o" ? "w" : "a+";
|
bool is_append = args[argidx] == "-a";
|
||||||
auto path = args[++argidx];
|
auto path = args[++argidx];
|
||||||
rewrite_filename(path);
|
rewrite_filename(path);
|
||||||
FILE *f = fopen(path.c_str(), open_mode);
|
try {
|
||||||
yosys_input_files.insert(args[argidx]);
|
log_sinks.push_back(std::make_unique<FileLogSink>(path.c_str(), false, is_append));
|
||||||
if (f == NULL) {
|
} catch (const std::runtime_error &e) {
|
||||||
for (auto cf : files_to_close)
|
std::cerr << e.what();
|
||||||
fclose(cf);
|
exit(1);
|
||||||
log_cmd_error("Can't create file %s.\n", args[argidx]);
|
|
||||||
}
|
}
|
||||||
log_files.push_back(f);
|
|
||||||
files_to_close.push_back(f);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (args[argidx] == "-s" && argidx+1 < args.size()) {
|
if (args[argidx] == "-s" && argidx+1 < args.size()) {
|
||||||
auto name = args[++argidx];
|
auto name = args[++argidx];
|
||||||
design->scratchpad[name] = "";
|
design->scratchpad[name] = "";
|
||||||
log_scratchpads.push_back(name);
|
log_sinks.push_back(std::make_unique<ScratchPadLogSink>(name));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (GetSize(args[argidx]) >= 2 && (args[argidx][0] == '-' || args[argidx][0] == '+') && args[argidx][1] >= '0' && args[argidx][1] <= '9') {
|
if (GetSize(args[argidx]) >= 2 && (args[argidx][0] == '-' || args[argidx][0] == '+') && args[argidx][1] >= '0' && args[argidx][1] <= '9') {
|
||||||
|
|
@ -106,21 +100,14 @@ struct TeePass : public Pass {
|
||||||
std::vector<std::string> new_args(args.begin() + argidx, args.end());
|
std::vector<std::string> new_args(args.begin() + argidx, args.end());
|
||||||
Pass::call(design, new_args);
|
Pass::call(design, new_args);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
for (auto cf : files_to_close)
|
log_sinks.clear();
|
||||||
fclose(cf);
|
log_sinks = std::move(backup_log_sinks);
|
||||||
log_files = backup_log_files;
|
|
||||||
log_streams = backup_log_streams;
|
|
||||||
log_scratchpads = backup_log_scratchpads;
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto cf : files_to_close)
|
|
||||||
fclose(cf);
|
|
||||||
|
|
||||||
log_verbose_level = backup_log_verbose_level;
|
log_verbose_level = backup_log_verbose_level;
|
||||||
log_files = backup_log_files;
|
log_sinks.clear();
|
||||||
log_streams = backup_log_streams;
|
log_sinks = std::move(backup_log_sinks);
|
||||||
log_scratchpads = backup_log_scratchpads;
|
|
||||||
}
|
}
|
||||||
} TeePass;
|
} TeePass;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ YOSYS_NAMESPACE_BEGIN
|
||||||
TEST(CellTypesTest, basic)
|
TEST(CellTypesTest, basic)
|
||||||
{
|
{
|
||||||
yosys_setup();
|
yosys_setup();
|
||||||
log_files.push_back(stdout);
|
if (log_sinks.empty()) log_sinks.push_back(std::make_unique<ConsoleLogSink>());
|
||||||
CellTypes older;
|
CellTypes older;
|
||||||
NewCellTypes newer;
|
NewCellTypes newer;
|
||||||
older.setup(nullptr);
|
older.setup(nullptr);
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ TEST(ModIndexSwapTest, has)
|
||||||
|
|
||||||
TEST(ModIndexDeleteTest, has)
|
TEST(ModIndexDeleteTest, has)
|
||||||
{
|
{
|
||||||
if (log_files.empty()) log_files.emplace_back(stdout);
|
if (log_sinks.empty()) log_sinks.push_back(std::make_unique<ConsoleLogSink>());
|
||||||
Design* d = new Design;
|
Design* d = new Design;
|
||||||
Module* m = d->addModule("$m");
|
Module* m = d->addModule("$m");
|
||||||
Wire* w = m->addWire("$w");
|
Wire* w = m->addWire("$w");
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace RTLIL {
|
||||||
class KernelRtlilTest : public testing::Test {
|
class KernelRtlilTest : public testing::Test {
|
||||||
protected:
|
protected:
|
||||||
KernelRtlilTest() {
|
KernelRtlilTest() {
|
||||||
if (log_files.empty()) log_files.emplace_back(stdout);
|
if (log_sinks.empty()) log_sinks.push_back(std::make_unique<ConsoleLogSink>());
|
||||||
}
|
}
|
||||||
virtual void SetUp() override {
|
virtual void SetUp() override {
|
||||||
IdString::ensure_prepopulated();
|
IdString::ensure_prepopulated();
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,7 @@ YOSYS_NAMESPACE_BEGIN
|
||||||
class ThreadingTest : public testing::Test {
|
class ThreadingTest : public testing::Test {
|
||||||
protected:
|
protected:
|
||||||
ThreadingTest() {
|
ThreadingTest() {
|
||||||
if (log_files.empty())
|
if (log_sinks.empty()) log_sinks.push_back(std::make_unique<ConsoleLogSink>());
|
||||||
log_files.emplace_back(stdout);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace RTLIL {
|
||||||
class TechmapLibparseTest : public testing::Test {
|
class TechmapLibparseTest : public testing::Test {
|
||||||
protected:
|
protected:
|
||||||
TechmapLibparseTest() {
|
TechmapLibparseTest() {
|
||||||
if (log_files.empty()) log_files.emplace_back(stdout);
|
if (log_sinks.empty()) log_sinks.push_back(std::make_unique<ConsoleLogSink>());
|
||||||
}
|
}
|
||||||
void checkAll(std::initializer_list<std::string> expressions, std::string expected) {
|
void checkAll(std::initializer_list<std::string> expressions, std::string expected) {
|
||||||
for (const auto& e : expressions) {
|
for (const auto& e : expressions) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue