aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/log.h
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/log.h')
-rw-r--r--kernel/log.h120
1 files changed, 107 insertions, 13 deletions
diff --git a/kernel/log.h b/kernel/log.h
index c4c03352a..e2b4db87b 100644
--- a/kernel/log.h
+++ b/kernel/log.h
@@ -17,22 +17,32 @@
*
*/
+#include "kernel/yosys.h"
+
#ifndef LOG_H
#define LOG_H
-#include "kernel/rtlil.h"
-#include <stdio.h>
#include <time.h>
-#include <vector>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+YOSYS_NAMESPACE_BEGIN
+
+#define S__LINE__sub2(x) #x
+#define S__LINE__sub1(x) S__LINE__sub2(x)
+#define S__LINE__ S__LINE__sub1(__LINE__)
+
+struct log_cmd_error_expection { };
extern std::vector<FILE*> log_files;
+extern std::vector<std::ostream*> log_streams;
extern FILE *log_errfile;
+extern class SHA1 *log_hasher;
+
extern bool log_time;
extern bool log_cmd_error_throw;
extern int log_verbose_level;
-std::string stringf(const char *fmt, ...);
-
void logv(const char *format, va_list ap);
void logv_header(const char *format, va_list ap);
void logv_error(const char *format, va_list ap) __attribute__ ((noreturn));
@@ -42,6 +52,7 @@ void log_header(const char *format, ...) __attribute__ ((format (printf, 1, 2)))
void log_error(const char *format, ...) __attribute__ ((format (printf, 1, 2))) __attribute__ ((noreturn));
void log_cmd_error(const char *format, ...) __attribute__ ((format (printf, 1, 2))) __attribute__ ((noreturn));
+void log_spacer();
void log_push();
void log_pop();
@@ -49,9 +60,70 @@ void log_reset_stack();
void log_flush();
const char *log_signal(const RTLIL::SigSpec &sig, bool autoint = true);
+const char *log_id(RTLIL::IdString id);
+
+template<typename T> static inline const char *log_id(T *obj) {
+ return log_id(obj->name);
+}
+
+void log_cell(RTLIL::Cell *cell, std::string indent = "");
#define log_abort() log_error("Abort in %s:%d.\n", __FILE__, __LINE__)
#define log_assert(_assert_expr_) do { if (_assert_expr_) break; log_error("Assert `%s' failed in %s:%d.\n", #_assert_expr_, __FILE__, __LINE__); } while (0)
+#define log_ping() log("-- %s:%d %s --\n", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+
+// ---------------------------------------------------
+// This is the magic behind the code coverage counters
+// ---------------------------------------------------
+
+#if defined(__linux__) && !defined(NDEBUG)
+#define COVER_ACTIVE
+
+#define cover(_id) do { \
+ static CoverData __d __attribute__((section("yosys_cover_list"), aligned(1))) = { __FILE__, __FUNCTION__, _id, __LINE__, 0 }; \
+ __d.counter++; \
+} while (0)
+
+struct CoverData {
+ const char *file, *func, *id;
+ int line, counter;
+} __attribute__ ((packed));
+
+// this two symbols are created by the linker for the "yosys_cover_list" ELF section
+extern "C" struct CoverData __start_yosys_cover_list[];
+extern "C" struct CoverData __stop_yosys_cover_list[];
+
+extern std::map<std::string, std::pair<std::string, int>> extra_coverage_data;
+
+void cover_extra(std::string parent, std::string id, bool increment = true);
+std::map<std::string, std::pair<std::string, int>> get_coverage_data();
+
+#define cover_list(_id, ...) do { cover(_id); \
+ std::string r = cover_list_worker(_id, __VA_ARGS__); \
+ log_assert(r.empty()); \
+} while (0)
+
+static inline std::string cover_list_worker(std::string, std::string last) {
+ return last;
+}
+
+template<typename... T>
+std::string cover_list_worker(std::string prefix, std::string first, T... rest) {
+ std::string selected = cover_list_worker(prefix, rest...);
+ cover_extra(prefix, prefix + "." + first, first == selected);
+ return first == selected ? "" : selected;
+}
+
+#else
+# define cover(...) do { } while (0)
+# define cover_list(...) do { } while (0)
+#endif
+
+
+// ------------------------------------------------------------
+// everything below this line are utilities for troubleshooting
+// ------------------------------------------------------------
// simple timer for performance measurements
// toggle the '#if 1' to get a baseline for the perormance penalty added by the measurement
@@ -65,30 +137,45 @@ struct PerformanceTimer
}
static int64_t query() {
+#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
struct timespec ts;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
return int64_t(ts.tv_sec)*1000000000 + ts.tv_nsec;
+#elif defined(RUSAGE_SELF)
+ struct rusage rusage;
+ int64_t t;
+ if (getrusage(RUSAGE_SELF, &rusage) == -1) {
+ log_cmd_error("getrusage failed!\n");
+ log_abort();
+ }
+ t = 1000000000ULL * (int64_t) rusage.ru_utime.tv_sec + (int64_t) rusage.ru_utime.tv_usec * 1000ULL;
+ t += 1000000000ULL * (int64_t) rusage.ru_stime.tv_sec + (int64_t) rusage.ru_stime.tv_usec * 1000ULL;
+ return t;
+#else
+ #error Dont know how to measure per-process CPU time. Need alternative method (times()/clocks()/gettimeofday()?).
+#endif
}
void reset() {
total_ns = 0;
}
- void add() {
- total_ns += query();
+ void begin() {
+ total_ns -= query();
}
- void sub() {
- total_ns -= query();
+ void end() {
+ total_ns += query();
}
float sec() const {
return total_ns * 1e-9;
}
#else
+ static int64_t query() { return 0; }
void reset() { }
- void add() { }
- void sub() { }
+ void begin() { }
+ void end() { }
float sec() const { return 0; }
#endif
};
@@ -107,12 +194,17 @@ static inline void log_dump_val_worker(char c) { log(c >= 32 && c < 127 ? "'%c'"
static inline void log_dump_val_worker(unsigned char c) { log(c >= 32 && c < 127 ? "'%c'" : "'\\x%02x'", c); }
static inline void log_dump_val_worker(bool v) { log("%s", v ? "true" : "false"); }
static inline void log_dump_val_worker(double v) { log("%f", v); }
+static inline void log_dump_val_worker(char *v) { log("%s", v); }
static inline void log_dump_val_worker(const char *v) { log("%s", v); }
static inline void log_dump_val_worker(std::string v) { log("%s", v.c_str()); }
-static inline void log_dump_val_worker(RTLIL::SigSpec v) { log("%s", log_signal(v)); }
+static inline void log_dump_val_worker(PerformanceTimer p) { log("%f seconds", p.sec()); }
static inline void log_dump_args_worker(const char *p) { log_assert(*p == 0); }
+void log_dump_val_worker(RTLIL::SigSpec v);
-template <typename T, typename ... Args>
+template<typename T>
+static inline void log_dump_val_worker(T *ptr) { log("%p", ptr); }
+
+template<typename T, typename ... Args>
void log_dump_args_worker(const char *p, T first, Args ... args)
{
int next_p_state = 0;
@@ -152,4 +244,6 @@ void log_dump_args_worker(const char *p, T first, Args ... args)
log("\n"); \
} while (0)
+YOSYS_NAMESPACE_END
+
#endif