scc  2022.4.0
SystemC components library
gz_writer.hh
1 /*
2  * gz_writer.hh
3  *
4  * Created on: Dec 15, 2021
5  * Author: eyckj
6  */
7 
8 #ifndef _SCC_TRACE_GZ_WRITER_HH_
9 #define _SCC_TRACE_GZ_WRITER_HH_
10 
11 #include <boost/lockfree/spsc_queue.hpp>
12 #include <boost/atomic.hpp>
13 #include <thread>
14 #include <mutex>
15 #include <deque>
16 #include <string>
17 #include <cstring>
18 #include <zlib.h>
19 #include <chrono>
20 
21 namespace scc {
22 namespace trace {
23 
24 class gz_writer {
25  static const size_t queue_size=16*1024;
26  std::deque<char*> pool;
27  std::deque<char*> write_queue;
28  boost::atomic<bool> done {false};
29  std::condition_variable cond;
30 
31  std::deque<char*> pool_buffer;
32  gzFile vcd_out{nullptr};
33  std::thread logger;
34 
35  inline void write_out(){
36  while (!write_queue.empty()) {
37  auto* value = write_queue.front();
38  write_queue.pop_front();
39  auto len = strlen(value);
40  if(len) gzwrite(vcd_out, value, strlen(value));
41  memset(value, 0, buffer_size);
42  pool.push_back(value);
43  }
44  }
45  void log(void){
46  auto const timeout = std::chrono::milliseconds(1);
47  while (!done) {
48  std::unique_lock<std::mutex> lock(writer_mtx);
49  auto now = std::chrono::system_clock::now();
50  cond.wait_until(lock, now+timeout, [this]() -> bool { return done || ! write_queue.empty(); });
51  write_out();
52  }
53  write_out();
54  }
55 
56  void enlarge_pool() {
57  auto buffer_pool = new char[queue_size * buffer_size];
58  for (auto i = 0u; i < queue_size; ++i) {
59  memset(buffer_pool + i * buffer_size, 0, buffer_size);
60  pool.push_back(buffer_pool + i * buffer_size);
61  }
62  pool_buffer.push_back(buffer_pool);
63  }
64 
65 public:
66  std::mutex writer_mtx;
67  using lock_type=std::unique_lock<std::mutex>;
68  static const size_t buffer_size=512;
69  gz_writer(std::string const& filename) {
70  vcd_out = gzopen(filename.c_str(), "w3");
71  logger=std::thread([this](){log();});
72  enlarge_pool();
73  }
74 
75  ~gz_writer(){
76  done=true;
77  {
78  lock_type lock(writer_mtx);
79  write("");
80  }
81  logger.join();
82  gzclose(vcd_out);
83  char* value;
84  pool.clear();
85  for(auto b:pool_buffer) delete b;
86  }
87 
88  inline void write_single(std::string const& msg){
89  lock_type lock(writer_mtx);
90  if(pool.empty()) enlarge_pool();
91  auto value = pool.front();
92  pool.pop_front();
93  strncpy(value, msg.c_str(), std::min(buffer_size-1, msg.length()));
94  write_queue.push_back(value);
95  }
96  inline void write(std::string const& msg){
97  if(pool.empty()) enlarge_pool();
98 // auto value = pool.front();
99 // pool.pop_front();
100 // strncpy(value, msg.c_str(), std::min(buffer_size-1, msg.length()));
101 // write_queue.push_back(value);
102  }
103  inline void write(char const* msg, size_t size){
104  if(pool.empty()) enlarge_pool();
105 // auto value = pool.front();
106 // pool.pop_front();
107 // strncpy(value, msg, std::min(buffer_size-1, size));
108 // write_queue.push_back(value);
109  }
110 };
111 }
112 }
113 #endif /* _SCC_TRACE_GZ_WRITER_HH_ */
SCC SystemC utilities.
log
enum defining the log levels
Definition: report.h:84