[#73220] add handling scopes to SAIF trace

This commit is contained in:
Mateusz Gancarz 2025-02-19 13:18:39 +01:00
parent 0e2cf72966
commit ab9ee43f8d
2 changed files with 102 additions and 15 deletions

View File

@ -229,19 +229,49 @@ void VerilatedSaif::close() VL_MT_SAFE_EXCLUDES(m_mutex) {
printStr(std::to_string(m_time).c_str()); printStr(std::to_string(m_time).c_str());
printStr(")\n"); 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 //NOTE: for now only care about NET, also PORT will be added
printStr("(INSTANCE foo (NET\n"); incrementIndent();
for (auto& [code, activity] : m_activity) { 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++) { for (size_t i = 0; i < activity.width; i++) {
auto& bit = activity.bits[i]; auto& bit = activity.bits[i];
if (bit.lastVal && activity.lastTime < m_time) { if (bit.lastVal && activity.lastTime < m_time) {
bit.highTime += m_time - activity.lastTime; bit.highTime += m_time - activity.lastTime;
} }
if (!bit.transitions) { if (bit.transitions <= 0) {
// Skip bits with no transitions // Skip bits with no transitions
continue; continue;
} }
assert(m_time >= bit.highTime); assert(m_time >= bit.highTime);
printIndent();
printStr("("); printStr("(");
printStr(activity.name.c_str()); printStr(activity.name.c_str());
if (activity.width > 1) { if (activity.width > 1) {
@ -262,15 +292,18 @@ void VerilatedSaif::close() VL_MT_SAFE_EXCLUDES(m_mutex) {
} }
activity.lastTime = m_time; activity.lastTime = m_time;
} }
printStr("))"); // INSTANCE/NET decrementIndent();
printStr(")\n"); // SAIFILE
// This function is on the flush() call path printIndent();
const VerilatedLockGuard lock{m_mutex}; printStr(")\n"); // NET
if (!isOpen()) return;
closePrev(); for (uint32_t childScopeIndex : saifScope.childScopesIndices) {
// closePrev() called Super::flush(), so we just printInstance(childScopeIndex);
// need to shut down the tracing thread here. }
Super::closeBase();
decrementIndent();
printIndent();
printStr(")\n"); // INSTANCE
} }
void VerilatedSaif::flush() VL_MT_SAFE_EXCLUDES(m_mutex) { void VerilatedSaif::flush() VL_MT_SAFE_EXCLUDES(m_mutex) {
@ -331,10 +364,36 @@ void VerilatedSaif::bufferFlush() VL_MT_UNSAFE_ONE {
//============================================================================= //=============================================================================
// Definitions // 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) { void VerilatedSaif::pushPrefix(const std::string& name, VerilatedTracePrefixType type) {
fprintf(stdout, "Pushing prefix: %s\n", name.c_str()); fprintf(stdout, "Pushing prefix: %s\n", name.c_str());
assert(!m_prefixStack.empty()); // Constructor makes an empty entry assert(!m_prefixStack.empty()); // Constructor makes an empty entry
std::string pname = name; 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 // 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 // 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 // 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()); fprintf(stdout, "Popping prefix: %s\n", m_prefixStack.back().first.c_str());
m_prefixStack.pop_back(); m_prefixStack.pop_back();
assert(!m_prefixStack.empty()); // Always one left, the constructor's initial one 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, 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 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); const bool enabled = Super::declCode(code, hierarchicalName, bits);
if (!enabled) return; if (!enabled) return;
@ -407,6 +468,9 @@ void VerilatedSaif::declare(uint32_t code, const char* name, const char* wirep,
finalName += ']'; finalName += ']';
} }
assert(m_currentScope >= 0);
m_scopes.at(m_currentScope).childSignalCodes.emplace_back(code);
m_activity.emplace(code, ActivityVar{ m_activity.emplace(code, ActivityVar{
finalName, finalName,
static_cast<uint32_t>(lsb), static_cast<uint32_t>(lsb),
@ -427,6 +491,7 @@ void VerilatedSaif::declEvent(
void VerilatedSaif::printSignalDirection(VerilatedTraceSigDirection signalDirection) void VerilatedSaif::printSignalDirection(VerilatedTraceSigDirection signalDirection)
{ {
return;
switch (signalDirection) { switch (signalDirection) {
case VerilatedTraceSigDirection::INPUT: case VerilatedTraceSigDirection::INPUT:
{ {
@ -453,6 +518,7 @@ void VerilatedSaif::printSignalDirection(VerilatedTraceSigDirection signalDirect
void VerilatedSaif::printSignalKind(VerilatedTraceSigKind signalKind) void VerilatedSaif::printSignalKind(VerilatedTraceSigKind signalKind)
{ {
return;
switch (signalKind) { switch (signalKind) {
case VerilatedTraceSigKind::PARAMETER: case VerilatedTraceSigKind::PARAMETER:
{ {
@ -498,6 +564,7 @@ void VerilatedSaif::printSignalKind(VerilatedTraceSigKind signalKind)
void VerilatedSaif::printSignalType(VerilatedTraceSigType signalType) void VerilatedSaif::printSignalType(VerilatedTraceSigType signalType)
{ {
return;
switch (signalType) { switch (signalType) {
case VerilatedTraceSigType::DOUBLE: case VerilatedTraceSigType::DOUBLE:
{ {
@ -700,7 +767,7 @@ void VerilatedSaifBuffer::emitQData(uint32_t code, QData newval, int bits) {
if (bits > activity.width) { if (bits > activity.width) {
fprintf(stdout, "Trying to emit more bits than activity width\n"); fprintf(stdout, "Trying to emit more bits than activity width\n");
} }
auto dt = m_owner.m_time - activity.lastTime; auto dt = m_owner.m_time - activity.lastTime;
for (size_t i = 0; i < activity.width; i++) { for (size_t i = 0; i < activity.width; i++) {
activity.bits[i].aggregateVal(dt, (newval >> i) & 1); activity.bits[i].aggregateVal(dt, (newval >> i) & 1);

View File

@ -30,6 +30,7 @@
class VerilatedSaifBuffer; class VerilatedSaifBuffer;
class VerilatedSaifFile; class VerilatedSaifFile;
struct ActivityBit { struct ActivityBit {
bool lastVal = false; bool lastVal = false;
uint64_t highTime = 0; uint64_t highTime = 0;
@ -42,6 +43,7 @@ struct ActivityBit {
lastVal = newVal; lastVal = newVal;
} }
}; };
struct ActivityVar { struct ActivityVar {
std::string name; std::string name;
uint32_t lsb; uint32_t lsb;
@ -50,6 +52,13 @@ struct ActivityVar {
uint64_t lastTime = 0; uint64_t lastTime = 0;
}; };
struct SaifScope {
std::string scopeName{};
std::vector<int32_t> childScopesIndices{};
std::vector<uint32_t> childSignalCodes{};
int32_t parentScopeIndex{-1};
};
//============================================================================= //=============================================================================
// VerilatedSaif // VerilatedSaif
// Base class to create a Verilator SAIF dump // Base class to create a Verilator SAIF dump
@ -70,6 +79,11 @@ private:
bool m_isOpen = false; // True indicates open file bool m_isOpen = false; // True indicates open file
std::string m_filename; // Filename we're writing to (if open) std::string m_filename; // Filename we're writing to (if open)
uint64_t m_rolloverSize = 0; // File size to rollover at uint64_t m_rolloverSize = 0; // File size to rollover at
void incrementIndent();
void decrementIndent();
void printIndent();
int m_indent = 0; // Indentation depth int m_indent = 0; // Indentation depth
char* m_wrBufp; // Output buffer 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 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 uint64_t m_wroteBytes = 0; // Number of bytes written to this file
std::vector<SaifScope> m_scopes{};
std::vector<uint32_t> m_topScopes{};
int32_t m_currentScope{-1};
std::unordered_map<uint32_t, ActivityVar> m_activity; std::unordered_map<uint32_t, ActivityVar> m_activity;
std::vector<std::vector<ActivityBit>> m_activityArena; std::vector<std::vector<ActivityBit>> m_activityArena;
uint64_t m_time; uint64_t m_time;
@ -105,6 +123,8 @@ private:
void declare(uint32_t code, const char* name, const char* wirep, bool array, int arraynum, void declare(uint32_t code, const char* name, const char* wirep, bool array, int arraynum,
bool bussed, int msb, int lsb); bool bussed, int msb, int lsb);
void printInstance(uint32_t scopeIndex);
// CONSTRUCTORS // CONSTRUCTORS
VL_UNCOPYABLE(VerilatedSaif); VL_UNCOPYABLE(VerilatedSaif);