Remove this unnecessary dependency. Fixed all incorrect includes of sim/core.hh. Change-Id: I3ae282dbaeb45fbf4630237a3ab9b1a593ffbe0c Signed-off-by: Daniel R. Carvalho <odanrc@yahoo.com.br> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/43592 Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com> Tested-by: kokoro <noreply+kokoro@google.com>
704 lines
17 KiB
C++
704 lines
17 KiB
C++
/*
|
|
* Copyright 2018 Google, Inc.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met: redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer;
|
|
* redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution;
|
|
* neither the name of the copyright holders nor the names of its
|
|
* contributors may be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "systemc/utils/vcd.hh"
|
|
|
|
#include <ctime>
|
|
#include <iomanip>
|
|
|
|
#include "base/bitfield.hh"
|
|
#include "base/cprintf.hh"
|
|
#include "sim/core.hh"
|
|
#include "systemc/core/scheduler.hh"
|
|
#include "systemc/ext/core/sc_event.hh"
|
|
#include "systemc/ext/core/sc_main.hh"
|
|
#include "systemc/ext/core/sc_time.hh"
|
|
#include "systemc/ext/dt/bit/sc_bv_base.hh"
|
|
#include "systemc/ext/dt/bit/sc_logic.hh"
|
|
#include "systemc/ext/dt/bit/sc_lv_base.hh"
|
|
#include "systemc/ext/dt/fx/sc_fxnum.hh"
|
|
#include "systemc/ext/dt/fx/sc_fxval.hh"
|
|
#include "systemc/ext/dt/int/sc_int_base.hh"
|
|
#include "systemc/ext/dt/int/sc_signed.hh"
|
|
#include "systemc/ext/dt/int/sc_uint_base.hh"
|
|
#include "systemc/ext/dt/int/sc_unsigned.hh"
|
|
#include "systemc/ext/utils/functions.hh"
|
|
|
|
namespace sc_gem5
|
|
{
|
|
|
|
namespace
|
|
{
|
|
|
|
std::string
|
|
cleanName(std::string name)
|
|
{
|
|
for (int i = 0; i < name.length(); i++) {
|
|
if (name[i] == '[')
|
|
name[i] = '(';
|
|
else if (name[i] == ']')
|
|
name[i] = ')';
|
|
}
|
|
return name;
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
class VcdTraceValBase : public TraceValBase
|
|
{
|
|
protected:
|
|
std::string _vcdName;
|
|
|
|
const char *
|
|
stripLeadingBits(const char *orig)
|
|
{
|
|
const char first = orig[0];
|
|
|
|
if (first != 'z' && first != 'x' && first != '0')
|
|
return orig;
|
|
|
|
const char *res = orig;
|
|
while (*++res == first) {}
|
|
|
|
if (first != '0' || *res != '1')
|
|
res--;
|
|
|
|
return res;
|
|
}
|
|
|
|
char
|
|
scLogicToVcdState(char in)
|
|
{
|
|
switch (in) {
|
|
case 'U':
|
|
case 'X':
|
|
case 'W':
|
|
case 'D':
|
|
return 'x';
|
|
case '0':
|
|
case 'L':
|
|
return '0';
|
|
case '1':
|
|
case 'H':
|
|
return '1';
|
|
case 'Z':
|
|
return 'z';
|
|
default:
|
|
return '?';
|
|
}
|
|
}
|
|
|
|
void
|
|
printVal(std::ostream &os, const std::string &rep)
|
|
{
|
|
switch (width()) {
|
|
case 0:
|
|
return;
|
|
case 1:
|
|
os << rep << vcdName() << std::endl;;
|
|
return;
|
|
default:
|
|
os << "b" << stripLeadingBits(rep.c_str()) << " " <<
|
|
vcdName() << std::endl;
|
|
return;
|
|
}
|
|
}
|
|
|
|
public:
|
|
VcdTraceValBase(int width) : TraceValBase(width) {}
|
|
~VcdTraceValBase() {}
|
|
|
|
void vcdName(const std::string &vcd_name) { _vcdName = vcd_name; }
|
|
const std::string &vcdName() { return _vcdName; }
|
|
virtual std::string vcdType() { return "wire"; }
|
|
|
|
virtual void output(std::ostream &os) = 0;
|
|
};
|
|
|
|
void
|
|
VcdTraceScope::addValue(const std::string &name, VcdTraceValBase *value)
|
|
{
|
|
size_t pos = name.find_first_of('.');
|
|
if (pos == std::string::npos) {
|
|
values.emplace_back(name, value);
|
|
} else {
|
|
std::string sname = name.substr(0, pos);
|
|
auto it = scopes.find(sname);
|
|
if (it == scopes.end())
|
|
it = scopes.emplace(sname, new VcdTraceScope).first;
|
|
it->second->addValue(name.substr(pos + 1), value);
|
|
}
|
|
}
|
|
|
|
void
|
|
VcdTraceScope::output(const std::string &name, std::ostream &os)
|
|
{
|
|
os << "$scope module " << name << " $end" << std::endl;
|
|
|
|
for (auto &p: values) {
|
|
const std::string &name = p.first;
|
|
VcdTraceValBase *value = p.second;
|
|
|
|
int w = value->width();
|
|
if (w <= 0) {
|
|
std::string msg = gem5::csprintf("'%s' has 0 bits", name);
|
|
// The typo in this error message is intentional to match the
|
|
// Accellera output.
|
|
SC_REPORT_ERROR("(E710) object cannot not be traced", msg.c_str());
|
|
return;
|
|
}
|
|
|
|
std::string clean_name = cleanName(name);
|
|
if (w == 1) {
|
|
gem5::ccprintf(os, "$var %s % 3d %s %s $end\n",
|
|
value->vcdType(), w, value->vcdName(), clean_name);
|
|
} else {
|
|
gem5::ccprintf(os, "$var %s % 3d %s %s [%d:0] $end\n",
|
|
value->vcdType(), w, value->vcdName(), clean_name, w - 1);
|
|
}
|
|
}
|
|
|
|
for (auto &p: scopes)
|
|
p.second->output(p.first, os);
|
|
|
|
os << "$upscope $end" << std::endl;
|
|
}
|
|
|
|
template <typename T>
|
|
class VcdTraceVal : public TraceVal<T, VcdTraceValBase>
|
|
{
|
|
public:
|
|
typedef T TracedType;
|
|
|
|
VcdTraceVal(const T* t, const std::string &vcd_name, int width) :
|
|
TraceVal<T, VcdTraceValBase>(t, width)
|
|
{
|
|
this->vcdName(vcd_name);
|
|
}
|
|
};
|
|
|
|
std::string
|
|
VcdTraceFile::nextSignalName()
|
|
{
|
|
std::string name(_nextName);
|
|
|
|
bool carry = false;
|
|
int pos = NextNameChars - 1;
|
|
do {
|
|
carry = (_nextName[pos] == 'z');
|
|
if (carry)
|
|
_nextName[pos--] = 'a';
|
|
else
|
|
_nextName[pos--]++;
|
|
} while (carry && pos >= 0);
|
|
|
|
return name;
|
|
}
|
|
|
|
void
|
|
VcdTraceFile::initialize()
|
|
{
|
|
finalizeTime();
|
|
|
|
// Date.
|
|
stream() << "$date" << std::endl;
|
|
time_t long_time;
|
|
time(&long_time);
|
|
struct tm *p_tm = localtime(&long_time);
|
|
stream() << std::put_time(p_tm, " %b %d, %Y %H:%M:%S\n");
|
|
stream() << "$end" << std::endl << std::endl;
|
|
|
|
// Version.
|
|
stream() << "$version" << std::endl;
|
|
stream() << " " << ::sc_core::sc_version() << std::endl;
|
|
stream() << "$end" << std::endl << std::endl;
|
|
|
|
// Timescale.
|
|
stream() << "$timescale" << std::endl;
|
|
stream() << " " << ::sc_core::sc_time::from_value(timeUnitTicks) <<
|
|
std::endl;
|
|
stream() << "$end" << std::endl << std::endl;
|
|
|
|
for (auto tv: traceVals)
|
|
tv->finalize();
|
|
|
|
topScope.output("SystemC", stream());
|
|
|
|
stream() << "$enddefinitions $end" << std::endl << std::endl;
|
|
|
|
gem5::Tick now = scheduler.getCurTick();
|
|
|
|
std::string timedump_comment =
|
|
gem5::csprintf("All initial values are dumped below at time "
|
|
"%g sec = %g timescale units.",
|
|
static_cast<double>(now) / gem5::sim_clock::as_float::s,
|
|
static_cast<double>(now / timeUnitTicks));
|
|
writeComment(timedump_comment);
|
|
|
|
lastPrintedTime = now / timeUnitTicks;
|
|
|
|
stream() << "$dumpvars" << std::endl;
|
|
for (auto tv: traceVals)
|
|
tv->output(stream());
|
|
stream() << "$end" << std::endl << std::endl;
|
|
|
|
initialized = true;
|
|
}
|
|
|
|
VcdTraceFile::~VcdTraceFile()
|
|
{
|
|
for (auto tv: traceVals)
|
|
delete tv;
|
|
traceVals.clear();
|
|
|
|
if (timeUnitTicks) {
|
|
gem5::ccprintf(stream(), "#%u\n",
|
|
scheduler.getCurTick() / timeUnitTicks);
|
|
}
|
|
}
|
|
|
|
void
|
|
VcdTraceFile::trace(bool delta)
|
|
{
|
|
if (!delta)
|
|
deltasAtNow = 0;
|
|
|
|
uint64_t deltaOffset = deltasAtNow;
|
|
|
|
if (delta)
|
|
deltaOffset = deltasAtNow++;
|
|
|
|
if (_traceDeltas != delta)
|
|
return;
|
|
|
|
if (!initialized) {
|
|
initialize();
|
|
return;
|
|
}
|
|
|
|
gem5::Tick now = scheduler.getCurTick() / timeUnitTicks + deltaOffset;
|
|
|
|
if (now <= lastPrintedTime) {
|
|
// TODO warn about reversed time?
|
|
return;
|
|
}
|
|
|
|
bool time_printed = false;
|
|
for (auto tv: traceVals) {
|
|
if (tv->check()) {
|
|
if (!time_printed) {
|
|
lastPrintedTime = now;
|
|
gem5::ccprintf(stream(), "#%u\n", now);
|
|
time_printed = true;
|
|
}
|
|
|
|
tv->output(stream());
|
|
}
|
|
}
|
|
if (time_printed)
|
|
stream() << std::endl;
|
|
}
|
|
|
|
class VcdTraceValBool : public VcdTraceVal<bool>
|
|
{
|
|
public:
|
|
using VcdTraceVal<bool>::VcdTraceVal;
|
|
|
|
void
|
|
output(std::ostream &os) override
|
|
{
|
|
printVal(os, this->value() ? "1" : "0");
|
|
}
|
|
};
|
|
|
|
void
|
|
VcdTraceFile::addTraceVal(const bool *v, const std::string &name)
|
|
{
|
|
addNewTraceVal<VcdTraceValBool>(v, name);
|
|
}
|
|
|
|
template <typename T>
|
|
class VcdTraceValFloat : public VcdTraceVal<T>
|
|
{
|
|
public:
|
|
using VcdTraceVal<T>::VcdTraceVal;
|
|
|
|
std::string vcdType() override { return "real"; }
|
|
|
|
void
|
|
output(std::ostream &os) override
|
|
{
|
|
gem5::ccprintf(os, "r%.16g %s\n", this->value(), this->vcdName());
|
|
}
|
|
};
|
|
|
|
void
|
|
VcdTraceFile::addTraceVal(const float *v, const std::string &name)
|
|
{
|
|
addNewTraceVal<VcdTraceValFloat<float>>(v, name);
|
|
}
|
|
void
|
|
VcdTraceFile::addTraceVal(const double *v, const std::string &name)
|
|
{
|
|
addNewTraceVal<VcdTraceValFloat<double>>(v, name);
|
|
}
|
|
|
|
class VcdTraceValScLogic : public VcdTraceVal<sc_dt::sc_logic>
|
|
{
|
|
public:
|
|
using VcdTraceVal<sc_dt::sc_logic>::VcdTraceVal;
|
|
|
|
void
|
|
output(std::ostream &os) override
|
|
{
|
|
char str[2] = {
|
|
scLogicToVcdState(value().to_char()),
|
|
'\0'
|
|
};
|
|
printVal(os, str);
|
|
}
|
|
};
|
|
|
|
void
|
|
VcdTraceFile::addTraceVal(const sc_dt::sc_logic *v, const std::string &name)
|
|
{
|
|
addNewTraceVal<VcdTraceValScLogic>(v, name);
|
|
}
|
|
|
|
template <typename T>
|
|
class VcdTraceValFinite : public VcdTraceVal<T>
|
|
{
|
|
public:
|
|
using VcdTraceVal<T>::VcdTraceVal;
|
|
|
|
void
|
|
finalize() override
|
|
{
|
|
VcdTraceVal<T>::finalize();
|
|
this->_width = this->value().length();
|
|
}
|
|
|
|
void
|
|
output(std::ostream &os) override
|
|
{
|
|
std::string str;
|
|
const int w = this->width();
|
|
|
|
str.reserve(w);
|
|
for (int i = w - 1; i >= 0; i--)
|
|
str += this->value()[i].to_bool() ? '1' : '0';
|
|
|
|
this->printVal(os, str);
|
|
}
|
|
};
|
|
|
|
void
|
|
VcdTraceFile::addTraceVal(const sc_dt::sc_int_base *v,
|
|
const std::string &name)
|
|
{
|
|
addNewTraceVal<VcdTraceValFinite<sc_dt::sc_int_base>>(v, name);
|
|
}
|
|
void
|
|
VcdTraceFile::addTraceVal(const sc_dt::sc_uint_base *v,
|
|
const std::string &name)
|
|
{
|
|
addNewTraceVal<VcdTraceValFinite<sc_dt::sc_uint_base>>(v, name);
|
|
}
|
|
|
|
void
|
|
VcdTraceFile::addTraceVal(const sc_dt::sc_signed *v, const std::string &name)
|
|
{
|
|
addNewTraceVal<VcdTraceValFinite<sc_dt::sc_signed>>(v, name);
|
|
}
|
|
void
|
|
VcdTraceFile::addTraceVal(const sc_dt::sc_unsigned *v,
|
|
const std::string &name)
|
|
{
|
|
addNewTraceVal<VcdTraceValFinite<sc_dt::sc_unsigned>>(v, name);
|
|
}
|
|
|
|
template <typename T>
|
|
class VcdTraceValLogic : public VcdTraceVal<T>
|
|
{
|
|
public:
|
|
using VcdTraceVal<T>::VcdTraceVal;
|
|
|
|
void
|
|
finalize() override
|
|
{
|
|
VcdTraceVal<T>::finalize();
|
|
this->_width = this->value().length();
|
|
}
|
|
|
|
void
|
|
output(std::ostream &os) override
|
|
{
|
|
this->printVal(os, this->value().to_string());
|
|
}
|
|
};
|
|
|
|
void
|
|
VcdTraceFile::addTraceVal(const sc_dt::sc_bv_base *v, const std::string &name)
|
|
{
|
|
addNewTraceVal<VcdTraceValLogic<::sc_dt::sc_bv_base>>(v, name);
|
|
}
|
|
void
|
|
VcdTraceFile::addTraceVal(const sc_dt::sc_lv_base *v, const std::string &name)
|
|
{
|
|
addNewTraceVal<VcdTraceValLogic<::sc_dt::sc_lv_base>>(v, name);
|
|
}
|
|
|
|
template <typename T>
|
|
class VcdTraceValFxval : public VcdTraceVal<T>
|
|
{
|
|
public:
|
|
using VcdTraceVal<T>::VcdTraceVal;
|
|
|
|
std::string vcdType() override { return "real"; }
|
|
|
|
void
|
|
output(std::ostream &os) override
|
|
{
|
|
gem5::ccprintf(os, "r%.16g %s\n",
|
|
this->value().to_double(), this->vcdName());
|
|
}
|
|
};
|
|
|
|
void
|
|
VcdTraceFile::addTraceVal(const sc_dt::sc_fxval *v, const std::string &name)
|
|
{
|
|
addNewTraceVal<VcdTraceValFxval<sc_dt::sc_fxval>>(v, name);
|
|
}
|
|
void
|
|
VcdTraceFile::addTraceVal(const sc_dt::sc_fxval_fast *v,
|
|
const std::string &name)
|
|
{
|
|
addNewTraceVal<VcdTraceValFxval<sc_dt::sc_fxval_fast>>(v, name);
|
|
}
|
|
|
|
template <typename T>
|
|
class VcdTraceValFxnum : public VcdTraceVal<T>
|
|
{
|
|
public:
|
|
using VcdTraceVal<T>::VcdTraceVal;
|
|
|
|
void
|
|
output(std::ostream &os) override
|
|
{
|
|
std::string str;
|
|
const int w = this->width();
|
|
|
|
str.reserve(w);
|
|
for (int i = w - 1; i >= 0; i--)
|
|
str += this->value()[i] ? '1' : '0';
|
|
|
|
this->printVal(os, str);
|
|
}
|
|
};
|
|
|
|
void
|
|
VcdTraceFile::addTraceVal(const sc_dt::sc_fxnum *v, const std::string &name)
|
|
{
|
|
addNewTraceVal<VcdTraceValFxnum<::sc_dt::sc_fxnum>>(v, name);
|
|
}
|
|
void
|
|
VcdTraceFile::addTraceVal(const sc_dt::sc_fxnum_fast *v,
|
|
const std::string &name)
|
|
{
|
|
addNewTraceVal<VcdTraceValFxnum<::sc_dt::sc_fxnum_fast>>(v, name);
|
|
}
|
|
|
|
class VcdTraceValEvent : public VcdTraceVal<::sc_core::sc_event>
|
|
{
|
|
public:
|
|
using VcdTraceVal<::sc_core::sc_event>::VcdTraceVal;
|
|
|
|
std::string vcdType() override { return "event"; }
|
|
|
|
void
|
|
output(std::ostream &os) override
|
|
{
|
|
if (value())
|
|
printVal(os, "1");
|
|
else
|
|
os << std::endl;
|
|
}
|
|
};
|
|
|
|
void
|
|
VcdTraceFile::addTraceVal(const sc_core::sc_event *v, const std::string &name)
|
|
{
|
|
addNewTraceVal<VcdTraceValEvent>(v, name);
|
|
}
|
|
|
|
class VcdTraceValTime : public VcdTraceVal<::sc_core::sc_time>
|
|
{
|
|
private:
|
|
static const int TimeWidth = 64;
|
|
|
|
public:
|
|
using VcdTraceVal<::sc_core::sc_time>::VcdTraceVal;
|
|
|
|
std::string vcdType() override { return "time"; }
|
|
|
|
void
|
|
finalize() override
|
|
{
|
|
VcdTraceVal<::sc_core::sc_time>::finalize();
|
|
_width = TimeWidth;
|
|
}
|
|
|
|
void
|
|
output(std::ostream &os) override
|
|
{
|
|
char str[TimeWidth + 1];
|
|
str[TimeWidth] = '\0';
|
|
|
|
const uint64_t val = value().value();
|
|
for (int i = 0; i < TimeWidth; i++)
|
|
str[i] = gem5::bits(val, TimeWidth - i - 1) ? '1' : '0';
|
|
|
|
printVal(os, str);
|
|
}
|
|
};
|
|
void
|
|
VcdTraceFile::addTraceVal(const sc_core::sc_time *v, const std::string &name)
|
|
{
|
|
addNewTraceVal<VcdTraceValTime>(v, name);
|
|
}
|
|
|
|
template <typename T>
|
|
class VcdTraceValInt : public VcdTraceVal<T>
|
|
{
|
|
public:
|
|
using VcdTraceVal<T>::VcdTraceVal;
|
|
|
|
void
|
|
output(std::ostream &os) override
|
|
{
|
|
const int w = this->width();
|
|
char str[w + 1];
|
|
str[w] = '\0';
|
|
|
|
const uint64_t val =
|
|
static_cast<uint64_t>(this->value()) & gem5::mask(sizeof(T) * 8);
|
|
|
|
if (gem5::mask(w) < val) {
|
|
for (int i = 0; i < w; i++)
|
|
str[i] = 'x';
|
|
} else {
|
|
for (int i = 0; i < w; i++)
|
|
str[i] = gem5::bits(val, w - i - 1) ? '1' : '0';
|
|
}
|
|
|
|
this->printVal(os, str);
|
|
}
|
|
};
|
|
|
|
void
|
|
VcdTraceFile::addTraceVal(const unsigned char *v, const std::string &name,
|
|
int width)
|
|
{
|
|
addNewTraceVal<VcdTraceValInt<unsigned char>>(v, name, width);
|
|
}
|
|
void
|
|
VcdTraceFile::addTraceVal(const char *v, const std::string &name, int width)
|
|
{
|
|
addNewTraceVal<VcdTraceValInt<char>>(v, name, width);
|
|
}
|
|
void
|
|
VcdTraceFile::addTraceVal(const unsigned short *v, const std::string &name,
|
|
int width)
|
|
{
|
|
addNewTraceVal<VcdTraceValInt<unsigned short>>(v, name, width);
|
|
}
|
|
void
|
|
VcdTraceFile::addTraceVal(const short *v, const std::string &name, int width)
|
|
{
|
|
addNewTraceVal<VcdTraceValInt<short>>(v, name, width);
|
|
}
|
|
void
|
|
VcdTraceFile::addTraceVal(const unsigned int *v, const std::string &name,
|
|
int width)
|
|
{
|
|
addNewTraceVal<VcdTraceValInt<unsigned int>>(v, name, width);
|
|
}
|
|
void
|
|
VcdTraceFile::addTraceVal(const int *v, const std::string &name, int width)
|
|
{
|
|
addNewTraceVal<VcdTraceValInt<int>>(v, name, width);
|
|
}
|
|
void
|
|
VcdTraceFile::addTraceVal(const unsigned long *v, const std::string &name,
|
|
int width)
|
|
{
|
|
addNewTraceVal<VcdTraceValInt<unsigned long>>(v, name, width);
|
|
}
|
|
void
|
|
VcdTraceFile::addTraceVal(const long *v, const std::string &name, int width)
|
|
{
|
|
addNewTraceVal<VcdTraceValInt<long>>(v, name, width);
|
|
}
|
|
|
|
void
|
|
VcdTraceFile::addTraceVal(const sc_dt::int64 *v, const std::string &name,
|
|
int width)
|
|
{
|
|
addNewTraceVal<VcdTraceValInt<sc_dt::int64>>(v, name, width);
|
|
}
|
|
void
|
|
VcdTraceFile::addTraceVal(const sc_dt::uint64 *v, const std::string &name,
|
|
int width)
|
|
{
|
|
addNewTraceVal<VcdTraceValInt<sc_dt::uint64>>(v, name, width);
|
|
}
|
|
|
|
void
|
|
VcdTraceFile::addTraceVal(const unsigned int *v, const std::string &name,
|
|
const char **literals)
|
|
{
|
|
uint64_t count = 0;
|
|
while (*literals++)
|
|
count++;
|
|
|
|
int bits = 0;
|
|
while (count >> bits)
|
|
bits++;
|
|
|
|
addNewTraceVal<VcdTraceValInt<unsigned int>>(v, name, bits);
|
|
}
|
|
|
|
void
|
|
VcdTraceFile::writeComment(const std::string &comment)
|
|
{
|
|
stream() << "$comment" << std::endl;
|
|
stream() << comment << std::endl;
|
|
stream() << "$end" << std::endl << std::endl;
|
|
}
|
|
|
|
} // namespace sc_gem5
|