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