ETISS 0.11.2
ExtendableTranslatingInstructionSetSimulator(version0.11.2)
Loading...
Searching...
No Matches
VCD.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2//
3// This file is part of ETISS. It is licensed under the BSD 3-Clause License; you may not use this file except in
4// compliance with the License. You should have received a copy of the license along with this project. If not, see the
5// LICENSE file.
6
8
9namespace etiss
10{
11namespace interfaces
12{
13
15static std::string val2str(uint64_t val, unsigned width, uint64_t udef)
16{
17 if (width == 1)
18 {
19 return (udef & 1) ? "x" : ((val & 1) ? "1" : "0");
20 }
21 else
22 {
23 char *ret = new char[width + 3];
24 ret[0] = 'b';
25 ret[width + 1] = ' ';
26 ret[width + 2] = 0;
27 for (unsigned i = 1; i < width + 1; i++)
28 {
29 ret[width + 1 - i] = (udef & 1) ? 'x' : ((val & 1) ? '1' : '0');
30 val = val >> 1;
31 udef = udef >> 1;
32 }
33 std::string r(ret);
34 delete[] ret;
35 return r;
36 }
37}
38
42static std::string index2str(int index)
43{
44 std::string out;
45 while (true)
46 {
47 out += static_cast<char>(index % 94) + 33;
48 if (index < 94)
49 break;
50 index -= 94;
51 index /= 94;
52 }
53 return out;
54}
55
56VCD::VCD(const std::string &file, const std::string &comment) : dumpstarted_(false), lasttime_ps(0), file(file)
57{
58 out_.open(file);
59 valid_ = out_.is_open();
60
61 if (!valid_)
62 {
63 etiss::log(etiss::WARNING, "Failed to open file for VCD output: " + file);
64 }
65 else
66 {
67 out_ << "$date\n"
68 " \n"
69 "$end\n"
70 "$version\n"
71 " ETISS " ETISS_VERSION_FULL "\n"
72 "$end\n"
73 "$comment\n"
74 << comment
75 << "\n"
76 "$end\n"
77 "$timescale 1ps $end\n";
78 }
79
80 dumpvar = "$enddefinitions $end\n$dumpvars\n";
81}
82
83VCD::~VCD()
84{
85 close();
86}
87
88void VCD::close()
89{
90 if (!valid_)
91 return;
92 valid_ = false;
93 flush();
94 out_.close();
95}
96
97bool VCD::declare(void *variable, const std::string &name, unsigned width, uint64_t initialvalue, uint64_t undefined)
98{
99 if (!valid_)
100 return false;
101 if (name.size() == 0)
102 {
103 etiss::log(etiss::ERROR, "Cannot call etiss::interfaces::VCD::declare without a name.", *this);
104 return false;
105 }
106 if (dumpstarted_)
107 {
108 etiss::log(etiss::ERROR, "Cannot call etiss::interfaces::VCD::declare after dump started.", *this);
109 return false;
110 }
111 if (sigs_.size() >= (94 + 94 * 94 + 94 * 94 * 94 + 94 * 94 * 94 * 94))
112 {
113 etiss::log(etiss::ERROR, "etiss::interfaces::VCD::declare called for more than supported variables.", *this);
114 return false;
115 }
116 int checked_sig_size = static_cast<int>(sigs_.size());
117 sigs_.emplace_back();
118 Signal &sig = sigs_.back();
119
120 sig.valid = false;
121 sig.name = name;
122 sig.value = initialvalue;
123 sig.width = width;
124 sig.ident = index2str(checked_sig_size - 1);
125 sig.undefined = undefined;
126
127 // declare signal
128 {
129 // split on dots and double quotes to get the submodules and enter their scopes
130 std::list<std::string> vec_bd = etiss::split(name,
131 [](const std::string &str, size_t from, size_t &seplen)
132 {
133 size_t f1 = str.find(".", from);
134 size_t f2 = str.find("::", from);
135 seplen = f1 < f2 ? 1 : 2;
136 return f1 < f2 ? f1 : f2;
137 });
138 std::vector<std::string> vec;
139 vec.insert(vec.end(), vec_bd.begin(), vec_bd.end());
140 if (vec.size() == 0)
141 vec.push_back(name);
142 for (size_t i = 1; i < vec.size(); i++)
143 {
144 out_ << "$scope module " << vec[i - 1] << " $end\n";
145 }
146 out_ << "$var wire " << width << " " << sig.ident << " " << vec[vec.size() - 1] << " $end\n";
147 for (size_t i = 1; i < vec.size(); i++)
148 {
149 out_ << "$upscope $end\n";
150 }
151 }
152
153 dumpvar = dumpvar + val2str(initialvalue, width, undefined) + sig.ident + "\n";
154
155 ptr2index_.insert(std::make_pair(variable, (checked_sig_size - 1)));
156
157 out_.flush();
158
159 return true;
160}
161void VCD::update(uint64_t time_ps, void *variable, uint64_t value, uint64_t undefined)
162{
163 if (!valid_)
164 return;
165 if (time_ps < lasttime_ps)
166 {
167 etiss::log(etiss::ERROR, "etiss::interfaces::VCD::update called with decreased time value");
168 }
169
170 auto findex = ptr2index_.find(variable);
171 if (findex != ptr2index_.end())
172 {
173 if (time_ps > lasttime_ps)
174 {
175 flush();
176 lasttime_ps = time_ps;
177 }
178 int index = findex->second;
179 Signal &sig = sigs_[index];
180 sig.valid = true;
181 sig.value = value;
182 sig.undefined = undefined;
183 }
184 else
185 {
186 // not a declared vriable. ignore
187 }
188}
189void VCD::flush()
190{
191 if (!valid_)
192 return;
193 dumpstarted_ = true;
194 if (lasttime_ps == 0)
195 {
196 out_ << dumpvar;
197 out_ << "$end\n"; // terminate dumpvars
198 }
199 bool empty = true;
200 for (size_t i = 0; i < sigs_.size(); i++)
201 {
202 if (sigs_[i].valid)
203 {
204 empty = false;
205 break;
206 }
207 }
208 if (empty)
209 return;
210 out_ << "#" << lasttime_ps << "\n";
211 for (size_t i = 0; i < sigs_.size(); i++)
212 {
213 Signal &s = sigs_[i];
214 if (s.valid)
215 {
216 out_ << val2str(s.value, s.width, s.undefined) << s.ident << "\n";
217 s.valid = false;
218 }
219 }
220 // out_.flush();
221}
222
223} // namespace interfaces
224} // namespace etiss
__device__ __2f16 float bool s
static __inline__ uint64_t
Definition arm_cde.h:31
#define ETISS_VERSION_FULL
Definition config.h:29
static std::string index2str(int index)
generated an identifier for the given index
Definition VCD.cpp:42
static std::string val2str(uint64_t val, unsigned width, uint64_t udef)
TODO efficient implementation.
Definition VCD.cpp:15
forwards: include/jit/*
Definition Benchmark.h:17
std::list< std::string > split(const std::string &str, std::function< size_t(const std::string &, size_t, size_t &)> findsplit)
Definition Misc.cpp:54
@ WARNING
Definition Misc.h:86
@ ERROR
Definition Misc.h:85
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition Misc.cpp:94
#define false
Definition stdbool.h:17