ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
VCD.cpp
Go to the documentation of this file.
1 /*
2 
3  @copyright
4 
5  <pre>
6 
7  Copyright 2018 Infineon Technologies AG
8 
9  This file is part of ETISS tool, see <https://github.com/tum-ei-eda/etiss>.
10 
11  The initial version of this software has been created with the funding support by the German Federal
12  Ministry of Education and Research (BMBF) in the project EffektiV under grant 01IS13022.
13 
14  Redistribution and use in source and binary forms, with or without modification, are permitted
15  provided that the following conditions are met:
16 
17  1. Redistributions of source code must retain the above copyright notice, this list of conditions and
18  the following disclaimer.
19 
20  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
21  and the following disclaimer in the documentation and/or other materials provided with the distribution.
22 
23  3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse
24  or promote products derived from this software without specific prior written permission.
25 
26  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
27  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
28  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
29  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  POSSIBILITY OF SUCH DAMAGE.
34 
35  </pre>
36 
37  @author Marc Greim <marc.greim@mytum.de>, Chair of Electronic Design Automation, TUM
38 
39  @version 0.1
40 
41 */
42 
43 #include "etiss/interfaces/VCD.h"
44 
45 namespace etiss
46 {
47 namespace interfaces
48 {
49 
51 static std::string val2str(uint64_t val, unsigned width, uint64_t udef)
52 {
53  if (width == 1)
54  {
55  return (udef & 1) ? "x" : ((val & 1) ? "1" : "0");
56  }
57  else
58  {
59  char *ret = new char[width + 3];
60  ret[0] = 'b';
61  ret[width + 1] = ' ';
62  ret[width + 2] = 0;
63  for (unsigned i = 1; i < width + 1; i++)
64  {
65  ret[width + 1 - i] = (udef & 1) ? 'x' : ((val & 1) ? '1' : '0');
66  val = val >> 1;
67  udef = udef >> 1;
68  }
69  std::string r(ret);
70  delete[] ret;
71  return r;
72  }
73 }
74 
78 static std::string index2str(int index)
79 {
80  std::string out;
81  while (true)
82  {
83  out += static_cast<char>(index % 94) + 33;
84  if (index < 94)
85  break;
86  index -= 94;
87  index /= 94;
88  }
89  return out;
90 }
91 
92 VCD::VCD(const std::string &file, const std::string &comment) : dumpstarted_(false), lasttime_ps(0), file(file)
93 {
94  out_.open(file);
95  valid_ = out_.is_open();
96 
97  if (!valid_)
98  {
99  etiss::log(etiss::WARNING, "Failed to open file for VCD output: " + file);
100  }
101  else
102  {
103  out_ << "$date\n"
104  " \n"
105  "$end\n"
106  "$version\n"
107  " ETISS " ETISS_VERSION_FULL "\n"
108  "$end\n"
109  "$comment\n"
110  << comment
111  << "\n"
112  "$end\n"
113  "$timescale 1ps $end\n";
114  }
115 
116  dumpvar = "$enddefinitions $end\n$dumpvars\n";
117 }
118 
119 VCD::~VCD()
120 {
121  close();
122 }
123 
124 void VCD::close()
125 {
126  if (!valid_)
127  return;
128  valid_ = false;
129  flush();
130  out_.close();
131 }
132 
133 bool VCD::declare(void *variable, const std::string &name, unsigned width, uint64_t initialvalue, uint64_t undefined)
134 {
135  if (!valid_)
136  return false;
137  if (name.size() == 0)
138  {
139  etiss::log(etiss::ERROR, "Cannot call etiss::interfaces::VCD::declare without a name.", *this);
140  return false;
141  }
142  if (dumpstarted_)
143  {
144  etiss::log(etiss::ERROR, "Cannot call etiss::interfaces::VCD::declare after dump started.", *this);
145  return false;
146  }
147  if (sigs_.size() >= (94 + 94 * 94 + 94 * 94 * 94 + 94 * 94 * 94 * 94))
148  {
149  etiss::log(etiss::ERROR, "etiss::interfaces::VCD::declare called for more than supported variables.", *this);
150  return false;
151  }
152  int checked_sig_size = static_cast<int>(sigs_.size());
153  sigs_.emplace_back();
154  Signal &sig = sigs_.back();
155 
156  sig.valid = false;
157  sig.name = name;
158  sig.value = initialvalue;
159  sig.width = width;
160  sig.ident = index2str(checked_sig_size - 1);
161  sig.undefined = undefined;
162 
163  // declare signal
164  {
165  // split on dots and double quotes to get the submodules and enter their scopes
166  std::list<std::string> vec_bd = etiss::split(name, [](const std::string &str, size_t from, size_t &seplen) {
167  size_t f1 = str.find(".", from);
168  size_t f2 = str.find("::", from);
169  seplen = f1 < f2 ? 1 : 2;
170  return f1 < f2 ? f1 : f2;
171  });
172  std::vector<std::string> vec;
173  vec.insert(vec.end(), vec_bd.begin(), vec_bd.end());
174  if (vec.size() == 0)
175  vec.push_back(name);
176  for (size_t i = 1; i < vec.size(); i++)
177  {
178  out_ << "$scope module " << vec[i - 1] << " $end\n";
179  }
180  out_ << "$var wire " << width << " " << sig.ident << " " << vec[vec.size() - 1] << " $end\n";
181  for (size_t i = 1; i < vec.size(); i++)
182  {
183  out_ << "$upscope $end\n";
184  }
185  }
186 
187  dumpvar = dumpvar + val2str(initialvalue, width, undefined) + sig.ident + "\n";
188 
189  ptr2index_.insert(std::make_pair(variable, (checked_sig_size - 1)));
190 
191  out_.flush();
192 
193  return true;
194 }
195 void VCD::update(uint64_t time_ps, void *variable, uint64_t value, uint64_t undefined)
196 {
197  if (!valid_)
198  return;
199  if (time_ps < lasttime_ps)
200  {
201  etiss::log(etiss::ERROR, "etiss::interfaces::VCD::update called with decreased time value");
202  }
203 
204  auto findex = ptr2index_.find(variable);
205  if (findex != ptr2index_.end())
206  {
207  if (time_ps > lasttime_ps)
208  {
209  flush();
210  lasttime_ps = time_ps;
211  }
212  int index = findex->second;
213  Signal &sig = sigs_[index];
214  sig.valid = true;
215  sig.value = value;
216  sig.undefined = undefined;
217  }
218  else
219  {
220  // not a declared vriable. ignore
221  }
222 }
223 void VCD::flush()
224 {
225  if (!valid_)
226  return;
227  dumpstarted_ = true;
228  if (lasttime_ps == 0)
229  {
230  out_ << dumpvar;
231  out_ << "$end\n"; // terminate dumpvars
232  }
233  bool empty = true;
234  for (size_t i = 0; i < sigs_.size(); i++)
235  {
236  if (sigs_[i].valid)
237  {
238  empty = false;
239  break;
240  }
241  }
242  if (empty)
243  return;
244  out_ << "#" << lasttime_ps << "\n";
245  for (size_t i = 0; i < sigs_.size(); i++)
246  {
247  Signal &s = sigs_[i];
248  if (s.valid)
249  {
250  out_ << val2str(s.value, s.width, s.undefined) << s.ident << "\n";
251  s.valid = false;
252  }
253  }
254  // out_.flush();
255 }
256 
257 } // namespace interfaces
258 } // namespace etiss
__device__ __2f16 float bool s
static __inline__ uint64_t
Definition: arm_cde.h:31
#define ETISS_VERSION_FULL
Definition: config.h:67
static std::string index2str(int index)
generated an identifier for the given index
Definition: VCD.cpp:78
static std::string val2str(uint64_t val, unsigned width, uint64_t udef)
TODO efficient implementation.
Definition: VCD.cpp:51
Page Table Entry (PTE) defines the composition of Page Frame Number (PFN) and relavant flags.
Definition: Benchmark.h:53
std::list< std::string > split(const std::string &str, std::function< size_t(const std::string &, size_t, size_t &)> findsplit)
Definition: Misc.cpp:91
@ WARNING
Definition: Misc.h:128
@ ERROR
Definition: Misc.h:127
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition: Misc.cpp:125
#define false
Definition: stdbool.h:17