gem5  v22.1.0.0
vcd.cc
Go to the documentation of this file.
1 /*
2  * Copyright 2018 Google, Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met: redistributions of source code must retain the above copyright
7  * notice, this list of conditions and the following disclaimer;
8  * redistributions in binary form must reproduce the above copyright
9  * notice, this list of conditions and the following disclaimer in the
10  * documentation and/or other materials provided with the distribution;
11  * neither the name of the copyright holders nor the names of its
12  * contributors may be used to endorse or promote products derived from
13  * this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "systemc/utils/vcd.hh"
29 
30 #include <ctime>
31 #include <iomanip>
32 
33 #include "base/bitfield.hh"
34 #include "base/cprintf.hh"
35 #include "sim/core.hh"
50 
51 namespace sc_gem5
52 {
53 
54 namespace
55 {
56 
57 std::string
58 cleanName(std::string name)
59 {
60  for (int i = 0; i < name.length(); i++) {
61  if (name[i] == '[')
62  name[i] = '(';
63  else if (name[i] == ']')
64  name[i] = ')';
65  }
66  return name;
67 }
68 
69 } // anonymous namespace
70 
72 {
73  protected:
74  std::string _vcdName;
75 
76  const char *
77  stripLeadingBits(const char *orig)
78  {
79  const char first = orig[0];
80 
81  if (first != 'z' && first != 'x' && first != '0')
82  return orig;
83 
84  const char *res = orig;
85  while (*++res == first) {}
86 
87  if (first != '0' || *res != '1')
88  res--;
89 
90  return res;
91  }
92 
93  char
95  {
96  switch (in) {
97  case 'U':
98  case 'X':
99  case 'W':
100  case 'D':
101  return 'x';
102  case '0':
103  case 'L':
104  return '0';
105  case '1':
106  case 'H':
107  return '1';
108  case 'Z':
109  return 'z';
110  default:
111  return '?';
112  }
113  }
114 
115  void
116  printVal(std::ostream &os, const std::string &rep)
117  {
118  switch (width()) {
119  case 0:
120  return;
121  case 1:
122  os << rep << vcdName() << std::endl;;
123  return;
124  default:
125  os << "b" << stripLeadingBits(rep.c_str()) << " " <<
126  vcdName() << std::endl;
127  return;
128  }
129  }
130 
131  public:
134 
135  void vcdName(const std::string &vcd_name) { _vcdName = vcd_name; }
136  const std::string &vcdName() { return _vcdName; }
137  virtual std::string vcdType() { return "wire"; }
138 
139  virtual void output(std::ostream &os) = 0;
140 };
141 
142 void
143 VcdTraceScope::addValue(const std::string &name, VcdTraceValBase *value)
144 {
145  size_t pos = name.find_first_of('.');
146  if (pos == std::string::npos) {
147  values.emplace_back(name, value);
148  } else {
149  std::string sname = name.substr(0, pos);
150  auto it = scopes.find(sname);
151  if (it == scopes.end())
152  it = scopes.emplace(sname, new VcdTraceScope).first;
153  it->second->addValue(name.substr(pos + 1), value);
154  }
155 }
156 
157 void
158 VcdTraceScope::output(const std::string &name, std::ostream &os)
159 {
160  os << "$scope module " << name << " $end" << std::endl;
161 
162  for (auto &p: values) {
163  const std::string &name = p.first;
164  VcdTraceValBase *value = p.second;
165 
166  int w = value->width();
167  if (w <= 0) {
168  std::string msg = gem5::csprintf("'%s' has 0 bits", name);
169  // The typo in this error message is intentional to match the
170  // Accellera output.
171  SC_REPORT_ERROR("(E710) object cannot not be traced", msg.c_str());
172  return;
173  }
174 
175  std::string clean_name = cleanName(name);
176  if (w == 1) {
177  gem5::ccprintf(os, "$var %s % 3d %s %s $end\n",
178  value->vcdType(), w, value->vcdName(), clean_name);
179  } else {
180  gem5::ccprintf(os, "$var %s % 3d %s %s [%d:0] $end\n",
181  value->vcdType(), w, value->vcdName(), clean_name, w - 1);
182  }
183  }
184 
185  for (auto &p: scopes)
186  p.second->output(p.first, os);
187 
188  os << "$upscope $end" << std::endl;
189 }
190 
191 template <typename T>
192 class VcdTraceVal : public TraceVal<T, VcdTraceValBase>
193 {
194  public:
195  typedef T TracedType;
196 
197  VcdTraceVal(const T* t, const std::string &vcd_name, int width) :
199  {
200  this->vcdName(vcd_name);
201  }
202 };
203 
204 std::string
206 {
207  std::string name(_nextName);
208 
209  bool carry = false;
210  int pos = NextNameChars - 1;
211  do {
212  carry = (_nextName[pos] == 'z');
213  if (carry)
214  _nextName[pos--] = 'a';
215  else
216  _nextName[pos--]++;
217  } while (carry && pos >= 0);
218 
219  return name;
220 }
221 
222 void
224 {
225  finalizeTime();
226 
227  // Date.
228  stream() << "$date" << std::endl;
229  time_t long_time;
230  time(&long_time);
231  struct tm *p_tm = localtime(&long_time);
232  stream() << std::put_time(p_tm, " %b %d, %Y %H:%M:%S\n");
233  stream() << "$end" << std::endl << std::endl;
234 
235  // Version.
236  stream() << "$version" << std::endl;
237  stream() << " " << ::sc_core::sc_version() << std::endl;
238  stream() << "$end" << std::endl << std::endl;
239 
240  // Timescale.
241  stream() << "$timescale" << std::endl;
243  std::endl;
244  stream() << "$end" << std::endl << std::endl;
245 
246  for (auto tv: traceVals)
247  tv->finalize();
248 
249  topScope.output("SystemC", stream());
250 
251  stream() << "$enddefinitions $end" << std::endl << std::endl;
252 
254 
255  std::string timedump_comment =
256  gem5::csprintf("All initial values are dumped below at time "
257  "%g sec = %g timescale units.",
258  static_cast<double>(now) / gem5::sim_clock::as_float::s,
259  static_cast<double>(now / timeUnitTicks));
260  writeComment(timedump_comment);
261 
263 
264  stream() << "$dumpvars" << std::endl;
265  for (auto tv: traceVals)
266  tv->output(stream());
267  stream() << "$end" << std::endl << std::endl;
268 
269  initialized = true;
270 }
271 
273 {
274  for (auto tv: traceVals)
275  delete tv;
276  traceVals.clear();
277 
278  if (timeUnitTicks) {
279  gem5::ccprintf(stream(), "#%u\n",
281  }
282 }
283 
284 void
286 {
287  if (!delta)
288  deltasAtNow = 0;
289 
290  uint64_t deltaOffset = deltasAtNow;
291 
292  if (delta)
293  deltaOffset = deltasAtNow++;
294 
295  if (_traceDeltas != delta)
296  return;
297 
298  if (!initialized) {
299  initialize();
300  return;
301  }
302 
303  gem5::Tick now = scheduler.getCurTick() / timeUnitTicks + deltaOffset;
304 
305  if (now <= lastPrintedTime) {
306  // TODO warn about reversed time?
307  return;
308  }
309 
310  bool time_printed = false;
311  for (auto tv: traceVals) {
312  if (tv->check()) {
313  if (!time_printed) {
314  lastPrintedTime = now;
315  gem5::ccprintf(stream(), "#%u\n", now);
316  time_printed = true;
317  }
318 
319  tv->output(stream());
320  }
321  }
322  if (time_printed)
323  stream() << std::endl;
324 }
325 
326 class VcdTraceValBool : public VcdTraceVal<bool>
327 {
328  public:
330 
331  void
332  output(std::ostream &os) override
333  {
334  printVal(os, this->value() ? "1" : "0");
335  }
336 };
337 
338 void
339 VcdTraceFile::addTraceVal(const bool *v, const std::string &name)
340 {
341  addNewTraceVal<VcdTraceValBool>(v, name);
342 }
343 
344 template <typename T>
345 class VcdTraceValFloat : public VcdTraceVal<T>
346 {
347  public:
349 
350  std::string vcdType() override { return "real"; }
351 
352  void
353  output(std::ostream &os) override
354  {
355  gem5::ccprintf(os, "r%.16g %s\n", this->value(), this->vcdName());
356  }
357 };
358 
359 void
360 VcdTraceFile::addTraceVal(const float *v, const std::string &name)
361 {
362  addNewTraceVal<VcdTraceValFloat<float>>(v, name);
363 }
364 void
365 VcdTraceFile::addTraceVal(const double *v, const std::string &name)
366 {
367  addNewTraceVal<VcdTraceValFloat<double>>(v, name);
368 }
369 
370 class VcdTraceValScLogic : public VcdTraceVal<sc_dt::sc_logic>
371 {
372  public:
374 
375  void
376  output(std::ostream &os) override
377  {
378  char str[2] = {
379  scLogicToVcdState(value().to_char()),
380  '\0'
381  };
382  printVal(os, str);
383  }
384 };
385 
386 void
387 VcdTraceFile::addTraceVal(const sc_dt::sc_logic *v, const std::string &name)
388 {
389  addNewTraceVal<VcdTraceValScLogic>(v, name);
390 }
391 
392 template <typename T>
394 {
395  public:
397 
398  void
399  finalize() override
400  {
402  this->_width = this->value().length();
403  }
404 
405  void
406  output(std::ostream &os) override
407  {
408  std::string str;
409  const int w = this->width();
410 
411  str.reserve(w);
412  for (int i = w - 1; i >= 0; i--)
413  str += this->value()[i].to_bool() ? '1' : '0';
414 
415  this->printVal(os, str);
416  }
417 };
418 
419 void
421  const std::string &name)
422 {
423  addNewTraceVal<VcdTraceValFinite<sc_dt::sc_int_base>>(v, name);
424 }
425 void
427  const std::string &name)
428 {
429  addNewTraceVal<VcdTraceValFinite<sc_dt::sc_uint_base>>(v, name);
430 }
431 
432 void
434 {
435  addNewTraceVal<VcdTraceValFinite<sc_dt::sc_signed>>(v, name);
436 }
437 void
439  const std::string &name)
440 {
441  addNewTraceVal<VcdTraceValFinite<sc_dt::sc_unsigned>>(v, name);
442 }
443 
444 template <typename T>
445 class VcdTraceValLogic : public VcdTraceVal<T>
446 {
447  public:
449 
450  void
451  finalize() override
452  {
454  this->_width = this->value().length();
455  }
456 
457  void
458  output(std::ostream &os) override
459  {
460  this->printVal(os, this->value().to_string());
461  }
462 };
463 
464 void
466 {
467  addNewTraceVal<VcdTraceValLogic<::sc_dt::sc_bv_base>>(v, name);
468 }
469 void
471 {
472  addNewTraceVal<VcdTraceValLogic<::sc_dt::sc_lv_base>>(v, name);
473 }
474 
475 template <typename T>
476 class VcdTraceValFxval : public VcdTraceVal<T>
477 {
478  public:
480 
481  std::string vcdType() override { return "real"; }
482 
483  void
484  output(std::ostream &os) override
485  {
486  gem5::ccprintf(os, "r%.16g %s\n",
487  this->value().to_double(), this->vcdName());
488  }
489 };
490 
491 void
492 VcdTraceFile::addTraceVal(const sc_dt::sc_fxval *v, const std::string &name)
493 {
494  addNewTraceVal<VcdTraceValFxval<sc_dt::sc_fxval>>(v, name);
495 }
496 void
498  const std::string &name)
499 {
500  addNewTraceVal<VcdTraceValFxval<sc_dt::sc_fxval_fast>>(v, name);
501 }
502 
503 template <typename T>
504 class VcdTraceValFxnum : public VcdTraceVal<T>
505 {
506  public:
508 
509  void
510  output(std::ostream &os) override
511  {
512  std::string str;
513  const int w = this->width();
514 
515  str.reserve(w);
516  for (int i = w - 1; i >= 0; i--)
517  str += this->value()[i] ? '1' : '0';
518 
519  this->printVal(os, str);
520  }
521 };
522 
523 void
524 VcdTraceFile::addTraceVal(const sc_dt::sc_fxnum *v, const std::string &name)
525 {
526  addNewTraceVal<VcdTraceValFxnum<::sc_dt::sc_fxnum>>(v, name);
527 }
528 void
530  const std::string &name)
531 {
532  addNewTraceVal<VcdTraceValFxnum<::sc_dt::sc_fxnum_fast>>(v, name);
533 }
534 
535 class VcdTraceValEvent : public VcdTraceVal<::sc_core::sc_event>
536 {
537  public:
539 
540  std::string vcdType() override { return "event"; }
541 
542  void
543  output(std::ostream &os) override
544  {
545  if (value())
546  printVal(os, "1");
547  else
548  os << std::endl;
549  }
550 };
551 
552 void
554 {
555  addNewTraceVal<VcdTraceValEvent>(v, name);
556 }
557 
558 class VcdTraceValTime : public VcdTraceVal<::sc_core::sc_time>
559 {
560  private:
561  static const int TimeWidth = 64;
562 
563  public:
565 
566  std::string vcdType() override { return "time"; }
567 
568  void
569  finalize() override
570  {
572  _width = TimeWidth;
573  }
574 
575  void
576  output(std::ostream &os) override
577  {
578  char str[TimeWidth + 1];
579  str[TimeWidth] = '\0';
580 
581  const uint64_t val = value().value();
582  for (int i = 0; i < TimeWidth; i++)
583  str[i] = gem5::bits(val, TimeWidth - i - 1) ? '1' : '0';
584 
585  printVal(os, str);
586  }
587 };
588 void
590 {
591  addNewTraceVal<VcdTraceValTime>(v, name);
592 }
593 
594 template <typename T>
595 class VcdTraceValInt : public VcdTraceVal<T>
596 {
597  public:
599 
600  void
601  output(std::ostream &os) override
602  {
603  const int w = this->width();
604  char str[w + 1];
605  str[w] = '\0';
606 
607  const uint64_t val =
608  static_cast<uint64_t>(this->value()) & gem5::mask(sizeof(T) * 8);
609 
610  if (gem5::mask(w) < val) {
611  for (int i = 0; i < w; i++)
612  str[i] = 'x';
613  } else {
614  for (int i = 0; i < w; i++)
615  str[i] = gem5::bits(val, w - i - 1) ? '1' : '0';
616  }
617 
618  this->printVal(os, str);
619  }
620 };
621 
622 void
623 VcdTraceFile::addTraceVal(const unsigned char *v, const std::string &name,
624  int width)
625 {
626  addNewTraceVal<VcdTraceValInt<unsigned char>>(v, name, width);
627 }
628 void
629 VcdTraceFile::addTraceVal(const char *v, const std::string &name, int width)
630 {
631  addNewTraceVal<VcdTraceValInt<char>>(v, name, width);
632 }
633 void
634 VcdTraceFile::addTraceVal(const unsigned short *v, const std::string &name,
635  int width)
636 {
637  addNewTraceVal<VcdTraceValInt<unsigned short>>(v, name, width);
638 }
639 void
640 VcdTraceFile::addTraceVal(const short *v, const std::string &name, int width)
641 {
642  addNewTraceVal<VcdTraceValInt<short>>(v, name, width);
643 }
644 void
645 VcdTraceFile::addTraceVal(const unsigned int *v, const std::string &name,
646  int width)
647 {
648  addNewTraceVal<VcdTraceValInt<unsigned int>>(v, name, width);
649 }
650 void
651 VcdTraceFile::addTraceVal(const int *v, const std::string &name, int width)
652 {
653  addNewTraceVal<VcdTraceValInt<int>>(v, name, width);
654 }
655 void
656 VcdTraceFile::addTraceVal(const unsigned long *v, const std::string &name,
657  int width)
658 {
659  addNewTraceVal<VcdTraceValInt<unsigned long>>(v, name, width);
660 }
661 void
662 VcdTraceFile::addTraceVal(const long *v, const std::string &name, int width)
663 {
664  addNewTraceVal<VcdTraceValInt<long>>(v, name, width);
665 }
666 
667 void
668 VcdTraceFile::addTraceVal(const sc_dt::int64 *v, const std::string &name,
669  int width)
670 {
671  addNewTraceVal<VcdTraceValInt<sc_dt::int64>>(v, name, width);
672 }
673 void
674 VcdTraceFile::addTraceVal(const sc_dt::uint64 *v, const std::string &name,
675  int width)
676 {
677  addNewTraceVal<VcdTraceValInt<sc_dt::uint64>>(v, name, width);
678 }
679 
680 void
681 VcdTraceFile::addTraceVal(const unsigned int *v, const std::string &name,
682  const char **literals)
683 {
684  uint64_t count = 0;
685  while (*literals++)
686  count++;
687 
688  int bits = 0;
689  while (count >> bits)
690  bits++;
691 
692  addNewTraceVal<VcdTraceValInt<unsigned int>>(v, name, bits);
693 }
694 
695 void
696 VcdTraceFile::writeComment(const std::string &comment)
697 {
698  stream() << "$comment" << std::endl;
699  stream() << comment << std::endl;
700  stream() << "$end" << std::endl << std::endl;
701 }
702 
703 } // namespace sc_gem5
static sc_time from_value(sc_dt::uint64)
Definition: sc_time.cc:210
gem5::Tick getCurTick()
Definition: scheduler.hh:243
uint64_t timeUnitTicks
Definition: tracefile.hh:195
std::ostream & stream()
Definition: tracefile.cc:55
const T & value()
Definition: tracefile.hh:75
void initialize()
Definition: vcd.cc:223
void writeComment(const std::string &comment) override
Definition: vcd.cc:696
void addTraceVal(const bool *v, const std::string &name) override
Definition: vcd.cc:339
uint64_t deltasAtNow
Definition: vcd.hh:56
char _nextName[NextNameChars+1]
Definition: vcd.hh:59
static const int NextNameChars
Definition: vcd.hh:58
std::vector< VcdTraceValBase * > traceVals
Definition: vcd.hh:65
gem5::Tick lastPrintedTime
Definition: vcd.hh:55
std::string nextSignalName()
Definition: vcd.cc:205
void trace(bool delta) override
Definition: vcd.cc:285
VcdTraceScope topScope
Definition: vcd.hh:66
void addValue(const std::string &name, VcdTraceValBase *value)
Definition: vcd.cc:143
std::map< std::string, VcdTraceScope * > scopes
Definition: vcd.hh:45
std::vector< std::pair< std::string, VcdTraceValBase * > > values
Definition: vcd.hh:44
void output(const std::string &name, std::ostream &os)
Definition: vcd.cc:158
const char * stripLeadingBits(const char *orig)
Definition: vcd.cc:77
char scLogicToVcdState(char in)
Definition: vcd.cc:94
VcdTraceValBase(int width)
Definition: vcd.cc:132
const std::string & vcdName()
Definition: vcd.cc:136
virtual std::string vcdType()
Definition: vcd.cc:137
void printVal(std::ostream &os, const std::string &rep)
Definition: vcd.cc:116
void vcdName(const std::string &vcd_name)
Definition: vcd.cc:135
virtual void output(std::ostream &os)=0
std::string _vcdName
Definition: vcd.cc:74
void output(std::ostream &os) override
Definition: vcd.cc:332
void output(std::ostream &os) override
Definition: vcd.cc:543
std::string vcdType() override
Definition: vcd.cc:540
void output(std::ostream &os) override
Definition: vcd.cc:406
void finalize() override
Definition: vcd.cc:399
void output(std::ostream &os) override
Definition: vcd.cc:353
std::string vcdType() override
Definition: vcd.cc:350
void output(std::ostream &os) override
Definition: vcd.cc:510
void output(std::ostream &os) override
Definition: vcd.cc:484
std::string vcdType() override
Definition: vcd.cc:481
void output(std::ostream &os) override
Definition: vcd.cc:601
void finalize() override
Definition: vcd.cc:451
void output(std::ostream &os) override
Definition: vcd.cc:458
void output(std::ostream &os) override
Definition: vcd.cc:376
std::string vcdType() override
Definition: vcd.cc:566
void output(std::ostream &os) override
Definition: vcd.cc:576
void finalize() override
Definition: vcd.cc:569
static const int TimeWidth
Definition: vcd.cc:561
VcdTraceVal(const T *t, const std::string &vcd_name, int width)
Definition: vcd.cc:197
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition: bitfield.hh:76
constexpr uint64_t mask(unsigned nbits)
Generate a 64-bit mask of 'nbits' 1s, right justified.
Definition: bitfield.hh:63
Bitfield< 4 > width
Definition: misc_types.hh:72
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 32 > tm
Definition: misc.hh:112
Bitfield< 0 > v
Definition: pagetable.hh:65
Bitfield< 6 > w
Definition: pagetable.hh:59
Bitfield< 54 > p
Definition: pagetable.hh:70
Bitfield< 17 > os
Definition: misc.hh:810
Bitfield< 63 > val
Definition: misc.hh:776
Bitfield< 6 > rep
Definition: types.hh:81
double s
These variables equal the number of ticks in the unit of time they're named after in a double.
Definition: core.cc:53
uint64_t Tick
Tick count type.
Definition: types.hh:58
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
void ccprintf(cp::Print &print)
Definition: cprintf.hh:130
const char * sc_version()
Definition: functions.cc:44
uint64_t uint64
Definition: sc_nbdefs.hh:172
int64_t int64
Definition: sc_nbdefs.hh:171
const std::string to_string(sc_enc enc)
Definition: sc_fxdefs.cc:60
Scheduler scheduler
Definition: scheduler.cc:494
#define SC_REPORT_ERROR(msg_type, msg)
const std::string & name()
Definition: trace.cc:49

Generated on Wed Dec 21 2022 10:22:50 for gem5 by doxygen 1.9.1