17 #include "vcd_pull_trace.hh"
18 #include "sc_vcd_trace.h"
19 #include "trace/vcd_trace.hh"
20 #include "utilities.h"
33 #include <unordered_map>
36 #define FPRINT(FP, FMTSTR) \
38 auto buf = fmt::format(FMTSTR); \
39 std::fwrite(buf.c_str(), 1, buf.size(), FP); \
41 #define FPRINTF(FP, FMTSTR, ...) \
43 auto buf = fmt::format(FMTSTR, __VA_ARGS__); \
44 std::fwrite(buf.c_str(), 1, buf.size(), FP); \
51 vcd_pull_trace_file::vcd_pull_trace_file(
const char* name, std::function<
bool()>& enable)
53 , check_enabled(enable) {
54 vcd_out = fopen(fmt::format(
"{}.vcd", name).c_str(),
"w");
56 #if defined(WITH_SC_TRACING_PHASE_CALLBACKS)
60 sc_object::register_simulation_phase_callback(SC_BEFORE_TIMESTEP);
62 sc_core::sc_get_curr_simcontext()->add_trace_file(
this);
66 vcd_pull_trace_file::~vcd_pull_trace_file() {
68 FPRINTF(vcd_out,
"#{}\n", sc_core::sc_time_stamp() / 1_ps);
71 for(
auto t : all_traces)
75 template <
typename T,
typename OT = T>
bool changed(trace::vcd_trace* trace) {
76 if(
reinterpret_cast<trace::vcd_trace_t<T, OT>*
>(trace)->changed()) {
77 reinterpret_cast<trace::vcd_trace_t<T, OT>*
>(trace)->update();
82 #define DECL_TRACE_METHOD_A(tp) \
83 void vcd_pull_trace_file::trace(const tp& object, const std::string& name) { \
84 all_traces.emplace_back(&changed<tp>, new trace::vcd_trace_t<tp>(object, name)); \
86 #define DECL_TRACE_METHOD_B(tp) \
87 void vcd_pull_trace_file::trace(const tp& object, const std::string& name, int width) { \
88 all_traces.emplace_back(&changed<tp>, new trace::vcd_trace_t<tp>(object, name)); \
90 #define DECL_TRACE_METHOD_C(tp, tpo) \
91 void vcd_pull_trace_file::trace(const tp& object, const std::string& name) { \
92 all_traces.emplace_back(&changed<tp, tpo>, new trace::vcd_trace_t<tp, tpo>(object, name)); \
95 #if(SYSTEMC_VERSION >= 20171012)
96 void vcd_pull_trace_file::trace(
const sc_core::sc_event&
object,
const std::string& name) {}
98 DECL_TRACE_METHOD_A(sc_core::sc_time)
100 DECL_TRACE_METHOD_A(
bool)
101 DECL_TRACE_METHOD_A(sc_dt::sc_bit)
102 DECL_TRACE_METHOD_A(sc_dt::sc_logic)
104 DECL_TRACE_METHOD_B(
unsigned char)
105 DECL_TRACE_METHOD_B(
unsigned short)
106 DECL_TRACE_METHOD_B(
unsigned int)
107 DECL_TRACE_METHOD_B(
unsigned long)
108 #ifdef SYSTEMC_64BIT_PATCHES
109 DECL_TRACE_METHOD_B(
unsigned long long)
111 DECL_TRACE_METHOD_B(
char)
112 DECL_TRACE_METHOD_B(
short)
113 DECL_TRACE_METHOD_B(
int)
114 DECL_TRACE_METHOD_B(
long)
115 DECL_TRACE_METHOD_B(sc_dt::int64)
116 DECL_TRACE_METHOD_B(sc_dt::uint64)
118 DECL_TRACE_METHOD_A(
float)
119 DECL_TRACE_METHOD_A(
double)
120 DECL_TRACE_METHOD_A(sc_dt::sc_int_base)
121 DECL_TRACE_METHOD_A(sc_dt::sc_uint_base)
122 DECL_TRACE_METHOD_A(sc_dt::sc_signed)
123 DECL_TRACE_METHOD_A(sc_dt::sc_unsigned)
125 DECL_TRACE_METHOD_A(sc_dt::sc_fxval)
126 DECL_TRACE_METHOD_A(sc_dt::sc_fxval_fast)
127 DECL_TRACE_METHOD_C(sc_dt::sc_fxnum, sc_dt::sc_fxval)
128 DECL_TRACE_METHOD_C(sc_dt::sc_fxnum_fast, sc_dt::sc_fxval_fast)
130 DECL_TRACE_METHOD_A(sc_dt::sc_bv_base)
131 DECL_TRACE_METHOD_A(sc_dt::sc_lv_base)
132 #undef DECL_TRACE_METHOD_A
133 #undef DECL_TRACE_METHOD_B
135 void vcd_pull_trace_file::trace(
const unsigned int&
object,
const std::string& name,
const char** enum_literals) {
136 all_traces.emplace_back(&changed<unsigned int>,
new trace::vcd_trace_enum(
object, name, enum_literals));
139 std::string vcd_pull_trace_file::obtain_name() {
140 const char first_type_used =
'a';
141 const int used_types_count =
'z' -
'a' + 1;
144 result = vcd_name_index;
145 char char6 =
static_cast<char>(vcd_name_index % used_types_count);
147 result = result / used_types_count;
148 char char5 =
static_cast<char>(result % used_types_count);
150 result = result / used_types_count;
151 char char4 =
static_cast<char>(result % used_types_count);
153 result = result / used_types_count;
154 char char3 =
static_cast<char>(result % used_types_count);
156 result = result / used_types_count;
157 char char2 =
static_cast<char>(result % used_types_count);
160 std::sprintf(buf,
"%c%c%c%c%c", char2 + first_type_used, char3 + first_type_used, char4 + first_type_used, char5 + first_type_used,
161 char6 + first_type_used);
163 return std::string(buf);
166 void vcd_pull_trace_file::write_comment(
const std::string& comment) { FPRINTF(vcd_out,
"$comment\n{}\n$end\n\n", comment); }
168 void vcd_pull_trace_file::init() {
169 std::sort(std::begin(all_traces), std::end(all_traces),
170 [](trace_entry
const& a, trace_entry
const& b) ->
bool {
return a.trc->name < b.trc->name; });
171 std::unordered_map<uintptr_t, std::string> alias_map;
173 trace::vcd_scope_stack<trace::vcd_trace> scope;
174 for(
auto& e : all_traces) {
175 auto alias_it = alias_map.find(e.trc->get_hash());
176 e.trc->is_alias = alias_it != std::end(alias_map);
177 e.trc->trc_hndl = e.trc->is_alias ? alias_it->second : obtain_name();
179 alias_map.insert({e.trc->get_hash(), e.trc->trc_hndl});
180 scope.add_trace(e.trc);
182 std::copy_if(std::begin(all_traces), std::end(all_traces), std::back_inserter(active_traces),
183 [](trace_entry
const& e) {
return !e.trc->is_alias; });
184 changed_traces.reserve(active_traces.size());
189 struct tm* p_tm = localtime(&long_time);
190 strftime(tbuf, 199,
"%b %d, %Y %H:%M:%S", p_tm);
191 FPRINTF(vcd_out,
"$date\n {}\n$end\n\n", tbuf);
193 FPRINTF(vcd_out,
"$version\n {}\n$end\n\n", sc_core::sc_version());
195 FPRINTF(vcd_out,
"$timescale\n {}\n$end\n\n", (1_ps).to_string());
196 std::stringstream ss;
197 ss <<
"tracing " << active_traces.size() <<
" distinct traces out of " << all_traces.size() <<
" traces";
198 write_comment(ss.str());
199 scope.print(vcd_out);
202 std::string vcd_pull_trace_file::prune_name(std::string
const& orig_name) {
203 static bool warned =
false;
204 bool braces_removed =
false;
205 std::string hier_name = orig_name;
206 for(
unsigned int i = 0; i < hier_name.length(); i++) {
207 if(hier_name[i] ==
'[') {
209 braces_removed =
true;
210 }
else if(hier_name[i] ==
']') {
212 braces_removed =
true;
216 if(braces_removed && !warned) {
217 std::stringstream ss;
220 "\tTraced objects found with name containing [], which may be\n"
221 "\tinterpreted by the waveform viewer in unexpected ways.\n"
222 "\tSo the [] is automatically replaced by ().";
224 SC_REPORT_WARNING(sc_core::SC_ID_TRACING_OBJECT_NAME_FILTERED_, ss.str().c_str());
229 void vcd_pull_trace_file::cycle(
bool delta_cycle) {
235 FPRINT(vcd_out,
"$enddefinitions $end\n\n$dumpvars\n");
236 for(
auto& e : active_traces) {
237 e.compare_and_update(e.trc);
238 e.trc->record(vcd_out);
240 FPRINT(vcd_out,
"$end\n\n");
242 if(check_enabled && !check_enabled())
244 changed_traces.clear();
245 for(
auto& e : active_traces) {
246 if(e.compare_and_update(e.trc))
247 changed_traces.push_back(e.trc);
249 if(changed_traces.size()) {
250 FPRINTF(vcd_out,
"#{}\n", sc_core::sc_time_stamp() / 1_ps);
251 for(
auto& t : changed_traces)
257 void vcd_pull_trace_file::set_time_unit(
double v, sc_core::sc_time_unit tu) {}
259 void vcd_pull_trace_file::set_time_unit(
int exponent10_seconds) {}
sc_core::sc_trace_file * create_vcd_pull_trace_file(const char *name, std::function< bool()> enable=std::function< bool()>())
create VCD file which uses pull mechanism
void close_vcd_pull_trace_file(sc_core::sc_trace_file *tf)
close the VCD file