2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include "kernel/yosys.h"
21 #include "libs/sha1/sha1.h"
22 #include "backends/ilang/ilang_backend.h"
24 #if !defined(_WIN32) || defined(__MINGW32__)
25 # include <sys/time.h>
41 std::vector
<FILE*> log_files
;
42 std::vector
<std::ostream
*> log_streams
;
43 std::map
<std::string
, std::set
<std::string
>> log_hdump
;
44 std::vector
<std::regex
> log_warn_regexes
, log_nowarn_regexes
;
45 bool log_hdump_all
= false;
46 FILE *log_errfile
= NULL
;
47 SHA1
*log_hasher
= NULL
;
49 bool log_time
= false;
50 bool log_error_stderr
= false;
51 bool log_cmd_error_throw
= false;
52 bool log_quiet_warnings
= false;
53 int log_verbose_level
;
54 string log_last_error
;
55 void (*log_error_atexit
)() = NULL
;
57 vector
<int> header_count
;
58 pool
<RTLIL::IdString
> log_id_cache
;
59 vector
<shared_str
> string_buf
;
60 int string_buf_index
= -1;
62 static struct timeval initial_tv
= { 0, 0 };
63 static bool next_print_log
= false;
64 static int log_newline_count
= 0;
66 #if defined(_WIN32) && !defined(__MINGW32__)
67 // this will get time information and return it in timeval, simulating gettimeofday()
68 int gettimeofday(struct timeval
*tv
, struct timezone
*tz
)
70 LARGE_INTEGER counter
;
73 QueryPerformanceFrequency(&freq
);
74 QueryPerformanceCounter(&counter
);
76 counter
.QuadPart
*= 1000000;
77 counter
.QuadPart
/= freq
.QuadPart
;
79 tv
->tv_sec
= long(counter
.QuadPart
/ 1000000);
80 tv
->tv_usec
= counter
.QuadPart
% 1000000;
86 void logv(const char *format
, va_list ap
)
88 while (format
[0] == '\n' && format
[1] != 0) {
93 std::string str
= vstringf(format
, ap
);
98 size_t nnl_pos
= str
.find_last_not_of('\n');
99 if (nnl_pos
== std::string::npos
)
100 log_newline_count
+= GetSize(str
);
102 log_newline_count
= GetSize(str
) - nnl_pos
- 1;
105 log_hasher
->update(str
);
109 std::string time_str
;
111 if (next_print_log
|| initial_tv
.tv_sec
== 0) {
112 next_print_log
= false;
114 gettimeofday(&tv
, NULL
);
115 if (initial_tv
.tv_sec
== 0)
117 if (tv
.tv_usec
< initial_tv
.tv_usec
) {
119 tv
.tv_usec
+= 1000000;
121 tv
.tv_sec
-= initial_tv
.tv_sec
;
122 tv
.tv_usec
-= initial_tv
.tv_usec
;
123 time_str
+= stringf("[%05d.%06d] ", int(tv
.tv_sec
), int(tv
.tv_usec
));
126 if (format
[0] && format
[strlen(format
)-1] == '\n')
127 next_print_log
= true;
129 for (auto f
: log_files
)
130 fputs(time_str
.c_str(), f
);
132 for (auto f
: log_streams
)
136 for (auto f
: log_files
)
137 fputs(str
.c_str(), f
);
139 for (auto f
: log_streams
)
142 static std::string linebuffer
;
143 static bool log_warn_regex_recusion_guard
= false;
145 if (!log_warn_regex_recusion_guard
)
147 log_warn_regex_recusion_guard
= true;
149 if (log_warn_regexes
.empty())
157 if (!linebuffer
.empty() && linebuffer
.back() == '\n') {
158 for (auto &re
: log_warn_regexes
)
159 if (std::regex_search(linebuffer
, re
))
160 log_warning("Found log message matching -W regex:\n%s", str
.c_str());
165 log_warn_regex_recusion_guard
= false;
169 void logv_header(RTLIL::Design
*design
, const char *format
, va_list ap
)
171 bool pop_errfile
= false;
174 if (header_count
.size() > 0)
175 header_count
.back()++;
177 if (int(header_count
.size()) <= log_verbose_level
&& log_errfile
!= NULL
) {
178 log_files
.push_back(log_errfile
);
182 std::string header_id
;
184 for (int c
: header_count
)
185 header_id
+= stringf("%s%d", header_id
.empty() ? "" : ".", c
);
187 log("%s. ", header_id
.c_str());
192 log_hdump
[header_id
].insert("yosys_dump_" + header_id
+ ".il");
194 if (log_hdump
.count(header_id
) && design
!= nullptr)
195 for (auto &filename
: log_hdump
.at(header_id
)) {
196 log("Dumping current design to '%s'.\n", filename
.c_str());
197 Pass::call(design
, {"dump", "-o", filename
});
201 log_files
.pop_back();
204 void logv_warning(const char *format
, va_list ap
)
206 std::string message
= vstringf(format
, ap
);
207 bool suppressed
= false;
209 for (auto &re
: log_nowarn_regexes
)
210 if (std::regex_search(message
, re
))
215 log("Suppressed warning: %s", message
.c_str());
219 if (log_errfile
!= NULL
&& !log_quiet_warnings
)
220 log_files
.push_back(log_errfile
);
222 log("Warning: %s", message
.c_str());
225 if (log_errfile
!= NULL
&& !log_quiet_warnings
)
226 log_files
.pop_back();
230 void logv_warning_noprefix(const char *format
, va_list ap
)
232 std::string message
= vstringf(format
, ap
);
233 bool suppressed
= false;
235 for (auto &re
: log_nowarn_regexes
)
236 if (std::regex_search(message
, re
))
241 log("%s", message
.c_str());
245 if (log_errfile
!= NULL
&& !log_quiet_warnings
)
246 log_files
.push_back(log_errfile
);
248 log("%s", message
.c_str());
251 if (log_errfile
!= NULL
&& !log_quiet_warnings
)
252 log_files
.pop_back();
256 void logv_error(const char *format
, va_list ap
)
259 auto backup_log_files
= log_files
;
262 if (log_errfile
!= NULL
)
263 log_files
.push_back(log_errfile
);
265 if (log_error_stderr
)
266 for (auto &f
: log_files
)
270 log_last_error
= vstringf(format
, ap
);
271 log("ERROR: %s", log_last_error
.c_str());
274 if (log_error_atexit
)
278 log_files
= backup_log_files
;
280 #elif defined(_MSC_VER)
287 void log(const char *format
, ...)
290 va_start(ap
, format
);
295 void log_header(RTLIL::Design
*design
, const char *format
, ...)
298 va_start(ap
, format
);
299 logv_header(design
, format
, ap
);
303 void log_warning(const char *format
, ...)
306 va_start(ap
, format
);
307 logv_warning(format
, ap
);
311 void log_warning_noprefix(const char *format
, ...)
314 va_start(ap
, format
);
315 logv_warning_noprefix(format
, ap
);
319 void log_error(const char *format
, ...)
322 va_start(ap
, format
);
323 logv_error(format
, ap
);
326 void log_cmd_error(const char *format
, ...)
329 va_start(ap
, format
);
331 if (log_cmd_error_throw
) {
332 log_last_error
= vstringf(format
, ap
);
333 log("ERROR: %s", log_last_error
.c_str());
335 throw log_cmd_error_exception();
338 logv_error(format
, ap
);
343 if (log_newline_count
< 2) log("\n");
344 if (log_newline_count
< 2) log("\n");
349 header_count
.push_back(0);
354 header_count
.pop_back();
355 log_id_cache
.clear();
357 string_buf_index
= -1;
361 #if defined(__linux__) && defined(YOSYS_ENABLE_PLUGINS)
362 void log_backtrace(const char *prefix
, int levels
)
364 if (levels
<= 0) return;
369 if ((p
= __builtin_extract_return_addr(__builtin_return_address(0))) && dladdr(p
, &dli
)) {
370 log("%sframe #1: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
372 log("%sframe #1: ---\n", prefix
);
376 if (levels
<= 1) return;
379 log("%sframe #2: [build Yosys with ENABLE_DEBUG for deeper backtraces]\n", prefix
);
381 if ((p
= __builtin_extract_return_addr(__builtin_return_address(1))) && dladdr(p
, &dli
)) {
382 log("%sframe #2: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
384 log("%sframe #2: ---\n", prefix
);
388 if (levels
<= 2) return;
390 if ((p
= __builtin_extract_return_addr(__builtin_return_address(2))) && dladdr(p
, &dli
)) {
391 log("%sframe #3: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
393 log("%sframe #3: ---\n", prefix
);
397 if (levels
<= 3) return;
399 if ((p
= __builtin_extract_return_addr(__builtin_return_address(3))) && dladdr(p
, &dli
)) {
400 log("%sframe #4: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
402 log("%sframe #4: ---\n", prefix
);
406 if (levels
<= 4) return;
408 if ((p
= __builtin_extract_return_addr(__builtin_return_address(4))) && dladdr(p
, &dli
)) {
409 log("%sframe #5: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
411 log("%sframe #5: ---\n", prefix
);
415 if (levels
<= 5) return;
417 if ((p
= __builtin_extract_return_addr(__builtin_return_address(5))) && dladdr(p
, &dli
)) {
418 log("%sframe #6: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
420 log("%sframe #6: ---\n", prefix
);
424 if (levels
<= 6) return;
426 if ((p
= __builtin_extract_return_addr(__builtin_return_address(6))) && dladdr(p
, &dli
)) {
427 log("%sframe #7: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
429 log("%sframe #7: ---\n", prefix
);
433 if (levels
<= 7) return;
435 if ((p
= __builtin_extract_return_addr(__builtin_return_address(7))) && dladdr(p
, &dli
)) {
436 log("%sframe #8: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
438 log("%sframe #8: ---\n", prefix
);
442 if (levels
<= 8) return;
444 if ((p
= __builtin_extract_return_addr(__builtin_return_address(8))) && dladdr(p
, &dli
)) {
445 log("%sframe #9: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
447 log("%sframe #9: ---\n", prefix
);
451 if (levels
<= 9) return;
455 void log_backtrace(const char*, int) { }
458 void log_reset_stack()
460 while (header_count
.size() > 1)
461 header_count
.pop_back();
462 log_id_cache
.clear();
464 string_buf_index
= -1;
470 for (auto f
: log_files
)
473 for (auto f
: log_streams
)
477 void log_dump_val_worker(RTLIL::IdString v
) {
478 log("%s", log_id(v
));
481 void log_dump_val_worker(RTLIL::SigSpec v
) {
482 log("%s", log_signal(v
));
485 const char *log_signal(const RTLIL::SigSpec
&sig
, bool autoint
)
487 std::stringstream buf
;
488 ILANG_BACKEND::dump_sigspec(buf
, sig
, autoint
);
490 if (string_buf
.size() < 100) {
491 string_buf
.push_back(buf
.str());
492 return string_buf
.back().c_str();
494 if (++string_buf_index
== 100)
495 string_buf_index
= 0;
496 string_buf
[string_buf_index
] = buf
.str();
497 return string_buf
[string_buf_index
].c_str();
501 const char *log_const(const RTLIL::Const
&value
, bool autoint
)
503 if ((value
.flags
& RTLIL::CONST_FLAG_STRING
) == 0)
504 return log_signal(value
, autoint
);
506 std::string str
= "\"" + value
.decode_string() + "\"";
508 if (string_buf
.size() < 100) {
509 string_buf
.push_back(str
);
510 return string_buf
.back().c_str();
512 if (++string_buf_index
== 100)
513 string_buf_index
= 0;
514 string_buf
[string_buf_index
] = str
;
515 return string_buf
[string_buf_index
].c_str();
519 const char *log_id(RTLIL::IdString str
)
521 log_id_cache
.insert(str
);
522 const char *p
= str
.c_str();
525 if (p
[1] == '$' || p
[1] == '\\' || p
[1] == 0)
527 if (p
[1] >= '0' && p
[1] <= '9')
532 void log_module(RTLIL::Module
*module
, std::string indent
)
534 std::stringstream buf
;
535 ILANG_BACKEND::dump_module(buf
, indent
, module
, module
->design
, false);
536 log("%s", buf
.str().c_str());
539 void log_cell(RTLIL::Cell
*cell
, std::string indent
)
541 std::stringstream buf
;
542 ILANG_BACKEND::dump_cell(buf
, indent
, cell
);
543 log("%s", buf
.str().c_str());
546 void log_wire(RTLIL::Wire
*wire
, std::string indent
)
548 std::stringstream buf
;
549 ILANG_BACKEND::dump_wire(buf
, indent
, wire
);
550 log("%s", buf
.str().c_str());
553 // ---------------------------------------------------
554 // This is the magic behind the code coverage counters
555 // ---------------------------------------------------
556 #if defined(YOSYS_ENABLE_COVER) && defined(__linux__)
558 dict
<std::string
, std::pair
<std::string
, int>> extra_coverage_data
;
560 void cover_extra(std::string parent
, std::string id
, bool increment
) {
561 if (extra_coverage_data
.count(id
) == 0) {
562 for (CoverData
*p
= __start_yosys_cover_list
; p
!= __stop_yosys_cover_list
; p
++)
564 extra_coverage_data
[id
].first
= stringf("%s:%d:%s", p
->file
, p
->line
, p
->func
);
565 log_assert(extra_coverage_data
.count(id
));
568 extra_coverage_data
[id
].second
++;
571 dict
<std::string
, std::pair
<std::string
, int>> get_coverage_data()
573 dict
<std::string
, std::pair
<std::string
, int>> coverage_data
;
575 for (auto &it
: pass_register
) {
576 std::string key
= stringf("passes.%s", it
.first
.c_str());
577 coverage_data
[key
].first
= stringf("%s:%d:%s", __FILE__
, __LINE__
, __FUNCTION__
);
578 coverage_data
[key
].second
+= it
.second
->call_counter
;
581 for (auto &it
: extra_coverage_data
) {
582 if (coverage_data
.count(it
.first
))
583 log_warning("found duplicate coverage id \"%s\".\n", it
.first
.c_str());
584 coverage_data
[it
.first
].first
= it
.second
.first
;
585 coverage_data
[it
.first
].second
+= it
.second
.second
;
588 for (CoverData
*p
= __start_yosys_cover_list
; p
!= __stop_yosys_cover_list
; p
++) {
589 if (coverage_data
.count(p
->id
))
590 log_warning("found duplicate coverage id \"%s\".\n", p
->id
);
591 coverage_data
[p
->id
].first
= stringf("%s:%d:%s", p
->file
, p
->line
, p
->func
);
592 coverage_data
[p
->id
].second
+= p
->counter
;
595 for (auto &it
: coverage_data
)
596 if (!it
.second
.first
.compare(0, strlen(YOSYS_SRC
"/"), YOSYS_SRC
"/"))
597 it
.second
.first
= it
.second
.first
.substr(strlen(YOSYS_SRC
"/"));
599 return coverage_data
;