[#73220] add handling scopes to SAIF trace
This commit is contained in:
parent
0e2cf72966
commit
ab9ee43f8d
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue