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 #ifdef FMT_SPDLOG_INTERNAL
30 #include <fmt/format.h>
33 #include <unordered_map>
39 inline void vcdEmitValueChange(FPTR os, std::string
const& handle,
unsigned bits,
const char *val) {
40 auto buf = bits==1?fmt::format(
"{}{}\n", *val, handle):fmt::format(
"b{} {}\n", val, handle);
41 FWRITE(buf.c_str(), 1, buf.size(), os);
44 inline void vcdEmitValueChange32(FPTR os, std::string
const& handle,
unsigned bits, uint32_t val){
45 auto buf = fmt::format(
"b{:b} {}\n", val&((1ull<<bits)-1), handle);
46 FWRITE(buf.c_str(), 1, buf.size(), os);
49 inline void vcdEmitValueChange64(FPTR os, std::string
const& handle,
unsigned bits, uint64_t val){
50 auto buf = fmt::format(
"b{:b} {}\n", val&((1ul<<std::min(63u,bits))-1), handle);
51 FWRITE(buf.c_str(), 1, buf.size(), os);
55 inline void vcdEmitValueChangeReal(FPTR os, std::string
const& handle,
unsigned bits, T val){
56 auto buf = fmt::format(
"r{:.16g} {}\n",
static_cast<double>(val), handle);
57 FWRITE(buf.c_str(), 1, buf.size(), os);
60 inline size_t get_buffer_size(
int length){
61 size_t sz = (
static_cast<size_t>(length) + 4096 ) & (~static_cast<size_t>(4096-1));
62 return std::max<uint64_t>(1024UL, sz);
70 void add_trace(T *trace){
72 add_trace_rec(std::begin(hier), std::end(hier), trace);
75 void print(FPTR os,
const char *scope_name =
"SystemC"){
76 auto buf = fmt::format(
"$scope module {} $end\n", scope_name);
77 FWRITE(buf.c_str(), 1, buf.size(), os);
78 for (
auto& e : m_traces)
79 print_variable_declaration_line(os, e.first.c_str(), e.second);
80 for (
auto& e : m_scopes)
81 e.second->print(os,e.first.c_str());
82 std::string end =
"$upscope $end\n";
83 FWRITE(end.c_str(), 1, end.size(), os);
87 for (
auto& s : m_scopes)
91 void add_trace_rec(std::vector<std::string>::iterator beg, std::vector<std::string>::iterator
const& end, T *trace){
92 if(std::distance(beg, end)==1){
93 m_traces.push_back(std::make_pair(*beg, trace));
95 auto sc = m_scopes.find(*beg);
96 if(sc == std::end(m_scopes))
98 sc->second->add_trace_rec(++beg, end, trace);
101 void print_variable_declaration_line(FPTR os,
const char* scoped_name, T* trc){
105 std::stringstream ss;
106 ss <<
"'" << scoped_name <<
"' has 0 bits";
107 SC_REPORT_ERROR(sc_core::SC_ID_TRACING_OBJECT_IGNORED_, ss.str().c_str() );
111 if(trc->type==WIRE) {
112 auto buf = fmt::format(
"$var wire {} {} {} $end\n", trc->bits, trc->trc_hndl, scoped_name);
113 FWRITE(buf.c_str(), 1, buf.size(), os);
115 auto buf = fmt::format(
"$var real {} {} {} $end\n", trc->bits, trc->trc_hndl, scoped_name);
116 FWRITE(buf.c_str(), 1, buf.size(), os);
120 auto buf = fmt::format(
"$var wire {} {} {} [{}:0] $end\n", trc->bits, trc->trc_hndl, scoped_name, trc->bits-1);
121 FWRITE(buf.c_str(), 1, buf.size(), os);
126 std::vector<std::pair<std::string,T*> > m_traces{0};
127 std::unordered_map<std::string, vcd_scope_stack*> m_scopes{0};
131 vcd_trace(std::string
const& nm, trace_type t,
unsigned bits): name{nm}, bits{bits}, type{t}{}
133 virtual void record(FPTR os) = 0;
135 virtual void update() = 0;
137 virtual uintptr_t get_hash() = 0;
141 const std::string name;
142 std::string trc_hndl{};
143 bool is_alias{
false};
144 bool is_triggered{
false};
146 const trace_type type;
151 inline unsigned get_bits(
const char** literals) {
153 for (nliterals = 0; literals[nliterals]; nliterals++)
continue;
154 return scc::ilog2(nliterals);
157 struct vcd_trace_enum :
public vcd_trace {
158 vcd_trace_enum(
const unsigned int& object_,
159 const std::string& name,
const char** literals)
160 : vcd_trace( name, trace::WIRE, get_bits(literals))
166 uintptr_t get_hash()
override {
return reinterpret_cast<uintptr_t
>(&act_val);}
168 inline bool changed() {
return !is_alias && old_val!=act_val; }
170 void update()
override { old_val=act_val; }
172 void record(FPTR os)
override { vcdEmitValueChange64(os, trc_hndl, bits, old_val); }
174 unsigned int old_val;
175 const unsigned int& act_val;
176 const char** literals;
179 template<
typename T,
typename OT=T>
180 struct vcd_trace_t :
public vcd_trace {
181 vcd_trace_t(
const T& object_,
182 const std::string& name)
183 : vcd_trace( name, trace::traits<T>::get_type(), trace::traits<T>::get_bits(object_))
188 uintptr_t get_hash()
override {
return reinterpret_cast<uintptr_t
>(&act_val);}
190 inline bool changed() {
return !is_alias && old_val!=act_val; }
192 void update()
override { old_val=act_val; }
194 void record(FPTR os)
override;
200 template<
typename T,
typename OT>
201 void vcd_trace_t<T, OT>::record(FPTR os) {
203 vcdEmitValueChange32(os, trc_hndl, bits, old_val);
205 vcdEmitValueChange64(os, trc_hndl, bits, old_val);
207 template<>
void vcd_trace_t<sc_core::sc_time, sc_core::sc_time>::record(FPTR os){
208 vcdEmitValueChange64(os, trc_hndl, bits, old_val.value());
210 template<>
void vcd_trace_t<bool, bool>::record(FPTR os){
211 vcdEmitValueChange(os, trc_hndl, 1, old_val ?
"1" :
"0");
213 template<>
void vcd_trace_t<sc_dt::sc_bit, sc_dt::sc_bit>::record(FPTR os){
214 vcdEmitValueChange(os, trc_hndl, 1, old_val ?
"1" :
"0");
216 template<>
void vcd_trace_t<sc_dt::sc_logic, sc_dt::sc_logic>::record(FPTR os){
217 char buf[2] = {0, 0};
218 buf[0]=old_val.to_char();
219 vcdEmitValueChange(os, trc_hndl, 1, buf);
221 template<>
void vcd_trace_t<float, float>::record(FPTR os){
222 vcdEmitValueChangeReal(os, trc_hndl, 32, old_val);
224 template<>
void vcd_trace_t<double, double>::record(FPTR os){
225 vcdEmitValueChangeReal(os, trc_hndl, 64, old_val);
227 template<>
void vcd_trace_t<sc_dt::sc_int_base, sc_dt::sc_int_base>::record(FPTR os){
228 static std::vector<char> rawdata(get_buffer_size(old_val.length()));
229 char *rawdata_ptr = &rawdata[0];
230 for (
int bitindex = old_val.length() - 1; bitindex >= 0; --bitindex) {
231 *rawdata_ptr++ =
'0'+old_val[bitindex].value();
233 vcdEmitValueChange(os, trc_hndl, bits, &rawdata[0]);
235 template<>
void vcd_trace_t<sc_dt::sc_uint_base, sc_dt::sc_uint_base>::record(FPTR os){
236 static std::vector<char> rawdata(get_buffer_size(old_val.length()));
237 char *rawdata_ptr = &rawdata[0];
238 for (
int bitindex = old_val.length() - 1; bitindex >= 0; --bitindex) {
239 *rawdata_ptr++ =
'0'+old_val[bitindex].value();
241 vcdEmitValueChange(os, trc_hndl, bits, &rawdata[0]);
243 template<>
void vcd_trace_t<sc_dt::sc_signed, sc_dt::sc_signed>::record(FPTR os){
244 static std::vector<char> rawdata(get_buffer_size(old_val.length()));
245 char *rawdata_ptr = &rawdata[0];
246 bool is_started=
false;
247 int bitindex = old_val.length() - 1;
248 *rawdata_ptr++ =
'0'+old_val[bitindex--].value();
249 for (; bitindex >= 0; --bitindex) {
250 auto c =
'0'+old_val[bitindex].value();
253 else if(c==
'1' || *(rawdata_ptr-1)!=c ) {
258 vcdEmitValueChange(os, trc_hndl, bits, &rawdata[0]);
260 template<>
void vcd_trace_t<sc_dt::sc_unsigned, sc_dt::sc_unsigned>::record(FPTR os){
261 static std::vector<char> rawdata(get_buffer_size(old_val.length()));
262 char *rawdata_ptr = &rawdata[0];
263 bool is_started=
false;
264 int bitindex = old_val.length() - 1;
265 *rawdata_ptr++ =
'0'+old_val[bitindex--].value();
266 for (; bitindex >= 0; --bitindex) {
267 auto c =
'0'+old_val[bitindex].value();
270 else if(c==
'1' || *(rawdata_ptr-1)!=c ) {
275 vcdEmitValueChange(os, trc_hndl, bits, &rawdata[0]);
277 template<>
void vcd_trace_t<sc_dt::sc_fxval, sc_dt::sc_fxval>::record(FPTR os){
278 vcdEmitValueChangeReal(os, trc_hndl, bits, old_val);
280 template<>
void vcd_trace_t<sc_dt::sc_fxval_fast, sc_dt::sc_fxval_fast>::record(FPTR os){
281 vcdEmitValueChangeReal(os, trc_hndl, bits, old_val);
283 template<>
void vcd_trace_t<sc_dt::sc_fxnum, sc_dt::sc_fxval>::record(FPTR os){
284 vcdEmitValueChangeReal(os, trc_hndl, bits, old_val);
286 template<>
void vcd_trace_t<sc_dt::sc_fxnum_fast, sc_dt::sc_fxval_fast>::record(FPTR os){
287 vcdEmitValueChangeReal(os, trc_hndl, bits, old_val);
289 template<>
void vcd_trace_t<sc_dt::sc_bv_base, sc_dt::sc_bv_base>::record(FPTR os){
290 auto str = old_val.to_string();
291 auto* cstr = str.c_str();
293 if(c!=
'1')
while(c == *(cstr+1)) cstr++;
294 vcdEmitValueChange(os, trc_hndl, bits, cstr);
296 template<>
void vcd_trace_t<sc_dt::sc_lv_base, sc_dt::sc_lv_base>::record(FPTR os){
297 auto str = old_val.to_string();
298 auto* cstr = str.c_str();
300 if(c!=
'1')
while(c == *(cstr+1)) cstr++;
301 vcdEmitValueChange(os, trc_hndl, bits, cstr);
std::vector< std::string > split(const std::string &s, char separator)