[#74021] move activity accumulating code to its own class

This commit is contained in:
Mateusz Gancarz 2025-03-05 12:43:30 +01:00
parent b383f64cff
commit c71f5b42e3
2 changed files with 130 additions and 76 deletions

View File

@ -94,7 +94,9 @@ VerilatedSaifActivityBit& VerilatedSaifActivityVar::bit(const std::size_t index)
//=============================================================================
// Opening/Closing
VerilatedSaif::VerilatedSaif(void* filep) {}
VerilatedSaif::VerilatedSaif(void* filep) {
m_activityAccumulators.emplace_back();
}
void VerilatedSaif::open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lock{m_mutex};
@ -178,14 +180,26 @@ void VerilatedSaif::closeInstanceScope() {
}
void VerilatedSaif::printScopeActivities(const VerilatedSaifActivityScope& scope) {
bool anyNetValid{false};
for (const auto& childSignal : scope.childActivities()) {
const uint32_t code = childSignal.first;
const char* const name = childSignal.second.c_str();
anyNetValid = printActivityStats(code, name, anyNetValid);
bool anyNetWritten{false};
for (auto& accumulator : m_activityAccumulators) {
anyNetWritten |= printScopeActivitiesFromAccumulatorIfPresent(scope.path(), accumulator, anyNetWritten);
}
if (anyNetValid) closeNetScope();
if (anyNetWritten) closeNetScope();
}
bool VerilatedSaif::printScopeActivitiesFromAccumulatorIfPresent(const std::string& absoluteScopePath, VerilatedSaifActivityAccumulator& accumulator, bool anyNetWritten) {
if (accumulator.m_scopeToActivities.count(absoluteScopePath) == 0) {
return false;
}
for (const auto& childSignal : accumulator.m_scopeToActivities.at(absoluteScopePath)) {
VerilatedSaifActivityVar& activityVariable = accumulator.m_activity.at(childSignal.first);
anyNetWritten = printActivityStats(activityVariable, childSignal.second.c_str(), anyNetWritten);
}
return anyNetWritten;
}
void VerilatedSaif::openNetScope() {
@ -200,9 +214,8 @@ void VerilatedSaif::closeNetScope() {
printStr(")\n");
}
bool VerilatedSaif::printActivityStats(const uint32_t activityCode, const char* activityName,
bool anyNetValid) {
VerilatedSaifActivityVar& activity = m_activity.at(activityCode);
bool VerilatedSaif::printActivityStats(VerilatedSaifActivityVar& activity, const char* activityName,
bool anyNetWritten) {
for (size_t i = 0; i < activity.width(); ++i) {
VerilatedSaifActivityBit& bit = activity.bit(i);
@ -213,9 +226,9 @@ bool VerilatedSaif::printActivityStats(const uint32_t activityCode, const char*
bit.aggregateVal(currentTime() - activity.lastUpdateTime(), bit.bitValue());
if (!anyNetValid) {
if (!anyNetWritten) {
openNetScope();
anyNetValid = true;
anyNetWritten = true;
}
printIndent();
@ -239,15 +252,14 @@ bool VerilatedSaif::printActivityStats(const uint32_t activityCode, const char*
activity.updateLastTime(currentTime());
return anyNetValid;
return anyNetWritten;
}
void VerilatedSaif::clearCurrentlyCollectedData() {
m_currentScope = -1;
m_scopes.clear();
m_topScopes.clear();
m_activity.clear();
m_activityArena.clear();
m_activityAccumulators.clear();
}
void VerilatedSaif::printStr(const char* str) { ::write(m_filep, str, strlen(str)); }
@ -287,7 +299,11 @@ void VerilatedSaif::pushPrefix(const std::string& name, VerilatedTracePrefixType
} else {
m_topScopes.emplace_back(newScopeIndex);
}
m_scopes.emplace_back(lastWord(m_prefixStack.back().first + pname), m_currentScope);
std::string scopePath = m_prefixStack.back().first + pname;
std::string scopeName = lastWord(scopePath);
m_scopes.emplace_back(std::move(scopePath), std::move(scopeName), m_currentScope);
m_currentScope = newScopeIndex;
}
@ -310,15 +326,7 @@ void VerilatedSaif::popPrefix() {
m_prefixStack.pop_back();
}
void VerilatedSaif::declare(const uint32_t code, const char* name, const char* wirep,
const bool array, const int arraynum, const bool bussed, const int msb,
const int lsb) {
const int bits = ((msb > lsb) ? (msb - lsb) : (lsb - msb)) + 1;
const std::string hierarchicalName = m_prefixStack.back().first + name;
if (!Super::declCode(code, hierarchicalName, bits)) return;
void VerilatedSaifActivityAccumulator::declare(uint32_t code, const std::string& absoluteScopePath, std::string variableName, int bits, bool array, int arraynum) {
const size_t block_size = 1024;
if (m_activityArena.empty()
|| m_activityArena.back().size() + bits > m_activityArena.back().capacity()) {
@ -328,56 +336,70 @@ void VerilatedSaif::declare(const uint32_t code, const char* name, const char* w
const size_t bitsIdx = m_activityArena.back().size();
m_activityArena.back().resize(m_activityArena.back().size() + bits);
std::string finalName = lastWord(hierarchicalName);
if (array) {
finalName += '[';
finalName += std::to_string(arraynum);
finalName += ']';
variableName += '[';
variableName += std::to_string(arraynum);
variableName += ']';
}
assert(m_currentScope >= 0);
m_scopes.at(m_currentScope).addActivityVar(code, std::move(finalName));
m_scopeToActivities[absoluteScopePath].emplace_back(code, variableName);
m_activity.emplace(code, VerilatedSaifActivityVar{
static_cast<uint32_t>(bits), m_activityArena.back().data() + bitsIdx});
}
m_activity.emplace(code, VerilatedSaifActivityVar{static_cast<uint32_t>(bits),
m_activityArena.back().data() + bitsIdx});
void VerilatedSaif::declare(const uint32_t code, uint32_t fidx, const char* name, const char* wirep,
const bool array, const int arraynum, const bool bussed, const int msb,
const int lsb) {
VerilatedSaifActivityAccumulator& accumulator = m_activityAccumulators.at(fidx);
const int bits = ((msb > lsb) ? (msb - lsb) : (lsb - msb)) + 1;
const std::string hierarchicalName = m_prefixStack.back().first + name;
if (!Super::declCode(code, hierarchicalName, bits)) return;
std::string variableName = lastWord(hierarchicalName);
m_scopes.at(m_currentScope).addActivityVar(code, variableName);
accumulator.declare(code, m_scopes.at(m_currentScope).path(), std::move(variableName), bits, array, arraynum);
}
void VerilatedSaif::declEvent(const uint32_t code, const uint32_t fidx, const char* name,
const int dtypenum, const VerilatedTraceSigDirection,
const VerilatedTraceSigKind, const VerilatedTraceSigType,
const bool array, const int arraynum) {
declare(code, name, "event", array, arraynum, false, 0, 0);
declare(code, fidx, name, "event", array, arraynum, false, 0, 0);
}
void VerilatedSaif::declBit(const uint32_t code, const uint32_t fidx, const char* name,
const int dtypenum, const VerilatedTraceSigDirection,
const VerilatedTraceSigKind, const VerilatedTraceSigType,
const bool array, const int arraynum) {
declare(code, name, "wire", array, arraynum, false, 0, 0);
declare(code, fidx, name, "wire", array, arraynum, false, 0, 0);
}
void VerilatedSaif::declBus(const uint32_t code, const uint32_t fidx, const char* name,
const int dtypenum, const VerilatedTraceSigDirection,
const VerilatedTraceSigKind, const VerilatedTraceSigType,
const bool array, const int arraynum, const int msb, const int lsb) {
declare(code, name, "wire", array, arraynum, true, msb, lsb);
declare(code, fidx, name, "wire", array, arraynum, true, msb, lsb);
}
void VerilatedSaif::declQuad(const uint32_t code, const uint32_t fidx, const char* name,
const int dtypenum, const VerilatedTraceSigDirection,
const VerilatedTraceSigKind, const VerilatedTraceSigType,
const bool array, const int arraynum, const int msb, const int lsb) {
declare(code, name, "wire", array, arraynum, true, msb, lsb);
declare(code, fidx, name, "wire", array, arraynum, true, msb, lsb);
}
void VerilatedSaif::declArray(const uint32_t code, const uint32_t fidx, const char* name,
const int dtypenum, const VerilatedTraceSigDirection,
const VerilatedTraceSigKind, const VerilatedTraceSigType,
const bool array, const int arraynum, const int msb, const int lsb) {
declare(code, name, "wire", array, arraynum, true, msb, lsb);
declare(code, fidx, name, "wire", array, arraynum, true, msb, lsb);
}
void VerilatedSaif::declDouble(const uint32_t code, const uint32_t fidx, const char* name,
const int dtypenum, const VerilatedTraceSigDirection,
const VerilatedTraceSigKind, const VerilatedTraceSigType,
const bool array, const int arraynum) {
declare(code, name, "real", array, arraynum, false, 63, 0);
declare(code, fidx, name, "real", array, arraynum, false, 63, 0);
}
//=============================================================================
@ -404,43 +426,43 @@ void VerilatedSaifBuffer::emitEvent(const uint32_t code) {
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitBit(const uint32_t code, const CData newval) {
assert(m_owner.m_activity.count(code) && "Activity must be declared earlier");
VerilatedSaifActivityVar& activity = m_owner.m_activity.at(code);
assert(m_owner.m_activityAccumulators.at(m_fidx).m_activity.count(code) && "Activity must be declared earlier");
VerilatedSaifActivityVar& activity = m_owner.m_activityAccumulators.at(m_fidx).m_activity.at(code);
activity.emitBit(m_owner.currentTime(), newval);
}
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitCData(const uint32_t code, const CData newval, const int bits) {
assert(m_owner.m_activity.count(code) && "Activity must be declared earlier");
VerilatedSaifActivityVar& activity = m_owner.m_activity.at(code);
assert(m_owner.m_activityAccumulators.at(m_fidx).m_activity.count(code) && "Activity must be declared earlier");
VerilatedSaifActivityVar& activity = m_owner.m_activityAccumulators.at(m_fidx).m_activity.at(code);
activity.emitData<CData>(m_owner.currentTime(), newval, bits);
}
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitSData(const uint32_t code, const SData newval, const int bits) {
assert(m_owner.m_activity.count(code) && "Activity must be declared earlier");
VerilatedSaifActivityVar& activity = m_owner.m_activity.at(code);
assert(m_owner.m_activityAccumulators.at(m_fidx).m_activity.count(code) && "Activity must be declared earlier");
VerilatedSaifActivityVar& activity = m_owner.m_activityAccumulators.at(m_fidx).m_activity.at(code);
activity.emitData<SData>(m_owner.currentTime(), newval, bits);
}
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitIData(const uint32_t code, const IData newval, const int bits) {
assert(m_owner.m_activity.count(code) && "Activity must be declared earlier");
VerilatedSaifActivityVar& activity = m_owner.m_activity.at(code);
assert(m_owner.m_activityAccumulators.at(m_fidx).m_activity.count(code) && "Activity must be declared earlier");
VerilatedSaifActivityVar& activity = m_owner.m_activityAccumulators.at(m_fidx).m_activity.at(code);
activity.emitData<IData>(m_owner.currentTime(), newval, bits);
}
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitQData(const uint32_t code, const QData newval, const int bits) {
assert(m_owner.m_activity.count(code) && "Activity must be declared earlier");
VerilatedSaifActivityVar& activity = m_owner.m_activity.at(code);
assert(m_owner.m_activityAccumulators.at(m_fidx).m_activity.count(code) && "Activity must be declared earlier");
VerilatedSaifActivityVar& activity = m_owner.m_activityAccumulators.at(m_fidx).m_activity.at(code);
activity.emitData<QData>(m_owner.currentTime(), newval, bits);
}
VL_ATTR_ALWINLINE
void VerilatedSaifBuffer::emitWData(const uint32_t code, const WData* newvalp, const int bits) {
assert(m_owner.m_activity.count(code) && "Activity must be declared earlier");
VerilatedSaifActivityVar& activity = m_owner.m_activity.at(code);
assert(m_owner.m_activityAccumulators.at(m_fidx).m_activity.count(code) && "Activity must be declared earlier");
VerilatedSaifActivityVar& activity = m_owner.m_activityAccumulators.at(m_fidx).m_activity.at(code);
activity.emitWData(m_owner.currentTime(), newvalp, bits);
}

View File

@ -106,16 +106,22 @@ private:
class VerilatedSaifActivityScope final {
// MEMBERS
std::string m_scopeName{}; // name of the activity scope
std::vector<int32_t> m_childScopesIndices{}; // array indices of child scopes
std::vector<std::pair<uint32_t, std::string>>
m_childActivities{}; // children signals codes mapped to their names in the current scope
int32_t m_parentScopeIndex{-1}; // array index of parent scope
// absolute path to the scope
std::string m_scopePath{};
// name of the activity scope
std::string m_scopeName{};
// array indices of child scopes
std::vector<int32_t> m_childScopesIndices{};
// children signals codes mapped to their names in the current scope
std::vector<std::pair<uint32_t, std::string>> m_childActivities{};
// array index of parent scope
int32_t m_parentScopeIndex{-1};
public:
// CONSTRUCTORS
VerilatedSaifActivityScope(std::string name, int32_t parentScopeIndex = -1)
: m_scopeName{std::move(name)}
VerilatedSaifActivityScope(std::string scopePath, std::string name, int32_t parentScopeIndex = -1)
: m_scopePath{std::move(scopePath)}
, m_scopeName{std::move(name)}
, m_parentScopeIndex{parentScopeIndex} {}
VerilatedSaifActivityScope(VerilatedSaifActivityScope&&) = default;
@ -131,6 +137,7 @@ public:
VL_ATTR_ALWINLINE bool hasParent() const { return m_parentScopeIndex >= 0; }
// ACCESSORS
VL_ATTR_ALWINLINE const std::string& path() const { return m_scopePath; }
VL_ATTR_ALWINLINE const std::string& name() const { return m_scopeName; }
VL_ATTR_ALWINLINE const std::vector<int32_t>& childScopesIndices() const {
return m_childScopesIndices;
@ -146,6 +153,33 @@ private:
VL_UNCOPYABLE(VerilatedSaifActivityScope);
};
class VerilatedSaifActivityAccumulator {
// Give access to the private activities
friend class VerilatedSaifBuffer;
friend class VerilatedSaif;
// MEMBERS
// map of scopes paths to codes of activities inside
std::unordered_map<std::string, std::vector<std::pair<uint32_t, std::string>>> m_scopeToActivities;
// map of variables codes mapped to their activity objects
std::unordered_map<uint32_t, VerilatedSaifActivityVar> m_activity;
// memory pool for signals bits objects
std::vector<std::vector<VerilatedSaifActivityBit>> m_activityArena;
public:
// METHODS
void declare(uint32_t code, const std::string& absoluteScopePath, std::string variableName, int bits, bool array, int arraynum);
// CONSTRUCTORS
VerilatedSaifActivityAccumulator() = default;
VerilatedSaifActivityAccumulator(VerilatedSaifActivityAccumulator&&) = default;
VerilatedSaifActivityAccumulator& operator=(VerilatedSaifActivityAccumulator&&) = default;
private:
VL_UNCOPYABLE(VerilatedSaifActivityAccumulator);
};
//=============================================================================
// VerilatedSaif
// Base class to create a Verilator SAIF dump
@ -167,14 +201,14 @@ private:
int m_indent = 0; // indentation size in spaces
int32_t m_currentScope{-1}; // currently active scope
std::vector<VerilatedSaifActivityScope> m_scopes{}; // array of declared scopes
std::vector<int32_t> m_topScopes{}; // array of top scopes
std::unordered_map<uint32_t, VerilatedSaifActivityVar>
m_activity; // map of variables codes mapped to their activity objects
std::vector<std::vector<VerilatedSaifActivityBit>>
m_activityArena; // memory pool for signals bits objects
// currently active scope
int32_t m_currentScope{-1};
// array of declared scopes
std::vector<VerilatedSaifActivityScope> m_scopes{};
// array of top scopes
std::vector<int32_t> m_topScopes{};
// activity accumulators used to store variables statistics over simulation time
std::vector<VerilatedSaifActivityAccumulator> m_activityAccumulators{};
uint64_t m_time{0}; // total time of the currently traced simulation
@ -191,9 +225,10 @@ private:
void openInstanceScope(const std::string& instanceName);
void closeInstanceScope();
void printScopeActivities(const VerilatedSaifActivityScope& scope);
bool printScopeActivitiesFromAccumulatorIfPresent(const std::string& absoluteScopePath, VerilatedSaifActivityAccumulator& accumulator, bool anyNetWritten);
void openNetScope();
void closeNetScope();
bool printActivityStats(uint32_t activityCode, const char* activityName, bool anyNetValid);
bool printActivityStats(VerilatedSaifActivityVar& activity, const char* activityName, bool anyNetWritten);
void incrementIndent();
void decrementIndent();
@ -204,7 +239,7 @@ private:
void clearCurrentlyCollectedData();
void declare(uint32_t code, const char* name, const char* wirep, bool array, int arraynum,
void declare(uint32_t code, uint32_t fidx, const char* name, const char* wirep, bool array, int arraynum,
bool bussed, int msb, int lsb);
// CONSTRUCTORS
@ -236,11 +271,6 @@ public:
explicit VerilatedSaif(void* filep = nullptr);
~VerilatedSaif();
// ACCESSORS
// Set size in bytes after which new file should be created.
void rolloverSize(uint64_t size) VL_MT_SAFE { /* noop */
}
// METHODS - All must be thread safe
// Open the file; call isOpen() to see if errors
void open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex);
@ -304,10 +334,13 @@ class VerilatedSaifBuffer VL_NOT_FINAL {
friend VerilatedSaif::OffloadBuffer;
VerilatedSaif& m_owner; // Trace file owning this buffer. Required by subclasses.
uint32_t m_fidx; // Index of target activity accumulator
// CONSTRUCTOR
explicit VerilatedSaifBuffer(VerilatedSaif& owner)
: m_owner{owner} {}
: m_owner{owner}, m_fidx{0} {}
explicit VerilatedSaifBuffer(VerilatedSaif& owner, uint32_t fidx)
: m_owner{owner}, m_fidx{fidx} {}
virtual ~VerilatedSaifBuffer() = default;
//=========================================================================
@ -351,8 +384,7 @@ public:
/// just as if this object was deleted and reconstructed.
virtual void open(const char* filename) VL_MT_SAFE { m_sptrace.open(filename); }
void rolloverSize(size_t size) VL_MT_SAFE { /* noop */
}
void rolloverSize(size_t size) VL_MT_SAFE {/* noop */}
/// Close dump
void close() VL_MT_SAFE {