circular_log.h 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. #ifndef __CIRCULAR_LOG_H
  2. #define __CIRCULAR_LOG_H
  3. #include "fixed_types.h"
  4. #include "lock.h"
  5. #include "timer.h"
  6. // Fast circular log to trace generic events
  7. //
  8. // Events consist of a printf-style format string and up to 6 arguments.
  9. // To reduce overhead, printf itself is not called during logging;
  10. // instead the format string and all arguments are stored in a circular buffer.
  11. // On simulation end or abort, the last 1M entries are formatted and written to sim.clog.
  12. // This means the arguments must remain valid until simulation end, which is fine
  13. // for integers and const char*. Pointers into dynamically allocated memory will be
  14. // invalid by the time they are dereferenced and should thus not be used.
  15. class CircularLog
  16. {
  17. public:
  18. static void init(String filename);
  19. static void enableCallbacks();
  20. static void fini();
  21. static void dump();
  22. static CircularLog *g_singleton;
  23. CircularLog(String filename);
  24. ~CircularLog();
  25. void insert(const char* type, const char* msg, ...) __attribute__ ((format(printf, 3, 4)));
  26. UInt64 getTime() const { return rdtsc() - m_time_zero; }
  27. private:
  28. typedef struct {
  29. UInt64 time;
  30. const char* type;
  31. const char* msg;
  32. UInt64 args[6];
  33. } event_t;
  34. static SInt64 hook_sigusr1(UInt64, UInt64) { dump(); return 0; }
  35. void writeLog();
  36. void writeEntry(FILE *fp, int idx);
  37. static const UInt64 BUFFER_SIZE = 1024*1024;
  38. const String m_filename;
  39. event_t* const m_buffer;
  40. Lock m_lock;
  41. UInt64 m_eventnum;
  42. UInt64 m_time_zero;
  43. };
  44. #define CLOG(type, ...) do { \
  45. if (CircularLog::g_singleton) \
  46. CircularLog::g_singleton->insert(type, __VA_ARGS__); \
  47. } while(0)
  48. #endif // __CIRCULAR_LOG_H