Handle correctly

This commit is contained in:
wsxarcher
2026-03-24 20:34:52 +01:00
parent fd2dfd6982
commit b28fde7e57
73 changed files with 2150 additions and 34 deletions
+14
View File
@@ -2926,6 +2926,20 @@ std::string VerilatedContext::dumpfileCheck() const VL_MT_SAFE_EXCLUDES(m_timeDu
}
return out;
}
void VerilatedContext::dumpvarsAdd(int level,
const std::string& hier) VL_MT_SAFE_EXCLUDES(m_timeDumpMutex) {
const VerilatedLockGuard lock{m_timeDumpMutex};
if (level == 0 && hier.empty()) {
m_dumpvars.clear();
} else {
m_dumpvars.emplace_back(level, hier);
}
}
std::vector<VerilatedTraceDumpvarsEntry>
VerilatedContext::dumpvars() const VL_MT_SAFE_EXCLUDES(m_timeDumpMutex) {
const VerilatedLockGuard lock{m_timeDumpMutex};
return m_dumpvars;
}
void VerilatedContext::errorCount(int val) VL_MT_SAFE {
const VerilatedLockGuard lock{m_mutex};
m_s.m_errorCount = val;
+16
View File
@@ -110,6 +110,15 @@ class VerilatedVcd;
class VerilatedVcdC;
class VerilatedVcdSc;
struct VerilatedTraceDumpvarsEntry final {
int m_level;
std::string m_hier;
VerilatedTraceDumpvarsEntry(int level, const std::string& hier)
: m_level{level}
, m_hier{hier} {}
};
//=========================================================================
// Basic types
@@ -404,6 +413,8 @@ protected:
mutable VerilatedMutex m_timeDumpMutex; // Protect misc slow strings
std::string m_timeFormatSuffix VL_GUARDED_BY(m_timeDumpMutex); // $timeformat printf format
std::string m_dumpfile VL_GUARDED_BY(m_timeDumpMutex); // $dumpfile setting
std::vector<VerilatedTraceDumpvarsEntry>
m_dumpvars VL_GUARDED_BY(m_timeDumpMutex); // $dumpvars settings
struct NonSerialized final { // Non-serialized information
// These are reloaded from on command-line settings, so do not need to persist
@@ -656,6 +667,11 @@ public:
void dumpfile(const std::string& flag) VL_MT_SAFE_EXCLUDES(m_timeDumpMutex);
std::string dumpfileCheck() const VL_MT_SAFE_EXCLUDES(m_timeDumpMutex);
// Internal: $dumpvars
void dumpvarsAdd(int level, const std::string& hier) VL_MT_SAFE_EXCLUDES(m_timeDumpMutex);
std::vector<VerilatedTraceDumpvarsEntry> dumpvars() const
VL_MT_SAFE_EXCLUDES(m_timeDumpMutex);
// Internal: --prof-exec related settings
uint64_t profExecStart() const VL_MT_SAFE { return m_ns.m_profExecStart; }
void profExecStart(uint64_t flag) VL_MT_SAFE;
+2 -1
View File
@@ -220,8 +220,9 @@ void VerilatedFst::declare(uint32_t code, const char* name, int dtypenum,
const int bits = ((msb > lsb) ? (msb - lsb) : (lsb - msb)) + 1;
const std::string hierarchicalName = m_prefixStack.back().first + name;
const auto dumpvarsPath = Super::dumpvarsPath(m_prefixStack, name);
const bool enabled = Super::declCode(code, hierarchicalName, bits);
const bool enabled = Super::declCode(code, dumpvarsPath, bits);
if (!enabled) return;
assert(hierarchicalName.rfind(' ') != std::string::npos);
+2 -1
View File
@@ -539,8 +539,9 @@ void VerilatedSaif::declare(const uint32_t code, uint32_t fidx, const char* name
const int bits = ((msb > lsb) ? (msb - lsb) : (lsb - msb)) + 1;
const std::string hierarchicalName = m_prefixStack.back().first + name;
const auto dumpvarsPath = Super::dumpvarsPath(m_prefixStack, name);
if (!Super::declCode(code, hierarchicalName, bits)) return;
if (!Super::declCode(code, dumpvarsPath, bits)) return;
std::string variableName = lastWord(hierarchicalName);
m_currentScope->addActivityVar(code, variableName);
+72 -2
View File
@@ -313,7 +313,7 @@ private:
uint32_t m_maxBits = 0; // Number of bits in the widest signal
void* m_initUserp = nullptr; // The callback userp of the instance currently being initialized
// TODO: Should keep this as a Trie, that is how it's accessed all the time.
std::vector<std::pair<int, std::string>> m_dumpvars; // dumpvar() entries
std::vector<VerilatedTraceDumpvarsEntry> m_dumpvars; // dumpvar() entries
double m_timeRes = 1e-9; // Time resolution (ns/ms etc)
double m_timeUnit = 1e-0; // Time units (ns/ms etc)
uint64_t m_timeLastDump = 0; // Last time we did a dump
@@ -371,6 +371,59 @@ private:
VL_UNCOPYABLE(VerilatedTrace);
protected:
struct DumpvarsPath final {
std::string m_name;
std::vector<size_t> m_scopeEndps;
static bool countsAsScopeLevel(VerilatedTracePrefixType type) {
return type == VerilatedTracePrefixType::SCOPE_MODULE
|| type == VerilatedTracePrefixType::SCOPE_INTERFACE
|| type == VerilatedTracePrefixType::ROOTIO_WRAPPER;
}
static char separator(VerilatedTracePrefixType type) {
return (type == VerilatedTracePrefixType::ARRAY_PACKED
|| type == VerilatedTracePrefixType::ARRAY_UNPACKED)
? '\0'
: '.';
}
static std::string trimPrefix(const std::string& prefix) {
if (!prefix.empty() && prefix.back() == ' ') {
return prefix.substr(0, prefix.size() - 1);
}
return prefix;
}
void append(const std::string& piece, VerilatedTracePrefixType type,
bool countLevel = true) {
if (piece.empty()) return;
const char sep = separator(type);
if (sep && !m_name.empty()) m_name += sep;
m_name += piece;
if (countLevel && countsAsScopeLevel(type)) m_scopeEndps.push_back(m_name.size());
}
bool matchesPrefix(const std::string& prefix) const {
if (prefix.empty()) return true;
if (m_name.compare(0, prefix.size(), prefix) != 0) return false;
return prefix.size() >= m_name.size() || m_name[prefix.size()] == '.';
}
int scopeLevelsBelow(size_t prefixLen) const {
int levels = 0;
for (const size_t endp : m_scopeEndps) {
if (endp > prefixLen) ++levels;
}
return levels;
}
bool matches(const VerilatedTraceDumpvarsEntry& entry) const {
if (!matchesPrefix(entry.m_hier)) return false;
return entry.m_level <= 0 || scopeLevelsBelow(entry.m_hier.size()) < entry.m_level;
}
};
//=========================================================================
// Internals available to format-specific implementations
@@ -390,7 +443,7 @@ protected:
void traceInit() VL_MT_UNSAFE;
// Declare new signal and return true if enabled
bool declCode(uint32_t code, const std::string& declName, uint32_t bits);
bool declCode(uint32_t code, const DumpvarsPath& path, uint32_t bits);
void closeBase();
void flushBase();
@@ -405,6 +458,23 @@ protected:
return str.substr(idx + 1);
}
static DumpvarsPath dumpvarsPath(
const std::vector<std::pair<std::string, VerilatedTracePrefixType>>& prefixStack,
const char* namep) {
DumpvarsPath out;
std::string prev;
for (size_t i = 1; i < prefixStack.size(); ++i) {
const std::string curr = DumpvarsPath::trimPrefix(prefixStack[i].first);
if (curr.size() < prev.size()) continue;
std::string piece = curr.substr(prev.size());
if (!piece.empty() && piece.front() == ' ') piece.erase(0, 1);
out.append(piece, prefixStack[i].second);
prev = curr;
}
out.append(namep ? namep : "", prefixStack.back().second, false);
return out;
}
//=========================================================================
// Virtual functions to be provided by the format-specific implementation
+6 -23
View File
@@ -369,7 +369,8 @@ void VerilatedTrace<VL_SUB_T, VL_BUF_T>::traceInit() VL_MT_UNSAFE {
}
template <>
bool VerilatedTrace<VL_SUB_T, VL_BUF_T>::declCode(uint32_t code, const std::string& declName,
bool VerilatedTrace<VL_SUB_T, VL_BUF_T>::declCode(uint32_t code,
const DumpvarsPath& path,
uint32_t bits) {
if (VL_UNCOVERABLE(!code)) {
VL_FATAL_MT(__FILE__, __LINE__, "", "Internal: internal trace problem, code 0 is illegal");
@@ -377,21 +378,8 @@ bool VerilatedTrace<VL_SUB_T, VL_BUF_T>::declCode(uint32_t code, const std::stri
// To keep it simple, this is O(enables * signals), but we expect few enables
bool enabled = false;
if (m_dumpvars.empty()) enabled = true;
for (const auto& item : m_dumpvars) {
const int dumpvarsLevel = item.first;
const char* dvp = item.second.c_str();
const char* np = declName.c_str();
while (*dvp && *dvp == *np) {
++dvp;
++np;
}
if (*dvp) continue; // Didn't match dumpvar item
if (*np && *np != ' ') continue; // e.g. "t" isn't a match for "top"
int levels = 0;
while (*np) {
if (*np++ == ' ') ++levels;
}
if (levels > dumpvarsLevel) continue; // Too deep
for (const auto& entry : m_dumpvars) {
if (!path.matches(entry)) continue;
// We only need to set first code word if it's a multicode signal
// as that's all we'll check for later
if (m_sigs_enabledVec.size() <= code) m_sigs_enabledVec.resize((code + 1024) * 2);
@@ -434,15 +422,10 @@ void VerilatedTrace<VL_SUB_T, VL_BUF_T>::set_time_resolution(const std::string&
}
template <>
void VerilatedTrace<VL_SUB_T, VL_BUF_T>::dumpvars(int level, const std::string& hier) VL_MT_SAFE {
if (level == 0) {
if (level == 0 && hier.empty()) {
m_dumpvars.clear(); // empty = everything on
} else {
// Convert Verilog . separators to trace space separators
std::string hierSpaced = hier;
for (auto& i : hierSpaced) {
if (i == '.') i = ' ';
}
m_dumpvars.emplace_back(level, hierSpaced);
m_dumpvars.emplace_back(level, hier);
}
}
+2 -1
View File
@@ -383,8 +383,9 @@ void VerilatedVcd::declare(uint32_t code, const char* name, const char* wirep, b
const int bits = ((msb > lsb) ? (msb - lsb) : (lsb - msb)) + 1;
const std::string hierarchicalName = m_prefixStack.back().first + name;
const auto dumpvarsPath = Super::dumpvarsPath(m_prefixStack, name);
const bool enabled = Super::declCode(code, hierarchicalName, bits);
const bool enabled = Super::declCode(code, dumpvarsPath, bits);
if (m_suffixes.size() <= nextCode() * VL_TRACE_SUFFIX_ENTRY_SIZE) {
m_suffixes.resize(nextCode() * VL_TRACE_SUFFIX_ENTRY_SIZE * 2, 0);