From ab9ee43f8d649539c8e9168567b3f29d0f0f8298 Mon Sep 17 00:00:00 2001 From: Mateusz Gancarz Date: Wed, 19 Feb 2025 13:18:39 +0100 Subject: [PATCH] [#73220] add handling scopes to SAIF trace --- include/verilated_saif_c.cpp | 97 ++++++++++++++++++++++++++++++------ include/verilated_saif_c.h | 20 ++++++++ 2 files changed, 102 insertions(+), 15 deletions(-) diff --git a/include/verilated_saif_c.cpp b/include/verilated_saif_c.cpp index cd747f3ee..ff3b1c3aa 100644 --- a/include/verilated_saif_c.cpp +++ b/include/verilated_saif_c.cpp @@ -229,19 +229,49 @@ void VerilatedSaif::close() VL_MT_SAFE_EXCLUDES(m_mutex) { printStr(std::to_string(m_time).c_str()); printStr(")\n"); + incrementIndent(); + printInstance(0); + decrementIndent(); + + printStr(")\n"); // SAIFILE + + // This function is on the flush() call path + const VerilatedLockGuard lock{m_mutex}; + if (!isOpen()) return; + closePrev(); + // closePrev() called Super::flush(), so we just + // need to shut down the tracing thread here. + Super::closeBase(); +} + +void VerilatedSaif::printInstance(uint32_t scopeIndex) { + const SaifScope& saifScope = m_scopes.at(scopeIndex); + + printIndent(); + printStr("(INSTANCE "); + printStr(saifScope.scopeName.c_str()); + printStr("\n"); + //NOTE: for now only care about NET, also PORT will be added - printStr("(INSTANCE foo (NET\n"); - for (auto& [code, activity] : m_activity) { + incrementIndent(); + printIndent(); + printStr("(NET\n"); + + incrementIndent(); + for (auto& childSignalCode : saifScope.childSignalCodes) { + ActivityVar& activity = m_activity.at(childSignalCode); for (size_t i = 0; i < activity.width; i++) { auto& bit = activity.bits[i]; if (bit.lastVal && activity.lastTime < m_time) { bit.highTime += m_time - activity.lastTime; } - if (!bit.transitions) { - // Skip bits with no transitions + if (bit.transitions <= 0) { + // Skip bits with no transitions continue; } assert(m_time >= bit.highTime); + + printIndent(); printStr("("); printStr(activity.name.c_str()); if (activity.width > 1) { @@ -262,15 +292,18 @@ void VerilatedSaif::close() VL_MT_SAFE_EXCLUDES(m_mutex) { } activity.lastTime = m_time; } - printStr("))"); // INSTANCE/NET - printStr(")\n"); // SAIFILE - // This function is on the flush() call path - const VerilatedLockGuard lock{m_mutex}; - if (!isOpen()) return; - closePrev(); - // closePrev() called Super::flush(), so we just - // need to shut down the tracing thread here. - Super::closeBase(); + decrementIndent(); + + printIndent(); + printStr(")\n"); // NET + + for (uint32_t childScopeIndex : saifScope.childScopesIndices) { + printInstance(childScopeIndex); + } + + decrementIndent(); + printIndent(); + printStr(")\n"); // INSTANCE } void VerilatedSaif::flush() VL_MT_SAFE_EXCLUDES(m_mutex) { @@ -331,10 +364,36 @@ void VerilatedSaif::bufferFlush() VL_MT_UNSAFE_ONE { //============================================================================= // Definitions +void VerilatedSaif::incrementIndent() +{ + m_indent += 1; +} + +void VerilatedSaif::decrementIndent() +{ + m_indent -= 1; +} + +void VerilatedSaif::printIndent() { + for (int i = 0; i < m_indent; ++i) printStr(" "); +} + void VerilatedSaif::pushPrefix(const std::string& name, VerilatedTracePrefixType type) { fprintf(stdout, "Pushing prefix: %s\n", name.c_str()); assert(!m_prefixStack.empty()); // Constructor makes an empty entry std::string pname = name; + + int32_t newScopeIndex = m_scopes.size(); + m_scopes.emplace_back(); + SaifScope& newScope = m_scopes.back(); + newScope.scopeName = name; + + if (m_currentScope >= 0) { + m_scopes.at(m_currentScope).childScopesIndices.emplace_back(newScopeIndex); + newScope.parentScopeIndex = m_currentScope; + } + m_currentScope = newScopeIndex; + // An empty name means this is the root of a model created with name()=="". The // tools get upset if we try to pass this as empty, so we put the signals under a // new scope, but the signals further down will be peers, not children (as usual @@ -376,6 +435,8 @@ void VerilatedSaif::popPrefix() { fprintf(stdout, "Popping prefix: %s\n", m_prefixStack.back().first.c_str()); m_prefixStack.pop_back(); assert(!m_prefixStack.empty()); // Always one left, the constructor's initial one + + m_currentScope = m_scopes.at(m_currentScope).parentScopeIndex; } void VerilatedSaif::declare(uint32_t code, const char* name, const char* wirep, bool array, @@ -387,7 +448,7 @@ void VerilatedSaif::declare(uint32_t code, const char* name, const char* wirep, const int bits = ((msb > lsb) ? (msb - lsb) : (lsb - msb)) + 1; - const std::string hierarchicalName = m_prefixStack.back().first + name; + std::string hierarchicalName = m_prefixStack.back().first + name; const bool enabled = Super::declCode(code, hierarchicalName, bits); if (!enabled) return; @@ -407,6 +468,9 @@ void VerilatedSaif::declare(uint32_t code, const char* name, const char* wirep, finalName += ']'; } + assert(m_currentScope >= 0); + m_scopes.at(m_currentScope).childSignalCodes.emplace_back(code); + m_activity.emplace(code, ActivityVar{ finalName, static_cast(lsb), @@ -427,6 +491,7 @@ void VerilatedSaif::declEvent( void VerilatedSaif::printSignalDirection(VerilatedTraceSigDirection signalDirection) { + return; switch (signalDirection) { case VerilatedTraceSigDirection::INPUT: { @@ -453,6 +518,7 @@ void VerilatedSaif::printSignalDirection(VerilatedTraceSigDirection signalDirect void VerilatedSaif::printSignalKind(VerilatedTraceSigKind signalKind) { + return; switch (signalKind) { case VerilatedTraceSigKind::PARAMETER: { @@ -498,6 +564,7 @@ void VerilatedSaif::printSignalKind(VerilatedTraceSigKind signalKind) void VerilatedSaif::printSignalType(VerilatedTraceSigType signalType) { + return; switch (signalType) { case VerilatedTraceSigType::DOUBLE: { @@ -700,7 +767,7 @@ void VerilatedSaifBuffer::emitQData(uint32_t code, QData newval, int bits) { if (bits > activity.width) { fprintf(stdout, "Trying to emit more bits than activity width\n"); } - + auto dt = m_owner.m_time - activity.lastTime; for (size_t i = 0; i < activity.width; i++) { activity.bits[i].aggregateVal(dt, (newval >> i) & 1); diff --git a/include/verilated_saif_c.h b/include/verilated_saif_c.h index c544b0681..56e8d9b02 100644 --- a/include/verilated_saif_c.h +++ b/include/verilated_saif_c.h @@ -30,6 +30,7 @@ class VerilatedSaifBuffer; class VerilatedSaifFile; + struct ActivityBit { bool lastVal = false; uint64_t highTime = 0; @@ -42,6 +43,7 @@ struct ActivityBit { lastVal = newVal; } }; + struct ActivityVar { std::string name; uint32_t lsb; @@ -50,6 +52,13 @@ struct ActivityVar { uint64_t lastTime = 0; }; +struct SaifScope { + std::string scopeName{}; + std::vector childScopesIndices{}; + std::vector childSignalCodes{}; + int32_t parentScopeIndex{-1}; +}; + //============================================================================= // VerilatedSaif // Base class to create a Verilator SAIF dump @@ -70,6 +79,11 @@ private: bool m_isOpen = false; // True indicates open file std::string m_filename; // Filename we're writing to (if open) uint64_t m_rolloverSize = 0; // File size to rollover at + + void incrementIndent(); + void decrementIndent(); + void printIndent(); + int m_indent = 0; // Indentation depth char* m_wrBufp; // Output buffer @@ -79,6 +93,10 @@ private: size_t m_maxSignalBytes = 0; // Upper bound on number of bytes a single signal can generate uint64_t m_wroteBytes = 0; // Number of bytes written to this file + std::vector m_scopes{}; + std::vector m_topScopes{}; + int32_t m_currentScope{-1}; + std::unordered_map m_activity; std::vector> m_activityArena; uint64_t m_time; @@ -105,6 +123,8 @@ private: void declare(uint32_t code, const char* name, const char* wirep, bool array, int arraynum, bool bussed, int msb, int lsb); + void printInstance(uint32_t scopeIndex); + // CONSTRUCTORS VL_UNCOPYABLE(VerilatedSaif);