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 <util/ities.h>
26 #include <scc/utilities.h>
27 #include <fmt/format.h>
29 #include <unordered_map>
35 inline void vcdEmitValueChange(FPTR os, std::string
const& handle,
unsigned bits,
const char *val) {
36 auto buf = bits==1?fmt::format(
"{}{}\n", *val, handle):fmt::format(
"b{} {}\n", val, handle);
37 FWRITE(buf.c_str(), 1, buf.size(), os);
40 inline void vcdEmitValueChange32(FPTR os, std::string
const& handle,
unsigned bits, uint32_t val){
41 auto buf = fmt::format(
"b{:b} {}\n", val&((1ull<<bits)-1), handle);
42 FWRITE(buf.c_str(), 1, buf.size(), os);
45 inline void vcdEmitValueChange64(FPTR os, std::string
const& handle,
unsigned bits, uint64_t val){
46 auto buf = fmt::format(
"b{:b} {}\n", val&((1ul<<std::min(63u,bits))-1), handle);
47 FWRITE(buf.c_str(), 1, buf.size(), os);
51 inline void vcdEmitValueChangeReal(FPTR os, std::string
const& handle,
unsigned bits, T val){
52 auto buf = fmt::format(
"r{:.16g} {}\n",
static_cast<double>(val), handle);
53 FWRITE(buf.c_str(), 1, buf.size(), os);
56 inline size_t get_buffer_size(
int length){
57 size_t sz = (
static_cast<size_t>(length) + 4096 ) & (~static_cast<size_t>(4096-1));
58 return std::max<uint64_t>(1024UL, sz);
66 void add_trace(T *trace){
68 add_trace_rec(std::begin(hier), std::end(hier), trace);
71 void print(FPTR os,
const char *scope_name =
"SystemC"){
72 auto buf = fmt::format(
"$scope module {} $end\n", scope_name);
73 FWRITE(buf.c_str(), 1, buf.size(), os);
74 for (
auto& e : m_traces)
75 print_variable_declaration_line(os, e.first.c_str(), e.second);
76 for (
auto& e : m_scopes)
77 e.second->print(os,e.first.c_str());
78 std::string end =
"$upscope $end\n";
79 FWRITE(end.c_str(), 1, end.size(), os);
83 for (
auto& s : m_scopes)
87 void add_trace_rec(std::vector<std::string>::iterator beg, std::vector<std::string>::iterator
const& end, T *trace){
88 if(std::distance(beg, end)==1){
89 m_traces.push_back(std::make_pair(*beg, trace));
91 auto sc = m_scopes.find(*beg);
92 if(sc == std::end(m_scopes))
94 sc->second->add_trace_rec(++beg, end, trace);
97 void print_variable_declaration_line(FPTR os,
const char* scoped_name, T* trc){
101 std::stringstream ss;
102 ss <<
"'" << scoped_name <<
"' has 0 bits";
103 SC_REPORT_ERROR(sc_core::SC_ID_TRACING_OBJECT_IGNORED_, ss.str().c_str() );
107 if(trc->type==WIRE) {
108 auto buf = fmt::format(
"$var wire {} {} {} $end\n", trc->bits, trc->trc_hndl, scoped_name);
109 FWRITE(buf.c_str(), 1, buf.size(), os);
111 auto buf = fmt::format(
"$var real {} {} {} $end\n", trc->bits, trc->trc_hndl, scoped_name);
112 FWRITE(buf.c_str(), 1, buf.size(), os);
116 auto buf = fmt::format(
"$var wire {} {} {} [{}:0] $end\n", trc->bits, trc->trc_hndl, scoped_name, trc->bits-1);
117 FWRITE(buf.c_str(), 1, buf.size(), os);
122 std::vector<std::pair<std::string,T*> > m_traces{0};
123 std::unordered_map<std::string, vcd_scope_stack*> m_scopes{0};
127 vcd_trace(std::string
const& nm, trace_type t,
unsigned bits): name{nm}, bits{bits}, type{t}{}
129 virtual void record(FPTR os) = 0;
131 virtual void update() = 0;
133 virtual uintptr_t get_hash() = 0;
137 const std::string name;
138 std::string trc_hndl{};
139 bool is_alias{
false};
140 bool is_triggered{
false};
142 const trace_type type;
147 inline unsigned get_bits(
const char** literals) {
149 for (nliterals = 0; literals[nliterals]; nliterals++)
continue;
150 return scc::ilog2(nliterals);
153 struct vcd_trace_enum :
public vcd_trace {
154 vcd_trace_enum(
const unsigned int& object_,
155 const std::string& name,
const char** literals)
156 : vcd_trace( name, trace::WIRE, get_bits(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;
175 template<
typename T,
typename OT=T>
176 struct vcd_trace_t :
public vcd_trace {
177 vcd_trace_t(
const T& object_,
178 const std::string& name)
179 : vcd_trace( name, trace::traits<T>::get_type(), trace::traits<T>::get_bits(object_))
184 uintptr_t get_hash()
override {
return reinterpret_cast<uintptr_t
>(&act_val);}
186 inline bool changed() {
return !is_alias && old_val!=act_val; }
188 void update()
override { old_val=act_val; }
190 void record(FPTR os)
override;
196 template<
typename T,
typename OT>
197 void vcd_trace_t<T, OT>::record(FPTR os) {
199 vcdEmitValueChange32(os, trc_hndl, bits, old_val);
201 vcdEmitValueChange64(os, trc_hndl, bits, old_val);
203 template<>
void vcd_trace_t<sc_core::sc_time, sc_core::sc_time>::record(FPTR os){
204 vcdEmitValueChange64(os, trc_hndl, bits, old_val.value());
206 template<>
void vcd_trace_t<bool, bool>::record(FPTR os){
207 vcdEmitValueChange(os, trc_hndl, 1, old_val ?
"1" :
"0");
209 template<>
void vcd_trace_t<sc_dt::sc_bit, sc_dt::sc_bit>::record(FPTR os){
210 vcdEmitValueChange(os, trc_hndl, 1, old_val ?
"1" :
"0");
212 template<>
void vcd_trace_t<sc_dt::sc_logic, sc_dt::sc_logic>::record(FPTR os){
213 char buf[2] = {0, 0};
214 buf[0]=old_val.to_char();
215 vcdEmitValueChange(os, trc_hndl, 1, buf);
217 template<>
void vcd_trace_t<float, float>::record(FPTR os){
218 vcdEmitValueChangeReal(os, trc_hndl, 32, old_val);
220 template<>
void vcd_trace_t<double, double>::record(FPTR os){
221 vcdEmitValueChangeReal(os, trc_hndl, 64, old_val);
223 template<>
void vcd_trace_t<sc_dt::sc_int_base, sc_dt::sc_int_base>::record(FPTR os){
224 static std::vector<char> rawdata(get_buffer_size(old_val.length()));
225 char *rawdata_ptr = &rawdata[0];
226 for (
int bitindex = old_val.length() - 1; bitindex >= 0; --bitindex) {
227 *rawdata_ptr++ =
'0'+old_val[bitindex].value();
229 vcdEmitValueChange(os, trc_hndl, bits, &rawdata[0]);
231 template<>
void vcd_trace_t<sc_dt::sc_uint_base, sc_dt::sc_uint_base>::record(FPTR os){
232 static std::vector<char> rawdata(get_buffer_size(old_val.length()));
233 char *rawdata_ptr = &rawdata[0];
234 for (
int bitindex = old_val.length() - 1; bitindex >= 0; --bitindex) {
235 *rawdata_ptr++ =
'0'+old_val[bitindex].value();
237 vcdEmitValueChange(os, trc_hndl, bits, &rawdata[0]);
239 template<>
void vcd_trace_t<sc_dt::sc_signed, sc_dt::sc_signed>::record(FPTR os){
240 static std::vector<char> rawdata(get_buffer_size(old_val.length()));
241 char *rawdata_ptr = &rawdata[0];
242 bool is_started=
false;
243 int bitindex = old_val.length() - 1;
244 *rawdata_ptr++ =
'0'+old_val[bitindex--].value();
245 for (; bitindex >= 0; --bitindex) {
246 auto c =
'0'+old_val[bitindex].value();
249 else if(c==
'1' || *(rawdata_ptr-1)!=c ) {
254 vcdEmitValueChange(os, trc_hndl, bits, &rawdata[0]);
256 template<>
void vcd_trace_t<sc_dt::sc_unsigned, sc_dt::sc_unsigned>::record(FPTR os){
257 static std::vector<char> rawdata(get_buffer_size(old_val.length()));
258 char *rawdata_ptr = &rawdata[0];
259 bool is_started=
false;
260 int bitindex = old_val.length() - 1;
261 *rawdata_ptr++ =
'0'+old_val[bitindex--].value();
262 for (; bitindex >= 0; --bitindex) {
263 auto c =
'0'+old_val[bitindex].value();
266 else if(c==
'1' || *(rawdata_ptr-1)!=c ) {
271 vcdEmitValueChange(os, trc_hndl, bits, &rawdata[0]);
273 template<>
void vcd_trace_t<sc_dt::sc_fxval, sc_dt::sc_fxval>::record(FPTR os){
274 vcdEmitValueChangeReal(os, trc_hndl, bits, old_val);
276 template<>
void vcd_trace_t<sc_dt::sc_fxval_fast, sc_dt::sc_fxval_fast>::record(FPTR os){
277 vcdEmitValueChangeReal(os, trc_hndl, bits, old_val);
279 template<>
void vcd_trace_t<sc_dt::sc_fxnum, sc_dt::sc_fxval>::record(FPTR os){
280 vcdEmitValueChangeReal(os, trc_hndl, bits, old_val);
282 template<>
void vcd_trace_t<sc_dt::sc_fxnum_fast, sc_dt::sc_fxval_fast>::record(FPTR os){
283 vcdEmitValueChangeReal(os, trc_hndl, bits, old_val);
285 template<>
void vcd_trace_t<sc_dt::sc_bv_base, sc_dt::sc_bv_base>::record(FPTR os){
286 auto str = old_val.to_string();
287 auto* cstr = str.c_str();
289 if(c!=
'1')
while(c == *(cstr+1)) cstr++;
290 vcdEmitValueChange(os, trc_hndl, bits, cstr);
292 template<>
void vcd_trace_t<sc_dt::sc_lv_base, sc_dt::sc_lv_base>::record(FPTR os){
293 auto str = old_val.to_string();
294 auto* cstr = str.c_str();
296 if(c!=
'1')
while(c == *(cstr+1)) cstr++;
297 vcdEmitValueChange(os, trc_hndl, bits, cstr);
std::vector< std::string > split(const std::string &s, char separator)