forked from github/verilator
Output checking
This commit is contained in:
parent
4952fd5203
commit
505949ec54
@ -23,6 +23,7 @@
|
||||
//=========================================================================
|
||||
|
||||
#include "verilated_replay.h"
|
||||
#include <cstring>
|
||||
|
||||
// TODO -- collapse into constructor?
|
||||
int VerilatedReplay::init() {
|
||||
@ -42,18 +43,35 @@ int VerilatedReplay::init() {
|
||||
|
||||
for (VarMap::iterator it = m_inputs.begin(); it != m_inputs.end();
|
||||
++it) {
|
||||
VL_PRINTF("%s = %d\n", it->second.fullName.c_str(), it->first);
|
||||
VL_PRINTF("input %s = %d\n", it->second.fullName.c_str(), it->first);
|
||||
fstReaderSetFacProcessMask(m_fstp, it->first);
|
||||
// TODO -- double check the size hasn't changed or just defer looking at size until here
|
||||
m_inputHandles[it->first] = FstSignal(it->second.hier.u.var.length,
|
||||
m_inputNames[it->second.fullName].signal);
|
||||
}
|
||||
|
||||
for (VarMap::iterator it = m_outputs.begin(); it != m_outputs.end();
|
||||
++it) {
|
||||
VL_PRINTF("output %s = %d\n", it->second.fullName.c_str(), it->first);
|
||||
fstReaderSetFacProcessMask(m_fstp, it->first);
|
||||
size_t bits = it->second.hier.u.var.length;
|
||||
size_t bytes = (bits + 7) / 8;
|
||||
vluint8_t* buffer = new vluint8_t [bytes];
|
||||
// TODO -- double check the size hasn't changed or just defer looking at size until here
|
||||
m_outputHandles[it->first] = FstSignal(bits, m_outputNames[it->second.fullName].signal,
|
||||
buffer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VerilatedReplay::~VerilatedReplay() {
|
||||
fstReaderClose(m_fstp);
|
||||
|
||||
for (SignalHandleMap::iterator it = m_outputHandles.begin(); it != m_outputHandles.end(); ++it) {
|
||||
delete [] it->second.expected;
|
||||
}
|
||||
|
||||
#if VM_TRACE
|
||||
if (m_tfp) m_tfp->close();
|
||||
#endif
|
||||
@ -100,21 +118,39 @@ void VerilatedReplay::fstCb(uint64_t time, fstHandle facidx,
|
||||
// TODO -- remove
|
||||
VL_PRINTF("%lu %u %s\n", time, facidx, valuep);
|
||||
|
||||
// TODO -- is len always right, or should we use strlen() or something?
|
||||
// TODO -- handle values other than 0/1, what can show up here?
|
||||
vluint8_t* signal = m_inputHandles[facidx].signal;
|
||||
if (m_outputHandles.empty() || m_inputHandles.find(facidx) != m_inputHandles.end()) {
|
||||
handleInput(facidx, valuep, len);
|
||||
} else {
|
||||
handleOutput(facidx, valuep, len);
|
||||
}
|
||||
}
|
||||
|
||||
void VerilatedReplay::copyValue(unsigned char* to, const unsigned char* valuep, uint32_t len) {
|
||||
vluint8_t byte = 0;
|
||||
for (size_t bit = 0; bit < len; ++bit) {
|
||||
char value = valuep[len - 1 - bit];
|
||||
if (value == '1') byte |= 1 << (bit % 8);
|
||||
if ((bit + 1) % 8 == 0 || bit == len - 1) {
|
||||
*signal = byte;
|
||||
++signal;
|
||||
*to = byte;
|
||||
++to;
|
||||
byte = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VerilatedReplay::handleInput(fstHandle facidx, const unsigned char* valuep, uint32_t len) {
|
||||
// TODO -- is len always right, or should we use strlen() or something?
|
||||
// TODO -- handle values other than 0/1, what can show up here?
|
||||
vluint8_t* signal = m_inputHandles[facidx].signal;
|
||||
copyValue(signal, valuep, len);
|
||||
}
|
||||
|
||||
void VerilatedReplay::handleOutput(fstHandle facidx, const unsigned char* valuep, uint32_t len) {
|
||||
FstSignal& fstSignal = m_outputHandles[facidx];
|
||||
size_t bytes = (len + 7) / 8;
|
||||
copyValue(fstSignal.expected, valuep, len);
|
||||
}
|
||||
|
||||
void VerilatedReplay::fstCallbackVarlen(void* userDatap, uint64_t time, fstHandle facidx,
|
||||
const unsigned char* valuep, uint32_t len) {
|
||||
reinterpret_cast<VerilatedReplay*>(userDatap)->fstCb(time, facidx, valuep, len);
|
||||
@ -134,6 +170,18 @@ void VerilatedReplay::fstCallback(void* userDatap, uint64_t time, fstHandle faci
|
||||
fstCallbackVarlen(userDatap, time, facidx, valuep, len);
|
||||
}
|
||||
|
||||
void VerilatedReplay::outputCheck() {
|
||||
for (SignalHandleMap::iterator it = m_outputHandles.begin(); it != m_outputHandles.end(); ++it) {
|
||||
size_t bytes = (it->second.bits + 7) / 8;
|
||||
if (std::memcmp(it->second.expected, it->second.signal, bytes)) {
|
||||
fstHandle facidx = it->first;
|
||||
// TODO -- timescale, actually print out values with Verilator runtime, etc.
|
||||
VL_PRINTF("Miscompare: %s @ %ld\n", m_outputs[facidx].fullName.c_str(),
|
||||
m_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VerilatedReplay::createMod() {
|
||||
// TODO -- maybe get rid of the need for VM_PREFIX by generating these things
|
||||
m_modp = new VM_PREFIX;
|
||||
@ -150,6 +198,7 @@ void VerilatedReplay::createMod() {
|
||||
void VerilatedReplay::eval() {
|
||||
// TODO -- make eval, trace and final virtual methods of VerilatedModule?
|
||||
m_modp->eval();
|
||||
outputCheck();
|
||||
}
|
||||
|
||||
void VerilatedReplay::trace() {
|
||||
|
@ -42,9 +42,12 @@ private:
|
||||
struct FstSignal {
|
||||
size_t bits;
|
||||
vluint8_t* signal;
|
||||
vluint8_t* expected;
|
||||
FstSignal() {}
|
||||
FstSignal(size_t _bits, vluint8_t* _signal):
|
||||
bits(_bits), signal(_signal) { }
|
||||
bits(_bits), signal(_signal), expected(NULL) { }
|
||||
FstSignal(size_t _bits, vluint8_t* _signal, vluint8_t* _expected):
|
||||
bits(_bits), signal(_signal), expected(_expected) { }
|
||||
};
|
||||
typedef std::map<fstHandle, FstSignal> SignalHandleMap;
|
||||
typedef std::map<std::string, FstSignal> SignalNameMap;
|
||||
@ -53,16 +56,21 @@ private:
|
||||
void addSignals();
|
||||
void addInput(const std::string& fullName, vluint8_t* signal, size_t size);
|
||||
void addOutput(const std::string& fullName, vluint8_t* signal, size_t size);
|
||||
void outputCheck();
|
||||
void eval();
|
||||
void trace();
|
||||
void final();
|
||||
void fstCb(uint64_t time, fstHandle facidx, const unsigned char* value,
|
||||
uint32_t len);
|
||||
void handleInput(fstHandle facidx, const unsigned char* valuep, uint32_t len);
|
||||
void handleOutput(fstHandle facidx, const unsigned char* valuep, uint32_t len);
|
||||
static void fstCallback(void* userData, uint64_t time, fstHandle facidx,
|
||||
const unsigned char* value);
|
||||
static void fstCallbackVarlen(void* userData, uint64_t time, fstHandle facidx,
|
||||
const unsigned char* value, uint32_t len);
|
||||
|
||||
static void copyValue(unsigned char* to, const unsigned char* valuep, uint32_t len);
|
||||
|
||||
std::string m_fstName;
|
||||
double& m_simTime;
|
||||
VM_PREFIX* m_modp;
|
||||
|
@ -37,6 +37,7 @@ int main(int argc, char** argv) {
|
||||
VL_PRINTF("FST = %s\n", fstFilename.c_str());
|
||||
|
||||
VerilatedReplay replay(fstFilename, simTime);
|
||||
|
||||
if (replay.init()) exit(-1);
|
||||
|
||||
if (replay.replay()) exit(-1);
|
||||
|
@ -7,14 +7,8 @@ void VlrGenerator::searchFst() {
|
||||
VerilatedReplayCommon::searchFst(m_opts.scope());
|
||||
}
|
||||
|
||||
void VlrGenerator::emitVltCode() {
|
||||
// TODO -- use V3OutCFile
|
||||
cout << "#include \"verilated_replay.h\"" << endl;
|
||||
cout << endl;
|
||||
cout << "void VerilatedReplay::addSignals() {" << endl;
|
||||
|
||||
for (VarMap::iterator it = m_inputs.begin(); it != m_inputs.end(); ++it) {
|
||||
string sigName(it->second.fullName);
|
||||
string VlrGenerator::replayName(const string& fullName) {
|
||||
string sigName(fullName);
|
||||
|
||||
// TODO -- add a trailing dot for the user if they don't
|
||||
if (m_opts.replayTop()) {
|
||||
@ -28,11 +22,34 @@ void VlrGenerator::emitVltCode() {
|
||||
sigName = sigName.substr(replayTop.length());
|
||||
}
|
||||
|
||||
// TODO -- need to be able to specify a new top level
|
||||
return sigName;
|
||||
}
|
||||
|
||||
void VlrGenerator::emitVltCode() {
|
||||
// TODO -- use V3OutCFile
|
||||
cout << "#include \"verilated_replay.h\"" << endl;
|
||||
cout << endl;
|
||||
cout << "void VerilatedReplay::addSignals() {" << endl;
|
||||
|
||||
for (VarMap::iterator it = m_inputs.begin(); it != m_inputs.end(); ++it) {
|
||||
string sigName = replayName(it->second.fullName);
|
||||
|
||||
cout << " addInput(\"" << it->second.fullName <<
|
||||
"\", &(m_modp->" << sigName <<
|
||||
"), " << it->second.hier.u.var.length << ");" << endl;
|
||||
// TODO -- sizof check (FST vs VLT)
|
||||
}
|
||||
|
||||
if (m_opts.checkOutputs()) {
|
||||
for (VarMap::iterator it = m_outputs.begin(); it != m_outputs.end(); ++it) {
|
||||
string sigName = replayName(it->second.fullName);
|
||||
|
||||
cout << " addOutput(\"" << it->second.fullName <<
|
||||
"\", &(m_modp->" << sigName <<
|
||||
"), " << it->second.hier.u.var.length << ");" << endl;
|
||||
// TODO -- sizof check (FST vs VLT)
|
||||
}
|
||||
}
|
||||
|
||||
cout << "}" << endl;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ public:
|
||||
// METHODS
|
||||
VlrOptions& opts() { return m_opts; }
|
||||
void searchFst();
|
||||
std::string replayName(const std::string& fullName);
|
||||
void emitVltCode();
|
||||
private:
|
||||
typedef std::list<std::string> StrList;
|
||||
|
@ -39,7 +39,8 @@ void VlrOptions::parseOptsList(int argc, char** argv) {
|
||||
if (sw[0]=='-' && sw[1]=='-') ++sw;
|
||||
if (0) {} // TODO -- just to avoid the asymetry of one "if"?
|
||||
// Single switches
|
||||
else if (onoff (sw, "-vlt", flag/*ref*/) ) { m_vlt = flag; }
|
||||
else if (onoff (sw, "-check-outputs", flag/*ref*/) ) { m_checkOutputs = flag; }
|
||||
else if (onoff (sw, "-vlt", flag/*ref*/) ) { m_vlt = flag; }
|
||||
//// Parameterized switches
|
||||
else if (!strcmp(sw, "-debug") ) {
|
||||
V3Error::debugDefault(3);
|
||||
|
@ -28,14 +28,15 @@ class VlrOptions {
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VlrOptions(VerilatedReplayCommon* replayp):
|
||||
m_fst(NULL), m_replayTop(NULL), m_scope(NULL), m_vlt(false),
|
||||
m_replayp(replayp)
|
||||
m_checkOutputs(false), m_fst(NULL), m_replayTop(NULL), m_scope(NULL),
|
||||
m_vlt(false), m_replayp(replayp)
|
||||
{}
|
||||
~VlrOptions() {}
|
||||
|
||||
// METHODS
|
||||
void parseOptsList(int argc, char** argv);
|
||||
|
||||
bool checkOutputs() { return m_checkOutputs; }
|
||||
const char* fst() { return m_fst; }
|
||||
const char* replayTop() { return m_replayTop; }
|
||||
const char* scope() { return m_scope; }
|
||||
@ -45,7 +46,9 @@ private:
|
||||
std::string version();
|
||||
bool onoff(const char* sw, const char* arg, bool& flag);
|
||||
void readSignalList(const char* filename);
|
||||
void outputCheck();
|
||||
|
||||
bool m_checkOutputs;
|
||||
char* m_fst;
|
||||
char* m_replayTop;
|
||||
char* m_scope;
|
||||
|
Loading…
Reference in New Issue
Block a user