dbc94ce8c0a82dc319dc36022fdf617365fc35f7
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 FILE *log_errfile
= NULL
;
44 SHA1
*log_hasher
= NULL
;
46 bool log_time
= false;
47 bool log_error_stderr
= false;
48 bool log_cmd_error_throw
= false;
49 bool log_quiet_warnings
= false;
50 int log_verbose_level
;
51 string log_last_error
;
53 vector
<int> header_count
;
54 pool
<RTLIL::IdString
> log_id_cache
;
55 vector
<string
> string_buf
;
56 int string_buf_index
= -1;
58 static struct timeval initial_tv
= { 0, 0 };
59 static bool next_print_log
= false;
60 static int log_newline_count
= 0;
62 #if defined(_WIN32) && !defined(__MINGW32__)
63 // this will get time information and return it in timeval, simulating gettimeofday()
64 int gettimeofday(struct timeval
*tv
, struct timezone
*tz
)
66 LARGE_INTEGER counter
;
69 QueryPerformanceFrequency(&freq
);
70 QueryPerformanceCounter(&counter
);
72 counter
.QuadPart
*= 1000000;
73 counter
.QuadPart
/= freq
.QuadPart
;
75 tv
->tv_sec
= long(counter
.QuadPart
/ 1000000);
76 tv
->tv_usec
= counter
.QuadPart
% 1000000;
82 void logv(const char *format
, va_list ap
)
84 while (format
[0] == '\n' && format
[1] != 0) {
89 std::string str
= vstringf(format
, ap
);
94 size_t nnl_pos
= str
.find_last_not_of('\n');
95 if (nnl_pos
== std::string::npos
)
96 log_newline_count
+= GetSize(str
);
98 log_newline_count
= GetSize(str
) - nnl_pos
- 1;
101 log_hasher
->update(str
);
105 std::string time_str
;
107 if (next_print_log
|| initial_tv
.tv_sec
== 0) {
108 next_print_log
= false;
110 gettimeofday(&tv
, NULL
);
111 if (initial_tv
.tv_sec
== 0)
113 if (tv
.tv_usec
< initial_tv
.tv_usec
) {
115 tv
.tv_usec
+= 1000000;
117 tv
.tv_sec
-= initial_tv
.tv_sec
;
118 tv
.tv_usec
-= initial_tv
.tv_usec
;
119 time_str
+= stringf("[%05d.%06d] ", int(tv
.tv_sec
), int(tv
.tv_usec
));
122 if (format
[0] && format
[strlen(format
)-1] == '\n')
123 next_print_log
= true;
125 for (auto f
: log_files
)
126 fputs(time_str
.c_str(), f
);
128 for (auto f
: log_streams
)
132 for (auto f
: log_files
)
133 fputs(str
.c_str(), f
);
135 for (auto f
: log_streams
)
139 void logv_header(const char *format
, va_list ap
)
141 bool pop_errfile
= false;
144 if (header_count
.size() > 0)
145 header_count
.back()++;
147 if (int(header_count
.size()) <= log_verbose_level
&& log_errfile
!= NULL
) {
148 log_files
.push_back(log_errfile
);
152 for (int c
: header_count
)
159 log_files
.pop_back();
162 void logv_warning(const char *format
, va_list ap
)
164 if (log_errfile
!= NULL
&& !log_quiet_warnings
)
165 log_files
.push_back(log_errfile
);
171 if (log_errfile
!= NULL
&& !log_quiet_warnings
)
172 log_files
.pop_back();
175 void logv_error(const char *format
, va_list ap
)
178 auto backup_log_files
= log_files
;
181 if (log_errfile
!= NULL
)
182 log_files
.push_back(log_errfile
);
184 if (log_error_stderr
)
185 for (auto &f
: log_files
)
189 log_last_error
= vstringf(format
, ap
);
190 log("ERROR: %s", log_last_error
.c_str());
194 log_files
= backup_log_files
;
201 void log(const char *format
, ...)
204 va_start(ap
, format
);
209 void log_header(const char *format
, ...)
212 va_start(ap
, format
);
213 logv_header(format
, ap
);
217 void log_warning(const char *format
, ...)
220 va_start(ap
, format
);
221 logv_warning(format
, ap
);
225 void log_error(const char *format
, ...)
228 va_start(ap
, format
);
229 logv_error(format
, ap
);
232 void log_cmd_error(const char *format
, ...)
235 va_start(ap
, format
);
237 if (log_cmd_error_throw
) {
238 log_last_error
= vstringf(format
, ap
);
239 log("ERROR: %s", log_last_error
.c_str());
241 throw log_cmd_error_exception();
244 logv_error(format
, ap
);
249 while (log_newline_count
< 2)
255 header_count
.push_back(0);
260 header_count
.pop_back();
261 log_id_cache
.clear();
263 string_buf_index
= -1;
267 #if defined(__linux__) && defined(YOSYS_ENABLE_PLUGINS)
268 void log_backtrace(const char *prefix
, int levels
)
270 if (levels
<= 0) return;
275 if ((p
= __builtin_extract_return_addr(__builtin_return_address(0))) && dladdr(p
, &dli
)) {
276 log("%sframe #1: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
278 log("%sframe #1: ---\n", prefix
);
282 if (levels
<= 1) return;
284 if ((p
= __builtin_extract_return_addr(__builtin_return_address(1))) && dladdr(p
, &dli
)) {
285 log("%sframe #2: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
287 log("%sframe #2: ---\n", prefix
);
291 if (levels
<= 2) return;
293 if ((p
= __builtin_extract_return_addr(__builtin_return_address(2))) && dladdr(p
, &dli
)) {
294 log("%sframe #3: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
296 log("%sframe #3: ---\n", prefix
);
300 if (levels
<= 3) return;
302 if ((p
= __builtin_extract_return_addr(__builtin_return_address(3))) && dladdr(p
, &dli
)) {
303 log("%sframe #4: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
305 log("%sframe #4: ---\n", prefix
);
309 if (levels
<= 4) return;
311 if ((p
= __builtin_extract_return_addr(__builtin_return_address(4))) && dladdr(p
, &dli
)) {
312 log("%sframe #5: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
314 log("%sframe #5: ---\n", prefix
);
318 if (levels
<= 5) return;
320 if ((p
= __builtin_extract_return_addr(__builtin_return_address(5))) && dladdr(p
, &dli
)) {
321 log("%sframe #6: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
323 log("%sframe #6: ---\n", prefix
);
327 if (levels
<= 6) return;
329 if ((p
= __builtin_extract_return_addr(__builtin_return_address(6))) && dladdr(p
, &dli
)) {
330 log("%sframe #7: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
332 log("%sframe #7: ---\n", prefix
);
336 if (levels
<= 7) return;
338 if ((p
= __builtin_extract_return_addr(__builtin_return_address(7))) && dladdr(p
, &dli
)) {
339 log("%sframe #8: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
341 log("%sframe #8: ---\n", prefix
);
345 if (levels
<= 8) return;
347 if ((p
= __builtin_extract_return_addr(__builtin_return_address(8))) && dladdr(p
, &dli
)) {
348 log("%sframe #9: %p %s(%p) %s(%p)\n", prefix
, p
, dli
.dli_fname
, dli
.dli_fbase
, dli
.dli_sname
, dli
.dli_saddr
);
350 log("%sframe #9: ---\n", prefix
);
354 if (levels
<= 9) return;
357 void log_backtrace(const char*, int) { }
360 void log_reset_stack()
362 while (header_count
.size() > 1)
363 header_count
.pop_back();
364 log_id_cache
.clear();
366 string_buf_index
= -1;
372 for (auto f
: log_files
)
375 for (auto f
: log_streams
)
379 void log_dump_val_worker(RTLIL::IdString v
) {
380 log("%s", log_id(v
));
383 void log_dump_val_worker(RTLIL::SigSpec v
) {
384 log("%s", log_signal(v
));
387 const char *log_signal(const RTLIL::SigSpec
&sig
, bool autoint
)
389 std::stringstream buf
;
390 ILANG_BACKEND::dump_sigspec(buf
, sig
, autoint
);
392 if (string_buf
.size() < 100) {
393 string_buf
.push_back(buf
.str());
394 return string_buf
.back().c_str();
396 if (++string_buf_index
== 100)
397 string_buf_index
= 0;
398 string_buf
[string_buf_index
] = buf
.str();
399 return string_buf
[string_buf_index
].c_str();
403 const char *log_id(RTLIL::IdString str
)
405 log_id_cache
.insert(str
);
406 const char *p
= str
.c_str();
409 if (p
[1] == '$' || p
[1] == '\\' || p
[1] == 0)
411 if (p
[1] >= '0' && p
[1] <= '9')
416 void log_cell(RTLIL::Cell
*cell
, std::string indent
)
418 std::stringstream buf
;
419 ILANG_BACKEND::dump_cell(buf
, indent
, cell
);
420 log("%s", buf
.str().c_str());
423 // ---------------------------------------------------
424 // This is the magic behind the code coverage counters
425 // ---------------------------------------------------
426 #if defined(YOSYS_ENABLE_COVER) && defined(__linux__)
428 dict
<std::string
, std::pair
<std::string
, int>> extra_coverage_data
;
430 void cover_extra(std::string parent
, std::string id
, bool increment
) {
431 if (extra_coverage_data
.count(id
) == 0) {
432 for (CoverData
*p
= __start_yosys_cover_list
; p
!= __stop_yosys_cover_list
; p
++)
434 extra_coverage_data
[id
].first
= stringf("%s:%d:%s", p
->file
, p
->line
, p
->func
);
435 log_assert(extra_coverage_data
.count(id
));
438 extra_coverage_data
[id
].second
++;
441 dict
<std::string
, std::pair
<std::string
, int>> get_coverage_data()
443 dict
<std::string
, std::pair
<std::string
, int>> coverage_data
;
445 for (auto &it
: pass_register
) {
446 std::string key
= stringf("passes.%s", it
.first
.c_str());
447 coverage_data
[key
].first
= stringf("%s:%d:%s", __FILE__
, __LINE__
, __FUNCTION__
);
448 coverage_data
[key
].second
+= it
.second
->call_counter
;
451 for (auto &it
: extra_coverage_data
) {
452 if (coverage_data
.count(it
.first
))
453 log_warning("found duplicate coverage id \"%s\".\n", it
.first
.c_str());
454 coverage_data
[it
.first
].first
= it
.second
.first
;
455 coverage_data
[it
.first
].second
+= it
.second
.second
;
458 for (CoverData
*p
= __start_yosys_cover_list
; p
!= __stop_yosys_cover_list
; p
++) {
459 if (coverage_data
.count(p
->id
))
460 log_warning("found duplicate coverage id \"%s\".\n", p
->id
);
461 coverage_data
[p
->id
].first
= stringf("%s:%d:%s", p
->file
, p
->line
, p
->func
);
462 coverage_data
[p
->id
].second
+= p
->counter
;
465 for (auto &it
: coverage_data
)
466 if (!it
.second
.first
.compare(0, strlen(YOSYS_SRC
"/"), YOSYS_SRC
"/"))
467 it
.second
.first
= it
.second
.first
.substr(strlen(YOSYS_SRC
"/"));
469 return coverage_data
;