Associate trace codes with function indices (#4610)

For each traced variable, also register the trace function index that
will write it.
This commit is contained in:
Geza Lore 2023-10-23 16:01:55 +01:00 committed by GitHub
parent 1bd31742b9
commit d1b6224c2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 125 additions and 83 deletions

View File

@ -222,35 +222,38 @@ void VerilatedFst::declare(uint32_t code, const char* name, int dtypenum, fstVar
} }
} }
void VerilatedFst::declEvent(uint32_t code, const char* name, int dtypenum, fstVarDir vardir, void VerilatedFst::declEvent(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
fstVarType vartype, bool array, int arraynum) { fstVarDir vardir, fstVarType vartype, bool array, int arraynum) {
declare(code, name, dtypenum, vardir, vartype, array, arraynum, false, 0, 0); declare(code, name, dtypenum, vardir, vartype, array, arraynum, false, 0, 0);
} }
void VerilatedFst::declBit(uint32_t code, const char* name, int dtypenum, fstVarDir vardir, void VerilatedFst::declBit(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
fstVarType vartype, bool array, int arraynum) { fstVarDir vardir, fstVarType vartype, bool array, int arraynum) {
declare(code, name, dtypenum, vardir, vartype, array, arraynum, false, 0, 0); declare(code, name, dtypenum, vardir, vartype, array, arraynum, false, 0, 0);
} }
void VerilatedFst::declBus(uint32_t code, const char* name, int dtypenum, fstVarDir vardir, void VerilatedFst::declBus(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
fstVarType vartype, bool array, int arraynum, int msb, int lsb) { fstVarDir vardir, fstVarType vartype, bool array, int arraynum, int msb,
int lsb) {
declare(code, name, dtypenum, vardir, vartype, array, arraynum, true, msb, lsb); declare(code, name, dtypenum, vardir, vartype, array, arraynum, true, msb, lsb);
} }
void VerilatedFst::declQuad(uint32_t code, const char* name, int dtypenum, fstVarDir vardir, void VerilatedFst::declQuad(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
fstVarType vartype, bool array, int arraynum, int msb, int lsb) { fstVarDir vardir, fstVarType vartype, bool array, int arraynum,
int msb, int lsb) {
declare(code, name, dtypenum, vardir, vartype, array, arraynum, true, msb, lsb); declare(code, name, dtypenum, vardir, vartype, array, arraynum, true, msb, lsb);
} }
void VerilatedFst::declArray(uint32_t code, const char* name, int dtypenum, fstVarDir vardir, void VerilatedFst::declArray(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
fstVarType vartype, bool array, int arraynum, int msb, int lsb) { fstVarDir vardir, fstVarType vartype, bool array, int arraynum,
int msb, int lsb) {
declare(code, name, dtypenum, vardir, vartype, array, arraynum, true, msb, lsb); declare(code, name, dtypenum, vardir, vartype, array, arraynum, true, msb, lsb);
} }
void VerilatedFst::declDouble(uint32_t code, const char* name, int dtypenum, fstVarDir vardir, void VerilatedFst::declDouble(uint32_t code, uint32_t fidx, const char* name, int dtypenum,
fstVarType vartype, bool array, int arraynum) { fstVarDir vardir, fstVarType vartype, bool array, int arraynum) {
declare(code, name, dtypenum, vardir, vartype, array, arraynum, false, 63, 0); declare(code, name, dtypenum, vardir, vartype, array, arraynum, false, 63, 0);
} }
//============================================================================= //=============================================================================
// Get/commit trace buffer // Get/commit trace buffer
VerilatedFst::Buffer* VerilatedFst::getTraceBuffer() { VerilatedFst::Buffer* VerilatedFst::getTraceBuffer(uint32_t fidx) {
if (offload()) return new OffloadBuffer{*this}; if (offload()) return new OffloadBuffer{*this};
return new Buffer{*this}; return new Buffer{*this};
} }

View File

@ -74,7 +74,7 @@ protected:
bool preChangeDump() override { return isOpen(); } bool preChangeDump() override { return isOpen(); }
// Trace buffer management // Trace buffer management
Buffer* getTraceBuffer() override; Buffer* getTraceBuffer(uint32_t fidx) override;
void commitTraceBuffer(Buffer*) override; void commitTraceBuffer(Buffer*) override;
// Configure sub-class // Configure sub-class
@ -101,17 +101,17 @@ public:
//========================================================================= //=========================================================================
// Internal interface to Verilator generated code // Internal interface to Verilator generated code
void declEvent(uint32_t code, const char* name, int dtypenum, fstVarDir vardir, void declEvent(uint32_t code, uint32_t fidx, const char* name, int dtypenum, fstVarDir vardir,
fstVarType vartype, bool array, int arraynum); fstVarType vartype, bool array, int arraynum);
void declBit(uint32_t code, const char* name, int dtypenum, fstVarDir vardir, void declBit(uint32_t code, uint32_t fidx, const char* name, int dtypenum, fstVarDir vardir,
fstVarType vartype, bool array, int arraynum); fstVarType vartype, bool array, int arraynum);
void declBus(uint32_t code, const char* name, int dtypenum, fstVarDir vardir, void declBus(uint32_t code, uint32_t fidx, const char* name, int dtypenum, fstVarDir vardir,
fstVarType vartype, bool array, int arraynum, int msb, int lsb); fstVarType vartype, bool array, int arraynum, int msb, int lsb);
void declQuad(uint32_t code, const char* name, int dtypenum, fstVarDir vardir, void declQuad(uint32_t code, uint32_t fidx, const char* name, int dtypenum, fstVarDir vardir,
fstVarType vartype, bool array, int arraynum, int msb, int lsb); fstVarType vartype, bool array, int arraynum, int msb, int lsb);
void declArray(uint32_t code, const char* name, int dtypenum, fstVarDir vardir, void declArray(uint32_t code, uint32_t fidx, const char* name, int dtypenum, fstVarDir vardir,
fstVarType vartype, bool array, int arraynum, int msb, int lsb); fstVarType vartype, bool array, int arraynum, int msb, int lsb);
void declDouble(uint32_t code, const char* name, int dtypenum, fstVarDir vardir, void declDouble(uint32_t code, uint32_t fidx, const char* name, int dtypenum, fstVarDir vardir,
fstVarType vartype, bool array, int arraynum); fstVarType vartype, bool array, int arraynum);
void declDTypeEnum(int dtypenum, const char* name, uint32_t elements, unsigned int minValbits, void declDTypeEnum(int dtypenum, const char* name, uint32_t elements, unsigned int minValbits,

View File

@ -162,24 +162,29 @@ private:
// (the one in Ubuntu 14.04 with GCC 4.8.4 in particular) use the // (the one in Ubuntu 14.04 with GCC 4.8.4 in particular) use the
// assignment operator on inserting into collections, so they don't work // assignment operator on inserting into collections, so they don't work
// with const fields... // with const fields...
union { // The callback const union { // The callback
initCb_t m_initCb; initCb_t m_initCb;
dumpCb_t m_dumpCb; dumpCb_t m_dumpCb;
dumpOffloadCb_t m_dumpOffloadCb; dumpOffloadCb_t m_dumpOffloadCb;
cleanupCb_t m_cleanupCb; cleanupCb_t m_cleanupCb;
}; };
void* m_userp; // The user pointer to pass to the callback (the symbol table) const uint32_t m_fidx; // The index of the tracing function
void* const m_userp; // The user pointer to pass to the callback (the symbol table)
CallbackRecord(initCb_t cb, void* userp) CallbackRecord(initCb_t cb, void* userp)
: m_initCb{cb} : m_initCb{cb}
, m_fidx{0}
, m_userp{userp} {} , m_userp{userp} {}
CallbackRecord(dumpCb_t cb, void* userp) CallbackRecord(dumpCb_t cb, uint32_t fidx, void* userp)
: m_dumpCb{cb} : m_dumpCb{cb}
, m_fidx{fidx}
, m_userp{userp} {} , m_userp{userp} {}
CallbackRecord(dumpOffloadCb_t cb, void* userp) CallbackRecord(dumpOffloadCb_t cb, uint32_t fidx, void* userp)
: m_dumpOffloadCb{cb} : m_dumpOffloadCb{cb}
, m_fidx{fidx}
, m_userp{userp} {} , m_userp{userp} {}
CallbackRecord(cleanupCb_t cb, void* userp) CallbackRecord(cleanupCb_t cb, void* userp)
: m_cleanupCb{cb} : m_cleanupCb{cb}
, m_fidx{0}
, m_userp{userp} {} , m_userp{userp} {}
}; };
@ -329,7 +334,7 @@ protected:
virtual bool preChangeDump() = 0; virtual bool preChangeDump() = 0;
// Trace buffer management // Trace buffer management
virtual Buffer* getTraceBuffer() = 0; virtual Buffer* getTraceBuffer(uint32_t fidx) = 0;
virtual void commitTraceBuffer(Buffer*) = 0; virtual void commitTraceBuffer(Buffer*) = 0;
// Configure sub-class // Configure sub-class
@ -363,12 +368,12 @@ public:
void addModel(VerilatedModel*) VL_MT_SAFE_EXCLUDES(m_mutex); void addModel(VerilatedModel*) VL_MT_SAFE_EXCLUDES(m_mutex);
void addInitCb(initCb_t cb, void* userp) VL_MT_SAFE; void addInitCb(initCb_t cb, void* userp) VL_MT_SAFE;
void addConstCb(dumpCb_t cb, void* userp) VL_MT_SAFE; void addConstCb(dumpCb_t cb, uint32_t fidx, void* userp) VL_MT_SAFE;
void addConstCb(dumpOffloadCb_t cb, void* userp) VL_MT_SAFE; void addConstCb(dumpOffloadCb_t cb, uint32_t fidx, void* userp) VL_MT_SAFE;
void addFullCb(dumpCb_t cb, void* userp) VL_MT_SAFE; void addFullCb(dumpCb_t cb, uint32_t fidx, void* userp) VL_MT_SAFE;
void addFullCb(dumpOffloadCb_t cb, void* userp) VL_MT_SAFE; void addFullCb(dumpOffloadCb_t cb, uint32_t fidx, void* userp) VL_MT_SAFE;
void addChgCb(dumpCb_t cb, void* userp) VL_MT_SAFE; void addChgCb(dumpCb_t cb, uint32_t fidx, void* userp) VL_MT_SAFE;
void addChgCb(dumpOffloadCb_t cb, void* userp) VL_MT_SAFE; void addChgCb(dumpOffloadCb_t cb, uint32_t fidx, void* userp) VL_MT_SAFE;
void addCleanupCb(cleanupCb_t cb, void* userp) VL_MT_SAFE; void addCleanupCb(cleanupCb_t cb, void* userp) VL_MT_SAFE;
void scopeEscape(char flag) { m_scopeEscape = flag; } void scopeEscape(char flag) { m_scopeEscape = flag; }

View File

@ -498,16 +498,15 @@ void VerilatedTrace<VL_SUB_T, VL_BUF_T>::runCallbacks(const std::vector<Callback
// Main thread executes all jobs with index % threads == 0 // Main thread executes all jobs with index % threads == 0
std::vector<ParallelWorkerData*> mainThreadWorkerData; std::vector<ParallelWorkerData*> mainThreadWorkerData;
// Enqueue all the jobs // Enqueue all the jobs
for (unsigned i = 0; i < cbVec.size(); ++i) { for (const CallbackRecord& cbr : cbVec) {
const CallbackRecord& cbr = cbVec[i];
// Always get the trace buffer on the main thread // Always get the trace buffer on the main thread
Buffer* const bufp = getTraceBuffer(); Buffer* const bufp = getTraceBuffer(cbr.m_fidx);
// Create new work item // Create new work item
workerData.emplace_back(cbr.m_dumpCb, cbr.m_userp, bufp); workerData.emplace_back(cbr.m_dumpCb, cbr.m_userp, bufp);
// Grab the new work item // Grab the new work item
ParallelWorkerData* const itemp = &workerData.back(); ParallelWorkerData* const itemp = &workerData.back();
// Enqueue task to thread pool, or main thread // Enqueue task to thread pool, or main thread
if (unsigned rem = i % threads) { if (unsigned rem = cbr.m_fidx % threads) {
threadPoolp->workerp(rem - 1)->addTask(parallelWorkerTask, itemp); threadPoolp->workerp(rem - 1)->addTask(parallelWorkerTask, itemp);
} else { } else {
mainThreadWorkerData.push_back(itemp); mainThreadWorkerData.push_back(itemp);
@ -530,7 +529,7 @@ void VerilatedTrace<VL_SUB_T, VL_BUF_T>::runCallbacks(const std::vector<Callback
} }
// Fall back on sequential execution // Fall back on sequential execution
for (const CallbackRecord& cbr : cbVec) { for (const CallbackRecord& cbr : cbVec) {
Buffer* const traceBufferp = getTraceBuffer(); Buffer* const traceBufferp = getTraceBuffer(cbr.m_fidx);
cbr.m_dumpCb(cbr.m_userp, traceBufferp); cbr.m_dumpCb(cbr.m_userp, traceBufferp);
commitTraceBuffer(traceBufferp); commitTraceBuffer(traceBufferp);
} }
@ -541,7 +540,7 @@ void VerilatedTrace<VL_SUB_T, VL_BUF_T>::runOffloadedCallbacks(
const std::vector<CallbackRecord>& cbVec) { const std::vector<CallbackRecord>& cbVec) {
// Fall back on sequential execution // Fall back on sequential execution
for (const CallbackRecord& cbr : cbVec) { for (const CallbackRecord& cbr : cbVec) {
Buffer* traceBufferp = getTraceBuffer(); Buffer* traceBufferp = getTraceBuffer(cbr.m_fidx);
cbr.m_dumpOffloadCb(cbr.m_userp, static_cast<OffloadBuffer*>(traceBufferp)); cbr.m_dumpOffloadCb(cbr.m_userp, static_cast<OffloadBuffer*>(traceBufferp));
commitTraceBuffer(traceBufferp); commitTraceBuffer(traceBufferp);
} }
@ -704,28 +703,34 @@ void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addInitCb(initCb_t cb, void* userp) VL_
addCallbackRecord(m_initCbs, CallbackRecord{cb, userp}); addCallbackRecord(m_initCbs, CallbackRecord{cb, userp});
} }
template <> template <>
void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addConstCb(dumpCb_t cb, void* userp) VL_MT_SAFE { void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addConstCb(dumpCb_t cb, uint32_t fidx,
addCallbackRecord(m_constCbs, CallbackRecord{cb, userp}); void* userp) VL_MT_SAFE {
addCallbackRecord(m_constCbs, CallbackRecord{cb, fidx, userp});
} }
template <> template <>
void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addConstCb(dumpOffloadCb_t cb, void* userp) VL_MT_SAFE { void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addConstCb(dumpOffloadCb_t cb, uint32_t fidx,
addCallbackRecord(m_constOffloadCbs, CallbackRecord{cb, userp}); void* userp) VL_MT_SAFE {
addCallbackRecord(m_constOffloadCbs, CallbackRecord{cb, fidx, userp});
} }
template <> template <>
void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addFullCb(dumpCb_t cb, void* userp) VL_MT_SAFE { void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addFullCb(dumpCb_t cb, uint32_t fidx,
addCallbackRecord(m_fullCbs, CallbackRecord{cb, userp}); void* userp) VL_MT_SAFE {
addCallbackRecord(m_fullCbs, CallbackRecord{cb, fidx, userp});
} }
template <> template <>
void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addFullCb(dumpOffloadCb_t cb, void* userp) VL_MT_SAFE { void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addFullCb(dumpOffloadCb_t cb, uint32_t fidx,
addCallbackRecord(m_fullOffloadCbs, CallbackRecord{cb, userp}); void* userp) VL_MT_SAFE {
addCallbackRecord(m_fullOffloadCbs, CallbackRecord{cb, fidx, userp});
} }
template <> template <>
void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addChgCb(dumpCb_t cb, void* userp) VL_MT_SAFE { void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addChgCb(dumpCb_t cb, uint32_t fidx,
addCallbackRecord(m_chgCbs, CallbackRecord{cb, userp}); void* userp) VL_MT_SAFE {
addCallbackRecord(m_chgCbs, CallbackRecord{cb, fidx, userp});
} }
template <> template <>
void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addChgCb(dumpOffloadCb_t cb, void* userp) VL_MT_SAFE { void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addChgCb(dumpOffloadCb_t cb, uint32_t fidx,
addCallbackRecord(m_chgOffloadCbs, CallbackRecord{cb, userp}); void* userp) VL_MT_SAFE {
addCallbackRecord(m_chgOffloadCbs, CallbackRecord{cb, fidx, userp});
} }
template <> template <>
void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addCleanupCb(cleanupCb_t cb, void* userp) VL_MT_SAFE { void VerilatedTrace<VL_SUB_T, VL_BUF_T>::addCleanupCb(cleanupCb_t cb, void* userp) VL_MT_SAFE {

View File

@ -520,32 +520,35 @@ void VerilatedVcd::declare(uint32_t code, const char* name, const char* wirep, b
m_namemapp->emplace(hiername, decl); m_namemapp->emplace(hiername, decl);
} }
void VerilatedVcd::declEvent(uint32_t code, const char* name, bool array, int arraynum) { void VerilatedVcd::declEvent(uint32_t code, uint32_t fidx, const char* name, bool array,
int arraynum) {
declare(code, name, "event", array, arraynum, false, false, 0, 0); declare(code, name, "event", array, arraynum, false, false, 0, 0);
} }
void VerilatedVcd::declBit(uint32_t code, const char* name, bool array, int arraynum) { void VerilatedVcd::declBit(uint32_t code, uint32_t fidx, const char* name, bool array,
int arraynum) {
declare(code, name, "wire", array, arraynum, false, false, 0, 0); declare(code, name, "wire", array, arraynum, false, false, 0, 0);
} }
void VerilatedVcd::declBus(uint32_t code, const char* name, bool array, int arraynum, int msb, void VerilatedVcd::declBus(uint32_t code, uint32_t fidx, const char* name, bool array,
int lsb) { int arraynum, int msb, int lsb) {
declare(code, name, "wire", array, arraynum, false, true, msb, lsb); declare(code, name, "wire", array, arraynum, false, true, msb, lsb);
} }
void VerilatedVcd::declQuad(uint32_t code, const char* name, bool array, int arraynum, int msb, void VerilatedVcd::declQuad(uint32_t code, uint32_t fidx, const char* name, bool array,
int lsb) { int arraynum, int msb, int lsb) {
declare(code, name, "wire", array, arraynum, false, true, msb, lsb); declare(code, name, "wire", array, arraynum, false, true, msb, lsb);
} }
void VerilatedVcd::declArray(uint32_t code, const char* name, bool array, int arraynum, int msb, void VerilatedVcd::declArray(uint32_t code, uint32_t fidx, const char* name, bool array,
int lsb) { int arraynum, int msb, int lsb) {
declare(code, name, "wire", array, arraynum, false, true, msb, lsb); declare(code, name, "wire", array, arraynum, false, true, msb, lsb);
} }
void VerilatedVcd::declDouble(uint32_t code, const char* name, bool array, int arraynum) { void VerilatedVcd::declDouble(uint32_t code, uint32_t fidx, const char* name, bool array,
int arraynum) {
declare(code, name, "real", array, arraynum, false, false, 63, 0); declare(code, name, "real", array, arraynum, false, false, 63, 0);
} }
//============================================================================= //=============================================================================
// Get/commit trace buffer // Get/commit trace buffer
VerilatedVcd::Buffer* VerilatedVcd::getTraceBuffer() { VerilatedVcd::Buffer* VerilatedVcd::getTraceBuffer(uint32_t fidx) {
VerilatedVcd::Buffer* const bufp = new Buffer{*this}; VerilatedVcd::Buffer* const bufp = new Buffer{*this};
if (parallel()) { if (parallel()) {
// Note: This is called from VerilatedVcd::dump, which already holds the lock // Note: This is called from VerilatedVcd::dump, which already holds the lock

View File

@ -107,7 +107,7 @@ protected:
bool preChangeDump() override; bool preChangeDump() override;
// Trace buffer management // Trace buffer management
Buffer* getTraceBuffer() override; Buffer* getTraceBuffer(uint32_t fidx) override;
void commitTraceBuffer(Buffer*) override; void commitTraceBuffer(Buffer*) override;
// Configure sub-class // Configure sub-class
@ -140,12 +140,15 @@ public:
//========================================================================= //=========================================================================
// Internal interface to Verilator generated code // Internal interface to Verilator generated code
void declEvent(uint32_t code, const char* name, bool array, int arraynum); void declEvent(uint32_t code, uint32_t fidx, const char* name, bool array, int arraynum);
void declBit(uint32_t code, const char* name, bool array, int arraynum); void declBit(uint32_t code, uint32_t fidx, const char* name, bool array, int arraynum);
void declBus(uint32_t code, const char* name, bool array, int arraynum, int msb, int lsb); void declBus(uint32_t code, uint32_t fidx, const char* name, bool array, int arraynum, int msb,
void declQuad(uint32_t code, const char* name, bool array, int arraynum, int msb, int lsb); int lsb);
void declArray(uint32_t code, const char* name, bool array, int arraynum, int msb, int lsb); void declQuad(uint32_t code, uint32_t fidx, const char* name, bool array, int arraynum,
void declDouble(uint32_t code, const char* name, bool array, int arraynum); int msb, int lsb);
void declArray(uint32_t code, uint32_t fidx, const char* name, bool array, int arraynum,
int msb, int lsb);
void declDouble(uint32_t code, uint32_t fidx, const char* name, bool array, int arraynum);
}; };
#ifndef DOXYGEN #ifndef DOXYGEN

View File

@ -3192,7 +3192,8 @@ class AstTraceDecl final : public AstNodeStmt {
// Expression being traced - Moved to AstTraceInc by V3Trace // Expression being traced - Moved to AstTraceInc by V3Trace
// @astgen op1 := valuep : Optional[AstNodeExpr] // @astgen op1 := valuep : Optional[AstNodeExpr]
private: private:
uint32_t m_code = 0; // Trace identifier code; converted to ASCII by trace routines uint32_t m_code{0}; // Trace identifier code
uint32_t m_fidx{0}; // Trace function index
const string m_showname; // Name of variable const string m_showname; // Name of variable
const VNumRange m_bitRange; // Property of var the trace details const VNumRange m_bitRange; // Property of var the trace details
const VNumRange m_arrayRange; // Property of var the trace details const VNumRange m_arrayRange; // Property of var the trace details
@ -3228,6 +3229,8 @@ public:
// Details on what we're tracing // Details on what we're tracing
uint32_t code() const { return m_code; } uint32_t code() const { return m_code; }
void code(uint32_t code) { m_code = code; } void code(uint32_t code) { m_code = code; }
uint32_t fidx() const { return m_fidx; }
void fidx(uint32_t fidx) { m_fidx = fidx; }
uint32_t codeInc() const { return m_codeInc; } uint32_t codeInc() const { return m_codeInc; }
const VNumRange& bitRange() const { return m_bitRange; } const VNumRange& bitRange() const { return m_bitRange; }
const VNumRange& arrayRange() const { return m_arrayRange; } const VNumRange& arrayRange() const { return m_arrayRange; }

View File

@ -649,6 +649,8 @@ class EmitCTrace final : EmitCFunc {
puts("(c+" + cvtToStr(nodep->code())); puts("(c+" + cvtToStr(nodep->code()));
if (nodep->arrayRange().ranged()) puts("+i*" + cvtToStr(nodep->widthWords())); if (nodep->arrayRange().ranged()) puts("+i*" + cvtToStr(nodep->widthWords()));
puts(","); puts(",");
puts(cvtToStr(nodep->fidx()));
puts(",");
putsQuoted(VIdProtect::protectWordsIf(nodep->showname(), nodep->protect())); putsQuoted(VIdProtect::protectWordsIf(nodep->showname(), nodep->protect()));
// Direction // Direction
if (v3Global.opt.traceFormat().fst()) { if (v3Global.opt.traceFormat().fst()) {

View File

@ -477,22 +477,28 @@ private:
} }
} }
AstCFunc* newCFunc(VTraceType traceType, AstCFunc* topFuncp, unsigned funcNum, AstCFunc* newCFunc(VTraceType traceType, AstCFunc* topFuncp, uint32_t funcNum,
uint32_t baseCode = 0) { uint32_t baseCode = 0) {
// Create new function // Create new function
const bool isTopFunc = topFuncp == nullptr; const bool isTopFunc = topFuncp == nullptr;
std::string baseName = "trace_"; std::string funcName;
if (traceType == VTraceType::CONSTANT) { if (isTopFunc) {
baseName += "const_"; if (traceType == VTraceType::CONSTANT) {
} else if (traceType == VTraceType::FULL) { funcName = "trace_const";
baseName += "full_"; } else if (traceType == VTraceType::FULL) {
funcName = "trace_full";
} else {
funcName = "trace_chg";
}
} else { } else {
baseName += "chg_"; funcName = topFuncp->name();
funcName += "_sub";
} }
baseName += isTopFunc ? "top_" : "sub_"; funcName += "_";
funcName += cvtToStr(funcNum);
FileLine* const flp = m_topScopep->fileline(); FileLine* const flp = m_topScopep->fileline();
AstCFunc* const funcp = new AstCFunc{flp, baseName + cvtToStr(funcNum), m_topScopep}; AstCFunc* const funcp = new AstCFunc{flp, funcName, m_topScopep};
funcp->isTrace(true); funcp->isTrace(true);
funcp->dontCombine(true); funcp->dontCombine(true);
funcp->isLoose(true); funcp->isLoose(true);
@ -526,6 +532,8 @@ private:
} }
m_regFuncp->addStmtsp(new AstText{flp, str, true}); m_regFuncp->addStmtsp(new AstText{flp, str, true});
m_regFuncp->addStmtsp(new AstAddrOfCFunc{flp, funcp}); m_regFuncp->addStmtsp(new AstAddrOfCFunc{flp, funcp});
m_regFuncp->addStmtsp(new AstText{flp, ", ", true});
m_regFuncp->addStmtsp(new AstConst{flp, funcNum});
m_regFuncp->addStmtsp(new AstText{flp, ", vlSelf);\n", true}); m_regFuncp->addStmtsp(new AstText{flp, ", vlSelf);\n", true});
} else { } else {
// Sub functions // Sub functions
@ -565,7 +573,7 @@ private:
: std::numeric_limits<int>::max(); : std::numeric_limits<int>::max();
AstCFunc* const topFuncp = newCFunc(VTraceType::CONSTANT, nullptr, 0); AstCFunc* const topFuncp = newCFunc(VTraceType::CONSTANT, nullptr, 0);
unsigned subFuncNum = 0; uint32_t subFuncNum = 0;
AstCFunc* subFuncp = nullptr; AstCFunc* subFuncp = nullptr;
int subStmts = 0; int subStmts = 0;
for (auto it = traces.cbegin(); it != traces.end(); ++it) { for (auto it = traces.cbegin(); it != traces.end(); ++it) {
@ -612,14 +620,16 @@ private:
uint32_t parallelism) { uint32_t parallelism) {
const int splitLimit = v3Global.opt.outputSplitCTrace() ? v3Global.opt.outputSplitCTrace() const int splitLimit = v3Global.opt.outputSplitCTrace() ? v3Global.opt.outputSplitCTrace()
: std::numeric_limits<int>::max(); : std::numeric_limits<int>::max();
unsigned topFuncNum = 0;
unsigned subFuncNum = 0; // pre-incremented, so starts at 0
uint32_t topFuncNum = std::numeric_limits<uint32_t>::max();
TraceVec::const_iterator it = traces.begin(); TraceVec::const_iterator it = traces.begin();
while (it != traces.end()) { while (it != traces.end()) {
AstCFunc* topFulFuncp = nullptr; AstCFunc* topFulFuncp = nullptr;
AstCFunc* topChgFuncp = nullptr; AstCFunc* topChgFuncp = nullptr;
AstCFunc* subFulFuncp = nullptr; AstCFunc* subFulFuncp = nullptr;
AstCFunc* subChgFuncp = nullptr; AstCFunc* subChgFuncp = nullptr;
uint32_t subFuncNum = 0;
int subStmts = 0; int subStmts = 0;
const uint32_t maxCodes = std::max((nAllCodes + parallelism - 1) / parallelism, 1U); const uint32_t maxCodes = std::max((nAllCodes + parallelism - 1) / parallelism, 1U);
uint32_t nCodes = 0; uint32_t nCodes = 0;
@ -627,20 +637,25 @@ private:
AstIf* ifp = nullptr; AstIf* ifp = nullptr;
uint32_t baseCode = 0; uint32_t baseCode = 0;
for (; nCodes < maxCodes && it != traces.end(); ++it) { for (; nCodes < maxCodes && it != traces.end(); ++it) {
const TraceTraceVertex* const vtxp = it->second;
// This is a duplicate decl, no need to add it
if (vtxp->duplicatep()) continue;
const ActCodeSet& actSet = it->first; const ActCodeSet& actSet = it->first;
// Traced value never changes, no need to add it // Traced value never changes, no need to add it
if (actSet.count(TraceActivityVertex::ACTIVITY_NEVER)) continue; if (actSet.count(TraceActivityVertex::ACTIVITY_NEVER)) continue;
const TraceTraceVertex* const vtxp = it->second;
AstTraceDecl* const declp = vtxp->nodep(); AstTraceDecl* const declp = vtxp->nodep();
// This is a duplicate decl, no need to add it, but must set the
// function index to the same as the canonical node.
if (const TraceTraceVertex* const canonVtxp = vtxp->duplicatep()) {
declp->fidx(canonVtxp->nodep()->fidx());
continue;
}
// Create top function if not yet created // Create top function if not yet created
if (!topFulFuncp) { if (!topFulFuncp) {
++topFuncNum;
topFulFuncp = newCFunc(VTraceType::FULL, nullptr, topFuncNum); topFulFuncp = newCFunc(VTraceType::FULL, nullptr, topFuncNum);
topChgFuncp = newCFunc(VTraceType::CHANGE, nullptr, topFuncNum); topChgFuncp = newCFunc(VTraceType::CHANGE, nullptr, topFuncNum);
++topFuncNum;
} }
// Create new sub function if required // Create new sub function if required
@ -682,6 +697,9 @@ private:
= new AstTraceInc{flp, declp, VTraceType::CHANGE, baseCode}; = new AstTraceInc{flp, declp, VTraceType::CHANGE, baseCode};
ifp->addThensp(incChgp); ifp->addThensp(incChgp);
// Set the function index of the decl
declp->fidx(topFuncNum);
// Track splitting due to size // Track splitting due to size
UASSERT_OBJ(incFulp->nodeCount() == incChgp->nodeCount(), declp, UASSERT_OBJ(incFulp->nodeCount() == incChgp->nodeCount(), declp,
"Should have equal cost"); "Should have equal cost");