Fixed various VS warnings
[yosys.git] / kernel / log.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
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.
9 *
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.
17 *
18 */
19
20 #include "kernel/yosys.h"
21 #include "libs/sha1/sha1.h"
22 #include "backends/ilang/ilang_backend.h"
23
24 #if !defined(_WIN32) || defined(__MINGW32__)
25 # include <sys/time.h>
26 #endif
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdarg.h>
32 #include <vector>
33 #include <list>
34
35 YOSYS_NAMESPACE_BEGIN
36
37 std::vector<FILE*> log_files;
38 std::vector<std::ostream*> log_streams;
39 FILE *log_errfile = NULL;
40 SHA1 *log_hasher = NULL;
41
42 bool log_time = false;
43 bool log_cmd_error_throw = false;
44 int log_verbose_level;
45
46 std::vector<int> header_count;
47 std::list<std::string> string_buf;
48 int string_buf_size = 0;
49
50 static struct timeval initial_tv = { 0, 0 };
51 static bool next_print_log = false;
52 static int log_newline_count = 0;
53
54 #if defined(_WIN32) && !defined(__MINGW32__)
55 // this will get time information and return it in timeval, simulating gettimeofday()
56 int gettimeofday(struct timeval *tv, struct timezone *tz)
57 {
58 LARGE_INTEGER counter;
59 LARGE_INTEGER freq;
60
61 QueryPerformanceFrequency(&freq);
62 QueryPerformanceCounter(&counter);
63
64 counter.QuadPart *= 1000000;
65 counter.QuadPart /= freq.QuadPart;
66
67 tv->tv_sec = long(counter.QuadPart / 1000000);
68 tv->tv_usec = counter.QuadPart % 1000000;
69
70 return 0;
71 }
72 #endif
73
74 void logv(const char *format, va_list ap)
75 {
76 while (format[0] == '\n' && format[1] != 0) {
77 log("\n");
78 format++;
79 }
80
81 std::string str = vstringf(format, ap);
82
83 if (str.empty())
84 return;
85
86 size_t nnl_pos = str.find_last_not_of('\n');
87 if (nnl_pos == std::string::npos)
88 log_newline_count += GetSize(str);
89 else
90 log_newline_count = GetSize(str) - nnl_pos - 1;
91
92 if (log_hasher)
93 log_hasher->update(str);
94
95 if (log_time)
96 {
97 std::string time_str;
98
99 if (next_print_log || initial_tv.tv_sec == 0) {
100 next_print_log = false;
101 struct timeval tv;
102 gettimeofday(&tv, NULL);
103 if (initial_tv.tv_sec == 0)
104 initial_tv = tv;
105 if (tv.tv_usec < initial_tv.tv_usec) {
106 tv.tv_sec--;
107 tv.tv_usec += 1000000;
108 }
109 tv.tv_sec -= initial_tv.tv_sec;
110 tv.tv_usec -= initial_tv.tv_usec;
111 time_str += stringf("[%05d.%06d] ", int(tv.tv_sec), int(tv.tv_usec));
112 }
113
114 if (format[0] && format[strlen(format)-1] == '\n')
115 next_print_log = true;
116
117 for (auto f : log_files)
118 fputs(time_str.c_str(), f);
119
120 for (auto f : log_streams)
121 *f << time_str;
122 }
123
124 for (auto f : log_files)
125 fputs(str.c_str(), f);
126
127 for (auto f : log_streams)
128 *f << str;
129 }
130
131 void logv_header(const char *format, va_list ap)
132 {
133 bool pop_errfile = false;
134
135 log_spacer();
136 if (header_count.size() > 0)
137 header_count.back()++;
138
139 if (int(header_count.size()) <= log_verbose_level && log_errfile != NULL) {
140 log_files.push_back(log_errfile);
141 pop_errfile = true;
142 }
143
144 for (int c : header_count)
145 log("%d.", c);
146 log(" ");
147 logv(format, ap);
148 log_flush();
149
150 if (pop_errfile)
151 log_files.pop_back();
152 }
153
154 void logv_error(const char *format, va_list ap)
155 {
156 if (log_errfile != NULL)
157 log_files.push_back(log_errfile);
158
159 log("ERROR: ");
160 logv(format, ap);
161 log_flush();
162 exit(1);
163 }
164
165 void log(const char *format, ...)
166 {
167 va_list ap;
168 va_start(ap, format);
169 logv(format, ap);
170 va_end(ap);
171 }
172
173 void log_header(const char *format, ...)
174 {
175 va_list ap;
176 va_start(ap, format);
177 logv_header(format, ap);
178 va_end(ap);
179 }
180
181 void log_error(const char *format, ...)
182 {
183 va_list ap;
184 va_start(ap, format);
185 logv_error(format, ap);
186 }
187
188 void log_cmd_error(const char *format, ...)
189 {
190 va_list ap;
191 va_start(ap, format);
192
193 if (log_cmd_error_throw) {
194 log("ERROR: ");
195 logv(format, ap);
196 log_flush();
197 throw log_cmd_error_expection();
198 }
199
200 logv_error(format, ap);
201 }
202
203 void log_spacer()
204 {
205 while (log_newline_count < 2)
206 log("\n");
207 }
208
209 void log_push()
210 {
211 header_count.push_back(0);
212 }
213
214 void log_pop()
215 {
216 header_count.pop_back();
217 string_buf.clear();
218 string_buf_size = 0;
219 log_flush();
220 }
221
222 void log_reset_stack()
223 {
224 while (header_count.size() > 1)
225 header_count.pop_back();
226 string_buf.clear();
227 string_buf_size = 0;
228 log_flush();
229 }
230
231 void log_flush()
232 {
233 for (auto f : log_files)
234 fflush(f);
235
236 for (auto f : log_streams)
237 f->flush();
238 }
239
240 void log_dump_val_worker(RTLIL::SigSpec v) {
241 log("%s", log_signal(v));
242 }
243
244 const char *log_signal(const RTLIL::SigSpec &sig, bool autoint)
245 {
246 std::stringstream buf;
247 ILANG_BACKEND::dump_sigspec(buf, sig, autoint);
248
249 if (string_buf_size < 100)
250 string_buf_size++;
251 else
252 string_buf.pop_front();
253 string_buf.push_back(buf.str());
254
255 return string_buf.back().c_str();
256 }
257
258 const char *log_id(RTLIL::IdString str)
259 {
260 const char *p = str.c_str();
261 log_assert(RTLIL::IdString::global_refcount_storage_[str.index_] > 1);
262 if (p[0] == '\\' && p[1] != '$' && p[1] != 0)
263 return p+1;
264 return p;
265 }
266
267 void log_cell(RTLIL::Cell *cell, std::string indent)
268 {
269 std::stringstream buf;
270 ILANG_BACKEND::dump_cell(buf, indent, cell);
271 log("%s", buf.str().c_str());
272 }
273
274 // ---------------------------------------------------
275 // This is the magic behind the code coverage counters
276 // ---------------------------------------------------
277 #ifdef COVER_ACTIVE
278
279 std::map<std::string, std::pair<std::string, int>> extra_coverage_data;
280
281 void cover_extra(std::string parent, std::string id, bool increment) {
282 if (extra_coverage_data.count(id) == 0) {
283 for (CoverData *p = __start_yosys_cover_list; p != __stop_yosys_cover_list; p++)
284 if (p->id == parent)
285 extra_coverage_data[id].first = stringf("%s:%d:%s", p->file, p->line, p->func);
286 log_assert(extra_coverage_data.count(id));
287 }
288 if (increment)
289 extra_coverage_data[id].second++;
290 }
291
292 std::map<std::string, std::pair<std::string, int>> get_coverage_data()
293 {
294 std::map<std::string, std::pair<std::string, int>> coverage_data;
295
296 for (auto &it : pass_register) {
297 std::string key = stringf("passes.%s", it.first.c_str());
298 coverage_data[key].first = stringf("%s:%d:%s", __FILE__, __LINE__, __FUNCTION__);
299 coverage_data[key].second += it.second->call_counter;
300 }
301
302 for (auto &it : extra_coverage_data) {
303 if (coverage_data.count(it.first))
304 log("WARNING: found duplicate coverage id \"%s\".\n", it.first.c_str());
305 coverage_data[it.first].first = it.second.first;
306 coverage_data[it.first].second += it.second.second;
307 }
308
309 for (CoverData *p = __start_yosys_cover_list; p != __stop_yosys_cover_list; p++) {
310 if (coverage_data.count(p->id))
311 log("WARNING: found duplicate coverage id \"%s\".\n", p->id);
312 coverage_data[p->id].first = stringf("%s:%d:%s", p->file, p->line, p->func);
313 coverage_data[p->id].second += p->counter;
314 }
315
316 for (auto &it : coverage_data)
317 if (!it.second.first.compare(0, strlen(YOSYS_SRC "/"), YOSYS_SRC "/"))
318 it.second.first = it.second.first.substr(strlen(YOSYS_SRC "/"));
319
320 return coverage_data;
321 }
322
323 #endif
324
325 YOSYS_NAMESPACE_END
326