gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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  * Authors: Gabe Black
28  */
29 
30 #include "systemc/utils/vcd.hh"
31 
32 #include <ctime>
33 #include <iomanip>
34 
35 #include "base/bitfield.hh"
36 #include "base/cprintf.hh"
51 
52 namespace sc_gem5
53 {
54 
55 namespace
56 {
57 
58 std::string
59 cleanName(std::string name)
60 {
61  for (int i = 0; i < name.length(); i++) {
62  if (name[i] == '[')
63  name[i] = '(';
64  else if (name[i] == ']')
65  name[i] = ')';
66  }
67  return name;
68 }
69 
70 } // anonymous namespace
71 
73 {
74  protected:
75  std::string _vcdName;
76 
77  const char *
78  stripLeadingBits(const char *orig)
79  {
80  const char first = orig[0];
81 
82  if (first != 'z' && first != 'x' && first != '0')
83  return orig;
84 
85  const char *res = orig;
86  while (*++res == first) {}
87 
88  if (first != '0' || *res != '1')
89  res--;
90 
91  return res;
92  }
93 
94  char
96  {
97  switch (in) {
98  case 'U':
99  case 'X':
100  case 'W':
101  case 'D':
102  return 'x';
103  case '0':
104  case 'L':
105  return '0';
106  case '1':
107  case 'H':
108  return '1';
109  case 'Z':
110  return 'z';
111  default:
112  return '?';
113  }
114  }
115 
116  void
117  printVal(std::ostream &os, const std::string &rep)
118  {
119  switch (width()) {
120  case 0:
121  return;
122  case 1:
123  os << rep << vcdName() << std::endl;;
124  return;
125  default:
126  os << "b" << stripLeadingBits(rep.c_str()) << " " <<
127  vcdName() << std::endl;
128  return;
129  }
130  }
131 
132  public:
135 
136  void vcdName(const std::string &vcd_name) { _vcdName = vcd_name; }
137  const std::string &vcdName() { return _vcdName; }
138  virtual std::string vcdType() { return "wire"; }
139 
140  virtual void output(std::ostream &os) = 0;
141 };
142 
143 void
144 VcdTraceScope::addValue(const std::string &name, VcdTraceValBase *value)
145 {
146  size_t pos = name.find_first_of('.');
147  if (pos == std::string::npos) {
148  values.emplace_back(name, value);
149  } else {
150  std::string sname = name.substr(0, pos);
151  auto it = scopes.find(sname);
152  if (it == scopes.end())
153  it = scopes.emplace(sname, new VcdTraceScope).first;
154  it->second->addValue(name.substr(pos + 1), value);
155  }
156 }
157 
158 void
159 VcdTraceScope::output(const std::string &name, std::ostream &os)
160 {
161  os << "$scope module " << name << " $end" << std::endl;
162 
163  for (auto &p: values) {
164  const std::string &name = p.first;
165  VcdTraceValBase *value = p.second;
166 
167  int w = value->width();
168  if (w <= 0) {
169  std::string msg = csprintf("'%s' has 0 bits", name);
170  // The typo in this error message is intentional to match the
171  // Accellera output.
172  SC_REPORT_ERROR("(E710) object cannot not be traced", msg.c_str());
173  return;
174  }
175 
176  std::string clean_name = cleanName(name);
177  if (w == 1) {
178  ccprintf(os, "$var %s % 3d %s %s $end\n",
179  value->vcdType(), w, value->vcdName(), clean_name);
180  } else {
181  ccprintf(os, "$var %s % 3d %s %s [%d:0] $end\n",
182  value->vcdType(), w, value->vcdName(), clean_name, w - 1);
183  }
184  }
185 
186  for (auto &p: scopes)
187  p.second->output(p.first, os);
188 
189  os << "$upscope $end" << std::endl;
190 }
191 
192 template <typename T>
193 class VcdTraceVal : public TraceVal<T, VcdTraceValBase>
194 {
195  public:
196  typedef T TracedType;
197 
198  VcdTraceVal(const T* t, const std::string &vcd_name, int width) :
199  TraceVal<T, VcdTraceValBase>(t, width)
200  {
201  this->vcdName(vcd_name);
202  }
203 };
204 
205 std::string
207 {
208  std::string name(_nextName);
209 
210  bool carry = false;
211  int pos = NextNameChars - 1;
212  do {
213  carry = (_nextName[pos] == 'z');
214  if (carry)
215  _nextName[pos--] = 'a';
216  else
217  _nextName[pos--]++;
218  } while (carry && pos >= 0);
219 
220  return name;
221 }
222 
223 void
225 {
226  finalizeTime();
227 
228  // Date.
229  stream() << "$date" << std::endl;
230  time_t long_time;
231  time(&long_time);
232  struct tm *p_tm = localtime(&long_time);
233  stream() << std::put_time(p_tm, " %b %d, %Y %H:%M:%S\n");
234  stream() << "$end" << std::endl << std::endl;
235 
236  // Version.
237  stream() << "$version" << std::endl;
238  stream() << " " << ::sc_core::sc_version() << std::endl;
239  stream() << "$end" << std::endl << std::endl;
240 
241  // Timescale.
242  stream() << "$timescale" << std::endl;
243  stream() << " " << ::sc_core::sc_time::from_value(timeUnitTicks) <<
244  std::endl;
245  stream() << "$end" << std::endl << std::endl;
246 
247  for (auto tv: traceVals)
248  tv->finalize();
249 
250  topScope.output("SystemC", stream());
251 
252  stream() << "$enddefinitions $end" << std::endl << std::endl;
253 
254  Tick now = scheduler.getCurTick();
255 
256  std::string timedump_comment =
257  csprintf("All initial values are dumped below at time "
258  "%g sec = %g timescale units.",
259  static_cast<double>(now) / SimClock::Float::s,
260  static_cast<double>(now / timeUnitTicks));
261  writeComment(timedump_comment);
262 
263  lastPrintedTime = now / timeUnitTicks;
264 
265  stream() << "$dumpvars" << std::endl;
266  for (auto tv: traceVals)
267  tv->output(stream());
268  stream() << "$end" << std::endl << std::endl;
269 
270  initialized = true;
271 }
272 
274 {
275  for (auto tv: traceVals)
276  delete tv;
277  traceVals.clear();
278 
279  if (timeUnitTicks)
280  ccprintf(stream(), "#%u\n", scheduler.getCurTick() / timeUnitTicks);
281 }
282 
283 void
285 {
286  if (!delta)
287  deltasAtNow = 0;
288 
289  uint64_t deltaOffset = deltasAtNow;
290 
291  if (delta)
292  deltaOffset = deltasAtNow++;
293 
294  if (_traceDeltas != delta)
295  return;
296 
297  if (!initialized) {
298  initialize();
299  return;
300  }
301 
302  Tick now = scheduler.getCurTick() / timeUnitTicks + deltaOffset;
303 
304  if (now <= lastPrintedTime) {
305  // TODO warn about reversed time?
306  return;
307  }
308 
309  bool time_printed = false;
310  for (auto tv: traceVals) {
311  if (tv->check()) {
312  if (!time_printed) {
313  lastPrintedTime = now;
314  ccprintf(stream(), "#%u\n", now);
315  time_printed = true;
316  }
317 
318  tv->output(stream());
319  }
320  }
321  if (time_printed)
322  stream() << std::endl;
323 }
324 
325 class VcdTraceValBool : public VcdTraceVal<bool>
326 {
327  public:
329 
330  void
331  output(std::ostream &os) override
332  {
333  printVal(os, this->value() ? "1" : "0");
334  }
335 };
336 
337 void
338 VcdTraceFile::addTraceVal(const bool *v, const std::string &name)
339 {
340  addNewTraceVal<VcdTraceValBool>(v, name);
341 }
342 
343 template <typename T>
344 class VcdTraceValFloat : public VcdTraceVal<T>
345 {
346  public:
348 
349  std::string vcdType() override { return "real"; }
350 
351  void
352  output(std::ostream &os) override
353  {
354  ccprintf(os, "r%.16g %s\n", this->value(), this->vcdName());
355  }
356 };
357 
358 void
359 VcdTraceFile::addTraceVal(const float *v, const std::string &name)
360 {
361  addNewTraceVal<VcdTraceValFloat<float>>(v, name);
362 }
363 void
364 VcdTraceFile::addTraceVal(const double *v, const std::string &name)
365 {
366  addNewTraceVal<VcdTraceValFloat<double>>(v, name);
367 }
368 
369 class VcdTraceValScLogic : public VcdTraceVal<sc_dt::sc_logic>
370 {
371  public:
373 
374  void
375  output(std::ostream &os) override
376  {
377  char str[2] = {
378  scLogicToVcdState(value().to_char()),
379  '\0'
380  };
381  printVal(os, str);
382  }
383 };
384 
385 void
386 VcdTraceFile::addTraceVal(const sc_dt::sc_logic *v, const std::string &name)
387 {
388  addNewTraceVal<VcdTraceValScLogic>(v, name);
389 }
390 
391 template <typename T>
393 {
394  public:
396 
397  void
398  finalize() override
399  {
401  this->_width = this->value().length();
402  }
403 
404  void
405  output(std::ostream &os) override
406  {
407  std::string str;
408  const int w = this->width();
409 
410  str.reserve(w);
411  for (int i = w - 1; i >= 0; i--)
412  str += this->value()[i].to_bool() ? '1' : '0';
413 
414  this->printVal(os, str);
415  }
416 };
417 
418 void
420  const std::string &name)
421 {
422  addNewTraceVal<VcdTraceValFinite<sc_dt::sc_int_base>>(v, name);
423 }
424 void
426  const std::string &name)
427 {
428  addNewTraceVal<VcdTraceValFinite<sc_dt::sc_uint_base>>(v, name);
429 }
430 
431 void
432 VcdTraceFile::addTraceVal(const sc_dt::sc_signed *v, const std::string &name)
433 {
434  addNewTraceVal<VcdTraceValFinite<sc_dt::sc_signed>>(v, name);
435 }
436 void
438  const std::string &name)
439 {
440  addNewTraceVal<VcdTraceValFinite<sc_dt::sc_unsigned>>(v, name);
441 }
442 
443 template <typename T>
444 class VcdTraceValLogic : public VcdTraceVal<T>
445 {
446  public:
448 
449  void
450  finalize() override
451  {
453  this->_width = this->value().length();
454  }
455 
456  void
457  output(std::ostream &os) override
458  {
459  this->printVal(os, this->value().to_string());
460  }
461 };
462 
463 void
464 VcdTraceFile::addTraceVal(const sc_dt::sc_bv_base *v, const std::string &name)
465 {
466  addNewTraceVal<VcdTraceValLogic<::sc_dt::sc_bv_base>>(v, name);
467 }
468 void
469 VcdTraceFile::addTraceVal(const sc_dt::sc_lv_base *v, const std::string &name)
470 {
471  addNewTraceVal<VcdTraceValLogic<::sc_dt::sc_lv_base>>(v, name);
472 }
473 
474 template <typename T>
475 class VcdTraceValFxval : public VcdTraceVal<T>
476 {
477  public:
479 
480  std::string vcdType() override { return "real"; }
481 
482  void
483  output(std::ostream &os) override
484  {
485  ccprintf(os, "r%.16g %s\n",
486  this->value().to_double(), this->vcdName());
487  }
488 };
489 
490 void
491 VcdTraceFile::addTraceVal(const sc_dt::sc_fxval *v, const std::string &name)
492 {
493  addNewTraceVal<VcdTraceValFxval<sc_dt::sc_fxval>>(v, name);
494 }
495 void
497  const std::string &name)
498 {
499  addNewTraceVal<VcdTraceValFxval<sc_dt::sc_fxval_fast>>(v, name);
500 }
501 
502 template <typename T>
503 class VcdTraceValFxnum : public VcdTraceVal<T>
504 {
505  public:
507 
508  void
509  output(std::ostream &os) override
510  {
511  std::string str;
512  const int w = this->width();
513 
514  str.reserve(w);
515  for (int i = w - 1; i >= 0; i--)
516  str += this->value()[i] ? '1' : '0';
517 
518  this->printVal(os, str);
519  }
520 };
521 
522 void
523 VcdTraceFile::addTraceVal(const sc_dt::sc_fxnum *v, const std::string &name)
524 {
525  addNewTraceVal<VcdTraceValFxnum<::sc_dt::sc_fxnum>>(v, name);
526 }
527 void
529  const std::string &name)
530 {
531  addNewTraceVal<VcdTraceValFxnum<::sc_dt::sc_fxnum_fast>>(v, name);
532 }
533 
534 class VcdTraceValEvent : public VcdTraceVal<::sc_core::sc_event>
535 {
536  public:
538 
539  std::string vcdType() override { return "event"; }
540 
541  void
542  output(std::ostream &os) override
543  {
544  if (value())
545  printVal(os, "1");
546  else
547  os << std::endl;
548  }
549 };
550 
551 void
552 VcdTraceFile::addTraceVal(const sc_core::sc_event *v, const std::string &name)
553 {
554  addNewTraceVal<VcdTraceValEvent>(v, name);
555 }
556 
557 class VcdTraceValTime : public VcdTraceVal<::sc_core::sc_time>
558 {
559  private:
560  static const int TimeWidth = 64;
561 
562  public:
564 
565  std::string vcdType() override { return "time"; }
566 
567  void
568  finalize() override
569  {
571  _width = TimeWidth;
572  }
573 
574  void
575  output(std::ostream &os) override
576  {
577  char str[TimeWidth + 1];
578  str[TimeWidth] = '\0';
579 
580  const uint64_t val = value().value();
581  for (int i = 0; i < TimeWidth; i++)
582  str[i] = ::bits(val, TimeWidth - i - 1) ? '1' : '0';
583 
584  printVal(os, str);
585  }
586 };
587 void
588 VcdTraceFile::addTraceVal(const sc_core::sc_time *v, const std::string &name)
589 {
590  addNewTraceVal<VcdTraceValTime>(v, name);
591 }
592 
593 template <typename T>
594 class VcdTraceValInt : public VcdTraceVal<T>
595 {
596  public:
598 
599  void
600  output(std::ostream &os) override
601  {
602  const int w = this->width();
603  char str[w + 1];
604  str[w] = '\0';
605 
606  const uint64_t val =
607  static_cast<uint64_t>(this->value()) & ::mask(sizeof(T) * 8);
608 
609  if (::mask(w) < val) {
610  for (int i = 0; i < w; i++)
611  str[i] = 'x';
612  } else {
613  for (int i = 0; i < w; i++)
614  str[i] = ::bits(val, w - i - 1) ? '1' : '0';
615  }
616 
617  this->printVal(os, str);
618  }
619 };
620 
621 void
622 VcdTraceFile::addTraceVal(const unsigned char *v, const std::string &name,
623  int width)
624 {
625  addNewTraceVal<VcdTraceValInt<unsigned char>>(v, name, width);
626 }
627 void
628 VcdTraceFile::addTraceVal(const char *v, const std::string &name, int width)
629 {
630  addNewTraceVal<VcdTraceValInt<char>>(v, name, width);
631 }
632 void
633 VcdTraceFile::addTraceVal(const unsigned short *v, const std::string &name,
634  int width)
635 {
636  addNewTraceVal<VcdTraceValInt<unsigned short>>(v, name, width);
637 }
638 void
639 VcdTraceFile::addTraceVal(const short *v, const std::string &name, int width)
640 {
641  addNewTraceVal<VcdTraceValInt<short>>(v, name, width);
642 }
643 void
644 VcdTraceFile::addTraceVal(const unsigned int *v, const std::string &name,
645  int width)
646 {
647  addNewTraceVal<VcdTraceValInt<unsigned int>>(v, name, width);
648 }
649 void
650 VcdTraceFile::addTraceVal(const int *v, const std::string &name, int width)
651 {
652  addNewTraceVal<VcdTraceValInt<int>>(v, name, width);
653 }
654 void
655 VcdTraceFile::addTraceVal(const unsigned long *v, const std::string &name,
656  int width)
657 {
658  addNewTraceVal<VcdTraceValInt<unsigned long>>(v, name, width);
659 }
660 void
661 VcdTraceFile::addTraceVal(const long *v, const std::string &name, int width)
662 {
663  addNewTraceVal<VcdTraceValInt<long>>(v, name, width);
664 }
665 
666 void
667 VcdTraceFile::addTraceVal(const sc_dt::int64 *v, const std::string &name,
668  int width)
669 {
670  addNewTraceVal<VcdTraceValInt<sc_dt::int64>>(v, name, width);
671 }
672 void
673 VcdTraceFile::addTraceVal(const sc_dt::uint64 *v, const std::string &name,
674  int width)
675 {
676  addNewTraceVal<VcdTraceValInt<sc_dt::uint64>>(v, name, width);
677 }
678 
679 void
680 VcdTraceFile::addTraceVal(const unsigned int *v, const std::string &name,
681  const char **literals)
682 {
683  uint64_t count = 0;
684  while (*literals++)
685  count++;
686 
687  int bits = 0;
688  while (count >> bits)
689  bits++;
690 
691  addNewTraceVal<VcdTraceValInt<unsigned int>>(v, name, bits);
692 }
693 
694 void
695 VcdTraceFile::writeComment(const std::string &comment)
696 {
697  stream() << "$comment" << std::endl;
698  stream() << comment << std::endl;
699  stream() << "$end" << std::endl << std::endl;
700 }
701 
702 } // namespace sc_gem5
count
Definition: misc.hh:705
void ccprintf(cp::Print &print)
Definition: cprintf.hh:131
void output(std::ostream &os) override
Definition: vcd.cc:509
Bitfield< 28 > v
const std::string & name()
Definition: trace.cc:54
void writeComment(const std::string &comment) override
Definition: vcd.cc:695
Bitfield< 7 > i
void addTraceVal(const bool *v, const std::string &name) override
Definition: vcd.cc:338
const std::string & vcdName()
Definition: vcd.cc:137
void addValue(const std::string &name, VcdTraceValBase *value)
Definition: vcd.cc:144
double s
These variables equal the number of ticks in the unit of time they&#39;re named after in a double...
Definition: core.cc:52
std::string nextSignalName()
Definition: vcd.cc:206
void trace(bool delta) override
Definition: vcd.cc:284
Bitfield< 17 > os
Definition: misc.hh:805
int64_t int64
Definition: sc_nbdefs.hh:171
void output(std::ostream &os) override
Definition: vcd.cc:331
Bitfield< 63 > val
Definition: misc.hh:771
void vcdName(const std::string &vcd_name)
Definition: vcd.cc:136
void output(const std::string &name, std::ostream &os)
Definition: vcd.cc:159
static sc_time from_value(sc_dt::uint64)
Definition: sc_time.cc:212
Bitfield< 6 > rep
Definition: types.hh:78
std::string _vcdName
Definition: vcd.cc:75
void output(std::ostream &os) override
Definition: vcd.cc:600
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:162
const char * sc_version()
Definition: functions.cc:46
char scLogicToVcdState(char in)
Definition: vcd.cc:95
std::string vcdType() override
Definition: vcd.cc:539
uint64_t Tick
Tick count type.
Definition: types.hh:63
virtual void output(std::ostream &os)=0
std::string vcdType() override
Definition: vcd.cc:565
const char * stripLeadingBits(const char *orig)
Definition: vcd.cc:78
void output(std::ostream &os) override
Definition: vcd.cc:483
void output(std::ostream &os) override
Definition: vcd.cc:575
Scheduler scheduler
Definition: scheduler.cc:491
Bitfield< 0 > w
void output(std::ostream &os) override
Definition: vcd.cc:405
VcdTraceVal(const T *t, const std::string &vcd_name, int width)
Definition: vcd.cc:198
void finalize() override
Definition: vcd.cc:450
uint64_t uint64
Definition: sc_nbdefs.hh:172
void printVal(std::ostream &os, const std::string &rep)
Definition: vcd.cc:117
void finalize() override
Definition: vcd.cc:398
#define SC_REPORT_ERROR(msg_type, msg)
void finalize() override
Definition: vcd.cc:568
Bitfield< 3, 0 > mask
Definition: types.hh:64
void initialize()
Definition: vcd.cc:224
Bitfield< 5 > t
void output(std::ostream &os) override
Definition: vcd.cc:542
std::string vcdType() override
Definition: vcd.cc:480
T bits(T val, int first, int last)
Extract the bitfield from position &#39;first&#39; to &#39;last&#39; (inclusive) from &#39;val&#39; and right justify it...
Definition: bitfield.hh:72
std::string vcdType() override
Definition: vcd.cc:349
virtual std::string vcdType()
Definition: vcd.cc:138
Bitfield< 0 > p
void output(std::ostream &os) override
Definition: vcd.cc:352
void output(std::ostream &os) override
Definition: vcd.cc:375
const std::string to_string(sc_enc enc)
Definition: sc_fxdefs.cc:60
VcdTraceValBase(int width)
Definition: vcd.cc:133
void output(std::ostream &os) override
Definition: vcd.cc:457

Generated on Fri Feb 28 2020 16:27:06 for gem5 by doxygen 1.8.13