scc 2025.09
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 <atomic>
12#include <chrono>
13#include <cstring>
14#include <deque>
15#include <mutex>
16#include <rigtorp/SPSCQueue.h>
17#include <string>
18#include <thread>
19#include <zlib.h>
20
21namespace scc {
22namespace trace {
23
24class gz_writer {
25 static const size_t queue_size = 16 * 1024;
26 std::deque<char*> pool;
27 std::deque<char*> write_queue;
28 std::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)
41 gzwrite(vcd_out, value, strlen(value));
42 memset(value, 0, buffer_size);
43 pool.push_back(value);
44 }
45 }
46 void log(void) {
47 auto const timeout = std::chrono::milliseconds(1);
48 while(!done) {
49 std::unique_lock<std::mutex> lock(writer_mtx);
50 auto now = std::chrono::system_clock::now();
51 cond.wait_until(lock, now + timeout, [this]() -> bool { return done || !write_queue.empty(); });
52 write_out();
53 }
54 write_out();
55 }
56
57 void enlarge_pool() {
58 auto buffer_pool = new char[queue_size * buffer_size];
59 for(auto i = 0u; i < queue_size; ++i) {
60 memset(buffer_pool + i * buffer_size, 0, buffer_size);
61 pool.push_back(buffer_pool + i * buffer_size);
62 }
63 pool_buffer.push_back(buffer_pool);
64 }
65
66public:
67 std::mutex writer_mtx;
68 using lock_type = std::unique_lock<std::mutex>;
69 static const size_t buffer_size = 512;
70 gz_writer(std::string const& filename) {
71 vcd_out = gzopen(filename.c_str(), "w3");
72 logger = std::thread([this]() { log(); });
73 enlarge_pool();
74 }
75
76 ~gz_writer() {
77 done = true;
78 {
79 lock_type lock(writer_mtx);
80 write("");
81 }
82 logger.join();
83 gzclose(vcd_out);
84 char* value;
85 pool.clear();
86 for(auto b : pool_buffer)
87 delete b;
88 }
89
90 inline void write_single(std::string const& msg) {
91 lock_type lock(writer_mtx);
92 if(pool.empty())
93 enlarge_pool();
94 auto value = pool.front();
95 pool.pop_front();
96 strncpy(value, msg.c_str(), std::min(buffer_size - 1, msg.length()));
97 write_queue.push_back(value);
98 }
99 inline void write(std::string const& msg) {
100 if(pool.empty())
101 enlarge_pool();
102 // auto value = pool.front();
103 // pool.pop_front();
104 // strncpy(value, msg.c_str(), std::min(buffer_size-1, msg.length()));
105 // write_queue.push_back(value);
106 }
107 inline void write(char const* msg, size_t size) {
108 if(pool.empty())
109 enlarge_pool();
110 // auto value = pool.front();
111 // pool.pop_front();
112 // strncpy(value, msg, std::min(buffer_size-1, size));
113 // write_queue.push_back(value);
114 }
115};
116} // namespace trace
117} // namespace scc
118#endif /* _SCC_TRACE_GZ_WRITER_HH_ */
SCC SystemC tracing utilities.
Definition fst_trace.cpp:33
SCC TLM utilities.
log
enum defining the log levels
Definition report.h:86