16#ifndef _SCC_TRACE_VCD_TRACE_HH_
17#define _SCC_TRACE_VCD_TRACE_HH_
22#define FWRITE(BUF, SZ, LEN, FP) std::fwrite(BUF, SZ, LEN, FP)
25#include <fmt/format.h>
26#include <scc/utilities.h>
27#include <unordered_map>
28#include <util/ities.h>
34inline void vcdEmitValueChange(FPTR os, std::string
const& handle,
unsigned bits,
const char* val) {
35 auto buf = bits == 1 ? fmt::format(
"{}{}\n", *val, handle) : fmt::format(
"b{} {}\n", val, handle);
36 FWRITE(buf.c_str(), 1, buf.size(), os);
39inline void vcdEmitValueChange32(FPTR os, std::string
const& handle,
unsigned bits, uint32_t val) {
40 auto buf = fmt::format(
"b{:b} {}\n", val & ((1ull << bits) - 1), handle);
41 FWRITE(buf.c_str(), 1, buf.size(), os);
44inline void vcdEmitValueChange64(FPTR os, std::string
const& handle,
unsigned bits, uint64_t val) {
45 auto buf = fmt::format(
"b{:b} {}\n", val & ((1ul << std::min(63u, bits)) - 1), handle);
46 FWRITE(buf.c_str(), 1, buf.size(), os);
49template <
typename T>
inline void vcdEmitValueChangeReal(FPTR os, std::string
const& handle,
unsigned bits, T val) {
50 auto buf = fmt::format(
"r{:.16g} {}\n",
static_cast<double>(val), handle);
51 FWRITE(buf.c_str(), 1, buf.size(), os);
54inline size_t get_buffer_size(
int length) {
55 size_t sz = (
static_cast<size_t>(length) + 4096) & (~
static_cast<size_t>(4096 - 1));
56 return std::max<uint64_t>(1024UL, sz);
63 void add_trace(T*
trace) {
65 add_trace_rec(std::begin(hier), std::end(hier),
trace);
68 void print(FPTR os,
const char* scope_name =
"SystemC") {
69 auto buf = fmt::format(
"$scope module {} $end\n", scope_name);
70 FWRITE(buf.c_str(), 1, buf.size(), os);
71 for(
auto& e : m_traces)
72 print_variable_declaration_line(os, e.first.c_str(), e.second);
73 for(
auto& e : m_scopes)
74 e.second->print(os, e.first.c_str());
75 std::string end =
"$upscope $end\n";
76 FWRITE(end.c_str(), 1, end.size(), os);
80 for(
auto& s : m_scopes)
85 void add_trace_rec(std::vector<std::string>::iterator beg, std::vector<std::string>::iterator
const& end, T*
trace) {
86 if(std::distance(beg, end) == 1) {
87 m_traces.push_back(std::make_pair(*beg,
trace));
89 auto sc = m_scopes.find(*beg);
90 if(sc == std::end(m_scopes))
92 sc->second->add_trace_rec(++beg, end,
trace);
95 void print_variable_declaration_line(FPTR os,
const char* scoped_name, T* trc) {
100 ss <<
"'" << scoped_name <<
"' has 0 bits";
101 SC_REPORT_ERROR(sc_core::SC_ID_TRACING_OBJECT_IGNORED_, ss.str().c_str());
105 if(trc->type == WIRE) {
106 auto buf = fmt::format(
"$var wire {} {} {} $end\n", trc->bits, trc->trc_hndl, scoped_name);
107 FWRITE(buf.c_str(), 1, buf.size(), os);
109 auto buf = fmt::format(
"$var real {} {} {} $end\n", trc->bits, trc->trc_hndl, scoped_name);
110 FWRITE(buf.c_str(), 1, buf.size(), os);
114 auto buf = fmt::format(
"$var wire {} {} {} [{}:0] $end\n", trc->bits, trc->trc_hndl, scoped_name, trc->bits - 1);
115 FWRITE(buf.c_str(), 1, buf.size(), os);
120 std::vector<std::pair<std::string, T*>> m_traces{0};
121 std::unordered_map<std::string, vcd_scope_stack*> m_scopes{0};
125 vcd_trace(std::string
const& nm, trace_type t,
unsigned bits)
130 virtual void record(FPTR os) = 0;
132 virtual void update() = 0;
134 virtual uintptr_t get_hash() = 0;
136 virtual ~vcd_trace(){};
138 const std::string name;
139 std::string trc_hndl{};
140 bool is_alias{
false};
141 bool is_triggered{
false};
143 const trace_type type;
148inline unsigned get_bits(
const char** literals) {
150 for(nliterals = 0; literals[nliterals]; nliterals++)
152 return scc::ilog2(nliterals);
155struct vcd_trace_enum :
public vcd_trace {
156 vcd_trace_enum(
const unsigned int& object_,
const std::string& name,
const char** literals)
157 : vcd_trace(name,
trace::WIRE, get_bits(literals))
160 , literals{literals} {}
162 uintptr_t get_hash()
override {
return reinterpret_cast<uintptr_t
>(&act_val); }
164 inline bool changed() {
return !is_alias && old_val != act_val; }
166 void update()
override { old_val = act_val; }
168 void record(FPTR os)
override { vcdEmitValueChange64(os, trc_hndl, bits, old_val); }
170 unsigned int old_val;
171 const unsigned int& act_val;
172 const char** literals;
175template <
typename T,
typename OT = T>
struct vcd_trace_t :
public vcd_trace {
176 vcd_trace_t(
const T& object_,
const std::string& name)
177 : vcd_trace(name, trace::traits<T>::get_type(), trace::traits<T>::get_bits(object_))
179 , old_val(object_) {}
181 uintptr_t get_hash()
override {
return reinterpret_cast<uintptr_t
>(&act_val); }
183 inline bool changed() {
return !is_alias && old_val != act_val; }
185 void update()
override { old_val = act_val; }
187 void record(FPTR os)
override;
193template <
typename T,
typename OT>
void vcd_trace_t<T, OT>::record(FPTR os) {
195 vcdEmitValueChange32(os, trc_hndl, bits, old_val);
197 vcdEmitValueChange64(os, trc_hndl, bits, old_val);
199template <>
void vcd_trace_t<sc_core::sc_time, sc_core::sc_time>::record(FPTR os) {
200 vcdEmitValueChange64(os, trc_hndl, bits, old_val.value());
202template <>
void vcd_trace_t<bool, bool>::record(FPTR os) { vcdEmitValueChange(os, trc_hndl, 1, old_val ?
"1" :
"0"); }
203template <>
void vcd_trace_t<sc_dt::sc_bit, sc_dt::sc_bit>::record(FPTR os) { vcdEmitValueChange(os, trc_hndl, 1, old_val ?
"1" :
"0"); }
204template <>
void vcd_trace_t<sc_dt::sc_logic, sc_dt::sc_logic>::record(FPTR os) {
205 char buf[2] = {0, 0};
206 buf[0] = old_val.to_char();
207 vcdEmitValueChange(os, trc_hndl, 1, buf);
209template <>
void vcd_trace_t<float, float>::record(FPTR os) { vcdEmitValueChangeReal(os, trc_hndl, 32, old_val); }
210template <>
void vcd_trace_t<double, double>::record(FPTR os) { vcdEmitValueChangeReal(os, trc_hndl, 64, old_val); }
211template <>
void vcd_trace_t<sc_dt::sc_int_base, sc_dt::sc_int_base>::record(FPTR os) {
212 static std::vector<char> rawdata(get_buffer_size(old_val.length()));
213 char* rawdata_ptr = &rawdata[0];
214 for(
int bitindex = old_val.length() - 1; bitindex >= 0; --bitindex) {
215 *rawdata_ptr++ =
'0' + old_val[bitindex].value();
217 vcdEmitValueChange(os, trc_hndl, bits, &rawdata[0]);
219template <>
void vcd_trace_t<sc_dt::sc_uint_base, sc_dt::sc_uint_base>::record(FPTR os) {
220 static std::vector<char> rawdata(get_buffer_size(old_val.length()));
221 char* rawdata_ptr = &rawdata[0];
222 for(
int bitindex = old_val.length() - 1; bitindex >= 0; --bitindex) {
223 *rawdata_ptr++ =
'0' + old_val[bitindex].value();
225 vcdEmitValueChange(os, trc_hndl, bits, &rawdata[0]);
227template <>
void vcd_trace_t<sc_dt::sc_signed, sc_dt::sc_signed>::record(FPTR os) {
228 static std::vector<char> rawdata(get_buffer_size(old_val.length()));
229 char* rawdata_ptr = &rawdata[0];
230 bool is_started =
false;
231 int bitindex = old_val.length() - 1;
232 *rawdata_ptr++ =
'0' + old_val[bitindex--].value();
233 for(; bitindex >= 0; --bitindex) {
234 auto c =
'0' + old_val[bitindex].value();
237 else if(c ==
'1' || *(rawdata_ptr - 1) != c) {
242 vcdEmitValueChange(os, trc_hndl, bits, &rawdata[0]);
244template <>
void vcd_trace_t<sc_dt::sc_unsigned, sc_dt::sc_unsigned>::record(FPTR os) {
245 static std::vector<char> rawdata(get_buffer_size(old_val.length()));
246 char* rawdata_ptr = &rawdata[0];
247 bool is_started =
false;
248 int bitindex = old_val.length() - 1;
249 *rawdata_ptr++ =
'0' + old_val[bitindex--].value();
250 for(; bitindex >= 0; --bitindex) {
251 auto c =
'0' + old_val[bitindex].value();
254 else if(c ==
'1' || *(rawdata_ptr - 1) != c) {
259 vcdEmitValueChange(os, trc_hndl, bits, &rawdata[0]);
261template <>
void vcd_trace_t<sc_dt::sc_fxval, sc_dt::sc_fxval>::record(FPTR os) { vcdEmitValueChangeReal(os, trc_hndl, bits, old_val); }
262template <>
void vcd_trace_t<sc_dt::sc_fxval_fast, sc_dt::sc_fxval_fast>::record(FPTR os) {
263 vcdEmitValueChangeReal(os, trc_hndl, bits, old_val);
265template <>
void vcd_trace_t<sc_dt::sc_fxnum, sc_dt::sc_fxval>::record(FPTR os) { vcdEmitValueChangeReal(os, trc_hndl, bits, old_val); }
266template <>
void vcd_trace_t<sc_dt::sc_fxnum_fast, sc_dt::sc_fxval_fast>::record(FPTR os) {
267 vcdEmitValueChangeReal(os, trc_hndl, bits, old_val);
269template <>
void vcd_trace_t<sc_dt::sc_bv_base, sc_dt::sc_bv_base>::record(FPTR os) {
270 auto str = old_val.to_string();
271 auto* cstr = str.c_str();
274 while(c == *(cstr + 1))
276 vcdEmitValueChange(os, trc_hndl, bits, cstr);
278template <>
void vcd_trace_t<sc_dt::sc_lv_base, sc_dt::sc_lv_base>::record(FPTR os) {
279 auto str = old_val.to_string();
280 auto* cstr = str.c_str();
283 while(c == *(cstr + 1))
285 vcdEmitValueChange(os, trc_hndl, bits, cstr);
SCC SystemC tracing utilities.
std::vector< std::string > split(const std::string &s, char separator)