Preload data option

This commit is contained in:
Todd Strader 2020-01-24 15:44:41 -05:00
parent 4430edf6da
commit 15a3f31d11
3 changed files with 141 additions and 16 deletions

View File

@ -38,6 +38,7 @@ int VerilatedReplay::init() {
openFst(m_fstName); openFst(m_fstName);
searchFst(NULL); searchFst(NULL);
m_time = fstReaderGetStartTime(m_fstp); m_time = fstReaderGetStartTime(m_fstp);
m_preloadTime = m_time;
// TODO -- use FST timescale // TODO -- use FST timescale
m_simTime = m_time; m_simTime = m_time;
@ -62,6 +63,19 @@ int VerilatedReplay::init() {
buffer); buffer);
} }
if (m_preloadData) {
// TODO -- should I be using fstReaderIterBlocks instead? (only one CB)
// It appears that 0 is the error return code
if (fstReaderIterBlocks2(m_fstp, &VerilatedReplay::fstCallback,
&VerilatedReplay::fstCallbackVarlen, this, NULL) == 0) {
VL_PRINTF("Error iterating FST\n");
exit(-1);
}
// Add final time
addPreloadTime();
}
return 0; return 0;
} }
@ -72,10 +86,14 @@ VerilatedReplay::~VerilatedReplay() {
delete [] it->second.expected; delete [] it->second.expected;
} }
for (ReplayVector::iterator it = m_replayData.begin(); it != m_replayData.end(); ++it) {
if (it->type != ReplayData::ReplayType::Time) delete [] it->data;
}
#if VM_TRACE #if VM_TRACE
if (m_tfp) m_tfp->close(); if (m_tfp) m_tfp->close();
#endif #endif
delete(m_modp); delete m_modp;
} }
void VerilatedReplay::addInput(const std::string& fullName, vluint8_t* signal, size_t size) { void VerilatedReplay::addInput(const std::string& fullName, vluint8_t* signal, size_t size) {
@ -86,14 +104,36 @@ void VerilatedReplay::addOutput(const std::string& fullName, vluint8_t* signal,
m_outputNames[fullName] = FstSignal(size, signal); m_outputNames[fullName] = FstSignal(size, signal);
} }
void VerilatedReplay::replayPreloadedData() {
for (ReplayVector::iterator it = m_replayData.begin(); it != m_replayData.end(); ++it) {
switch (it->type) {
case ReplayData::ReplayType::Input:
case ReplayData::ReplayType::Output:
memcpy(it->u.target, it->data, it->size);
break;
case ReplayData::ReplayType::Time:
m_time = it->u.time;
// TODO -- use FST timescale
m_simTime = m_time;
eval();
break;
}
}
}
int VerilatedReplay::replay() { int VerilatedReplay::replay() {
// TODO -- lockless ring buffer for separate reader/replay threads // TODO -- lockless ring buffer for separate reader/replay threads if
// TODO -- should I be using fstReaderIterBlocks instead? (only one CB) // dumb preloading is insufficient
// It appears that 0 is the error return code if (m_preloadData) {
if (fstReaderIterBlocks2(m_fstp, &VerilatedReplay::fstCallback, replayPreloadedData();
&VerilatedReplay::fstCallbackVarlen, this, NULL) == 0) { } else {
VL_PRINTF("Error iterating FST\n"); // TODO -- should I be using fstReaderIterBlocks instead? (only one CB)
exit(-1); // It appears that 0 is the error return code
if (fstReaderIterBlocks2(m_fstp, &VerilatedReplay::fstCallback,
&VerilatedReplay::fstCallbackVarlen, this, NULL) == 0) {
VL_PRINTF("Error iterating FST\n");
exit(-1);
}
} }
// One final eval + trace since we only eval on time changes // One final eval + trace since we only eval on time changes
@ -104,8 +144,60 @@ int VerilatedReplay::replay() {
return 0; return 0;
} }
void VerilatedReplay::addPreloadTime() {
ReplayData data;
data.type = ReplayData::ReplayType::Time;
data.u.time = m_preloadTime;
m_replayData.push_back(data);
}
void VerilatedReplay::loadData(ReplayData::ReplayType type, fstHandle facidx,
const unsigned char* valuep, uint32_t len) {
ReplayData data;
data.type = type;
if (type == ReplayData::ReplayType::Input) {
data.u.target = m_inputHandles[facidx].signal;
} else {
data.u.target = m_outputHandles[facidx].expected;
}
size_t bytes = (len + 7) / 8;
data.size = bytes;
// TODO -- would pre-allocating space be better? possibly hugepages if available
data.data = new vluint8_t [bytes];
copyValue(data.data, valuep, len);
m_replayData.push_back(data);
}
void VerilatedReplay::loadInput(fstHandle facidx, const unsigned char* valuep, uint32_t len) {
loadData(ReplayData::ReplayType::Input, facidx, valuep, len);
}
void VerilatedReplay::loadOutput(fstHandle facidx, const unsigned char* valuep, uint32_t len) {
loadData(ReplayData::ReplayType::Output, facidx, valuep, len);
}
void VerilatedReplay::loadData(uint64_t time, fstHandle facidx,
const unsigned char* valuep, uint32_t len) {
// TODO -- move to method and call at the very end too
if (m_preloadTime != time) {
addPreloadTime();
m_preloadTime = time;
}
if (m_outputHandles.empty() || m_inputHandles.find(facidx) != m_inputHandles.end()) {
loadInput(facidx, valuep, len);
} else {
loadOutput(facidx, valuep, len);
}
}
void VerilatedReplay::fstCb(uint64_t time, fstHandle facidx, void VerilatedReplay::fstCb(uint64_t time, fstHandle facidx,
const unsigned char* valuep, uint32_t len) { const unsigned char* valuep, uint32_t len) {
if (m_preloadData) {
loadData(time, facidx, valuep, len);
return;
}
// Watch for new time steps and eval before we start working on the new time // Watch for new time steps and eval before we start working on the new time
if (m_time != time) { if (m_time != time) {
eval(); eval();
@ -123,6 +215,8 @@ void VerilatedReplay::fstCb(uint64_t time, fstHandle facidx,
} }
void VerilatedReplay::copyValue(unsigned char* to, const unsigned char* valuep, uint32_t len) { void VerilatedReplay::copyValue(unsigned char* to, 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 byte = 0; vluint8_t byte = 0;
for (size_t bit = 0; bit < len; ++bit) { for (size_t bit = 0; bit < len; ++bit) {
char value = valuep[len - 1 - bit]; char value = valuep[len - 1 - bit];
@ -136,8 +230,6 @@ void VerilatedReplay::copyValue(unsigned char* to, const unsigned char* valuep,
} }
void VerilatedReplay::handleInput(fstHandle facidx, const unsigned char* valuep, uint32_t len) { 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; vluint8_t* signal = m_inputHandles[facidx].signal;
copyValue(signal, valuep, len); copyValue(signal, valuep, len);
} }
@ -184,11 +276,13 @@ void VerilatedReplay::createMod() {
m_modp = new VM_PREFIX; m_modp = new VM_PREFIX;
// TODO -- make VerilatedModule destructor virtual so we can delete from the base class? // TODO -- make VerilatedModule destructor virtual so we can delete from the base class?
#if VM_TRACE #if VM_TRACE
Verilated::traceEverOn(true); if (m_doTrace) {
m_tfp = new VerilatedFstC; Verilated::traceEverOn(true);
m_modp->trace(m_tfp, 99); m_tfp = new VerilatedFstC;
// TODO -- command line parameter m_modp->trace(m_tfp, 99);
m_tfp->open("replay.fst"); // TODO -- command line parameter
m_tfp->open("replay.fst");
}
#endif // VM_TRACE #endif // VM_TRACE
} }

View File

@ -32,6 +32,7 @@
#include "gtkwave/fstapi.h" #include "gtkwave/fstapi.h"
#include <string> #include <string>
#include <map> #include <map>
#include <vector>
#define QUOTE(x) #x #define QUOTE(x) #x
#define MAKE_HEADER(x) QUOTE(x.h) #define MAKE_HEADER(x) QUOTE(x.h)
@ -52,6 +53,18 @@ private:
typedef std::map<fstHandle, FstSignal> SignalHandleMap; typedef std::map<fstHandle, FstSignal> SignalHandleMap;
typedef std::map<std::string, FstSignal> SignalNameMap; typedef std::map<std::string, FstSignal> SignalNameMap;
struct ReplayData {
enum ReplayType {Input, Output, Time};
size_t size;
ReplayType type;
union {
uint64_t time;
vluint8_t* target;
} u;
vluint8_t* data;
};
typedef std::vector<ReplayData> ReplayVector;
void createMod(); void createMod();
void addSignals(); void addSignals();
void addInput(const std::string& fullName, vluint8_t* signal, size_t size); void addInput(const std::string& fullName, vluint8_t* signal, size_t size);
@ -60,6 +73,14 @@ private:
void eval(); void eval();
void trace(); void trace();
void final(); void final();
void addPreloadTime();
void loadData(ReplayData::ReplayType type, fstHandle facidx,
const unsigned char* valuep, uint32_t len);
void loadInput(fstHandle facidx, const unsigned char* valuep, uint32_t len);
void loadOutput(fstHandle facidx, const unsigned char* valuep, uint32_t len);
void replayPreloadedData();
void loadData(uint64_t time, fstHandle facidx, const unsigned char* value,
uint32_t len);
void fstCb(uint64_t time, fstHandle facidx, const unsigned char* value, void fstCb(uint64_t time, fstHandle facidx, const unsigned char* value,
uint32_t len); uint32_t len);
void handleInput(fstHandle facidx, const unsigned char* valuep, uint32_t len); void handleInput(fstHandle facidx, const unsigned char* valuep, uint32_t len);
@ -76,17 +97,24 @@ private:
VM_PREFIX* m_modp; VM_PREFIX* m_modp;
VerilatedFstC* m_tfp; VerilatedFstC* m_tfp;
uint64_t m_time; uint64_t m_time;
uint64_t m_preloadTime;
bool m_preloadData;
bool m_doTrace;
SignalHandleMap m_inputHandles; SignalHandleMap m_inputHandles;
SignalHandleMap m_outputHandles; SignalHandleMap m_outputHandles;
SignalNameMap m_inputNames; SignalNameMap m_inputNames;
SignalNameMap m_outputNames; SignalNameMap m_outputNames;
ReplayVector m_replayData;
public: public:
VerilatedReplay(const std::string& fstName, double& simTime): VerilatedReplay(const std::string& fstName, double& simTime):
m_fstName(fstName), m_simTime(simTime) m_fstName(fstName), m_simTime(simTime), m_tfp(NULL),
m_preloadData(false), m_doTrace(false)
{} {}
~VerilatedReplay(); ~VerilatedReplay();
int init(); int init();
int replay(); int replay();
void preloadData(bool value) { m_preloadData = value; }
void doTrace(bool value) { m_doTrace = value; }
}; };
#endif // Guard #endif // Guard

View File

@ -43,6 +43,9 @@ int main(int argc, char** argv) {
VL_PRINTF("FST = %s\n", fstFilename.c_str()); VL_PRINTF("FST = %s\n", fstFilename.c_str());
VerilatedReplay replay(fstFilename, simTime); VerilatedReplay replay(fstFilename, simTime);
// TODO -- again, arg parsing
replay.preloadData(true);
replay.doTrace(false);
if (replay.init()) exit(-1); if (replay.init()) exit(-1);