forked from github/verilator
Preload data option
This commit is contained in:
parent
4430edf6da
commit
15a3f31d11
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user