diff --git a/include/verilated.cpp b/include/verilated.cpp index 158cdbac3..1f7987af6 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -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 +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; diff --git a/include/verilated.h b/include/verilated.h index 909956d82..a7cd7d734 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -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 + 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 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; diff --git a/include/verilated_fst_c.cpp b/include/verilated_fst_c.cpp index a0f636dc4..c47dc93ca 100644 --- a/include/verilated_fst_c.cpp +++ b/include/verilated_fst_c.cpp @@ -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); diff --git a/include/verilated_saif_c.cpp b/include/verilated_saif_c.cpp index abff785ce..09e2df1df 100644 --- a/include/verilated_saif_c.cpp +++ b/include/verilated_saif_c.cpp @@ -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); diff --git a/include/verilated_trace.h b/include/verilated_trace.h index 15e3cd964..c107a76cc 100644 --- a/include/verilated_trace.h +++ b/include/verilated_trace.h @@ -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> m_dumpvars; // dumpvar() entries + std::vector 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 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>& 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 diff --git a/include/verilated_trace_imp.h b/include/verilated_trace_imp.h index 635e3e897..758d97dfa 100644 --- a/include/verilated_trace_imp.h +++ b/include/verilated_trace_imp.h @@ -369,7 +369,8 @@ void VerilatedTrace::traceInit() VL_MT_UNSAFE { } template <> -bool VerilatedTrace::declCode(uint32_t code, const std::string& declName, +bool VerilatedTrace::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::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::set_time_resolution(const std::string& } template <> void VerilatedTrace::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); } } diff --git a/include/verilated_vcd_c.cpp b/include/verilated_vcd_c.cpp index d36cb85da..d3086afe3 100644 --- a/include/verilated_vcd_c.cpp +++ b/include/verilated_vcd_c.cpp @@ -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); diff --git a/src/V3AstNodeStmt.h b/src/V3AstNodeStmt.h index 76f32b64a..d5eb0b884 100644 --- a/src/V3AstNodeStmt.h +++ b/src/V3AstNodeStmt.h @@ -636,6 +636,8 @@ class AstDumpCtl final : public AstNodeStmt { // $dumpon etc // Parents: expr // @astgen op1 := exprp : Optional[AstNodeExpr] // Expression based on type of statement + // @astgen op2 := scopeNamep : Optional[AstScopeName] // Scope of the $dumpvars call site + // @astgen op3 := targetsp : List[AstNode] // Optional scope/signal targets for $dumpvars const VDumpCtlType m_ctlType; // Type of operation public: AstDumpCtl(FileLine* fl, VDumpCtlType ctlType, AstNodeExpr* exprp = nullptr) @@ -649,8 +651,9 @@ public: bool isOutputter() override { return true; } bool isPredictOptimizable() const override { return false; } bool isPure() override { return false; } - virtual bool cleanOut() const { return true; } - bool sameNode(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* samep) const override { + return ctlType() == VN_DBG_AS(samep, DumpCtl)->ctlType(); + } VDumpCtlType ctlType() const { return m_ctlType; } }; class AstEventControl final : public AstNodeStmt { diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index b1b02ca0a..b5dd82aad 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -377,6 +377,12 @@ class BeginVisitor final : public VNVisitor { // If there's a %m in the display text, we add a special node that will contain the name() // Similar code in V3Inline if (nodep->user1SetOnce()) return; // Don't double-add text's + // $dumpvars scope names resolve relative to the enclosing module, + // not the block, so don't add block scope components for them. + if (VN_IS(nodep->backp(), DumpCtl)) { + iterateChildren(nodep); + return; + } // DPI svGetScope doesn't include function name, but %m does const std::string scname = nodep->forFormat() ? m_displayScope : m_namedScope; // To keep correct visual order, must add before exising diff --git a/src/V3EmitCFunc.h b/src/V3EmitCFunc.h index aeab8fe8e..05272ee74 100644 --- a/src/V3EmitCFunc.h +++ b/src/V3EmitCFunc.h @@ -895,6 +895,62 @@ public: if (nodep->addNewline()) text += "\n"; displayNode(nodep, nodep->fmtp(), text, nodep->fmtp()->exprsp(), false); } + static bool dumpvarsHasScopePrefix(const string& target, const string& scope) { + return target == scope + || (target.length() > scope.length() && target.compare(0, scope.length(), scope) == 0 + && target[scope.length()] == '.'); + } + + static string dumpvarsHierPath(const string& scope, const string& target) { + if (target.empty()) return scope; + if (scope.empty() || dumpvarsHasScopePrefix(target, scope)) return target; + return scope + "." + target; + } + + // Emit C++ code that registers a $dumpvars filter at runtime. + // Builds the full hierarchy path from vlSymsp->name() and the given suffix, + // then calls dumpvarsAdd with the specified level expression. + void emitDumpVarsAdd(const AstDumpCtl* nodep, const string& hierPath, + const string& levelExpr) { + putns(nodep, "{ std::string __vlDvHier{vlSymsp->name()};\n"); + if (!hierPath.empty()) { + puts("if (!__vlDvHier.empty()) __vlDvHier += '.';\n"); + puts("__vlDvHier += \""); + puts(V3OutFormatter::quoteNameControls(hierPath)); + puts("\";\n"); + } + puts("vlSymsp->_vm_contextp__->dumpvarsAdd("); + puts(levelExpr); + puts(", __vlDvHier); }\n"); + } + // Emit $dumpvars filter logic when scope info is available. + void emitDumpVarsWithScope(AstDumpCtl* nodep) { + UASSERT_OBJ(nodep->scopeNamep(), nodep, "$dumpvars missing AstScopeName"); + const string scope = nodep->scopeNamep()->scopePrettySymName(); + // Resolve the level expression (constant or runtime) + const AstConst* const levelp = VN_CAST(nodep->exprp(), Const); + string levelExpr; + if (levelp) { + levelExpr = cvtToStr(levelp->toUInt()); + } else { + putns(nodep, "{ const int __vlDvLevel = "); + iterateConst(nodep->exprp()); + puts(";\n"); + levelExpr = "__vlDvLevel"; + } + // Emit one dumpvarsAdd call per target, or one for the scope itself + if (nodep->targetsp()) { + for (AstNode* tp = nodep->targetsp(); tp; tp = tp->nextp()) { + const string target = VN_AS(tp, Text)->text(); + emitDumpVarsAdd(nodep, dumpvarsHierPath(scope, target), levelExpr); + } + } else { + emitDumpVarsAdd(nodep, scope, levelExpr); + } + if (!levelp) puts("}\n"); + putns(nodep, "vlSymsp->_traceDumpClose();\n"); + putns(nodep, "vlSymsp->_traceDumpOpen();\n"); + } void visit(AstDumpCtl* nodep) override { switch (nodep->ctlType()) { case VDumpCtlType::FILE: @@ -903,9 +959,8 @@ public: puts(");\n"); break; case VDumpCtlType::VARS: - // We ignore number of levels to dump in exprp() if (v3Global.opt.trace()) { - putns(nodep, "vlSymsp->_traceDumpOpen();\n"); + emitDumpVarsWithScope(nodep); } else { putns(nodep, "VL_PRINTF_MT(\"-Info: "); puts(V3OutFormatter::quoteNameControls(protect(nodep->fileline()->filename()))); diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index 58bc6c621..e4e014208 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -1215,6 +1215,10 @@ void EmitCSyms::emitSymImp(const AstNetlist* netlistp) { puts("const VerilatedLockGuard lock{__Vm_dumperMutex};\n"); puts("if (VL_UNLIKELY(!__Vm_dumperp)) {\n"); puts("__Vm_dumperp = new " + v3Global.opt.traceClassLang() + "();\n"); + puts("const auto dvars = _vm_contextp__->dumpvars();\n"); + puts("for (const auto& dv : dvars) {\n"); + puts("__Vm_dumperp->dumpvars(dv.m_level, dv.m_hier);\n"); + puts("}\n"); puts("__Vm_modelp->trace(__Vm_dumperp, 0, 0);\n"); puts("const std::string dumpfile = _vm_contextp__->dumpfileCheck();\n"); puts("__Vm_dumperp->open(dumpfile.c_str());\n"); diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 9a39a4afd..629fd074a 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -80,6 +80,27 @@ VL_DEFINE_DEBUG_FUNCTIONS; +static string dumpvarsTargetText(const AstNode* nodep) { + if (!nodep) return ""; + if (const AstText* const textp = VN_CAST(nodep, Text)) return textp->text(); + if (const AstCellRef* const refp = VN_CAST(nodep, CellRef)) return refp->name(); + if (const AstCellArrayRef* const refp = VN_CAST(nodep, CellArrayRef)) return refp->name(); + if (const AstParseRef* const refp = VN_CAST(nodep, ParseRef)) return refp->prettyName(); + if (const AstVarRef* const refp = VN_CAST(nodep, VarRef)) return refp->name(); + if (const AstVarXRef* const refp = VN_CAST(nodep, VarXRef)) { + if (refp->dotted().empty()) return refp->name(); + return refp->dotted() + "." + refp->name(); + } + if (const AstDot* const dotp = VN_CAST(nodep, Dot)) { + const string lhs = dumpvarsTargetText(dotp->lhsp()); + const string rhs = dumpvarsTargetText(dotp->rhsp()); + if (lhs.empty()) return rhs; + if (rhs.empty()) return lhs; + return lhs + "." + rhs; + } + return nodep->prettyName(); +} + static string extractDottedPath(AstNode* nodep, bool& hasPartSelect) { if (AstParseRef* const refp = VN_CAST(nodep, ParseRef)) { return refp->name(); @@ -6029,6 +6050,37 @@ class LinkDotResolveVisitor final : public VNVisitor { UINFO(5, indent() << "visit " << nodep); iterateChildren(nodep); } + void visit(AstDumpCtl* nodep) override { + LINKDOT_VISIT_START(); + UINFO(5, indent() << "visit " << nodep); + if (nodep->exprp()) iterateAndNextNull(nodep->exprp()); + AstNode* targetsp = nodep->targetsp(); + if (!targetsp) return; + // Resolve each target from its parse-tree form (AstParseRef/AstDot) + // into a plain text name, validating it against the symbol table. + VNRelinker relinker; + targetsp->unlinkFrBackWithNext(&relinker); + AstNode* newTargetsp = nullptr; + for (AstNode* targetp = targetsp; targetp;) { + AstNode* const nextp = targetp->nextp(); + if (nextp) nextp->unlinkFrBackWithNext(); + const string target = dumpvarsTargetText(targetp); + if (!target.empty() && m_curSymp) { + string baddot; + VSymEnt* matchSymp = nullptr; + if (!m_statep->findDotted(nodep->fileline(), m_curSymp, target, + baddot, matchSymp, true)) { + UINFO(5, "$dumpvars target '" << target + << "' not found in hierarchy" << endl); + } + } + VL_DO_DANGLING(pushDeletep(targetp), targetp); + newTargetsp + = AstNode::addNextNull(newTargetsp, new AstText{nodep->fileline(), target}); + targetp = nextp; + } + relinker.relink(newTargetsp); + } void visit(AstCellArrayRef* nodep) override { LINKDOT_VISIT_START(); UINFO(5, indent() << "visit " << nodep); diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index 3690fdb39..09c5475eb 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -461,6 +461,14 @@ class LinkResolveVisitor final : public VNVisitor { } } + void visit(AstDumpCtl* nodep) override { + if (nodep->ctlType() == VDumpCtlType::VARS && !nodep->scopeNamep()) { + // Attach AstScopeName so V3Scope/V3Inline build the call-site scope path + nodep->scopeNamep(new AstScopeName{nodep->fileline(), false}); + } + iterateChildren(nodep); + } + void visit(AstUdpTable* nodep) override { UINFO(5, "UDPTABLE " << nodep); if (!v3Global.opt.bboxUnsup()) { diff --git a/src/V3ParseGrammar.cpp b/src/V3ParseGrammar.cpp index fdc0e218b..5ba13aba5 100644 --- a/src/V3ParseGrammar.cpp +++ b/src/V3ParseGrammar.cpp @@ -96,6 +96,13 @@ AstArg* V3ParseGrammar::argWrapList(AstNodeExpr* nodep) { return outp; } +AstDumpCtl* V3ParseGrammar::createDumpVarsScoped(FileLine* fl, AstNodeExpr* levelp, + AstNode* exprListp) { + AstDumpCtl* const resultp = new AstDumpCtl{fl, VDumpCtlType::VARS, levelp}; + resultp->addTargetsp(exprListp); + return resultp; +} + AstAssignW* V3ParseGrammar::createSupplyExpr(FileLine* fileline, const string& name, int value) { AstAssignW* assignp = new AstAssignW{fileline, new AstParseRef{fileline, name}, value ? new AstConst{fileline, AstConst::All1{}} diff --git a/src/V3ParseGrammar.h b/src/V3ParseGrammar.h index 276ed2ffb..5f4f28b86 100644 --- a/src/V3ParseGrammar.h +++ b/src/V3ParseGrammar.h @@ -67,6 +67,8 @@ public: // METHODS AstArg* argWrapList(AstNodeExpr* nodep) VL_MT_DISABLED; + AstDumpCtl* createDumpVarsScoped(FileLine* fl, AstNodeExpr* levelp, + AstNode* exprListp) VL_MT_DISABLED; bool allTracingOn(const FileLine* fl) const { return v3Global.opt.trace() && m_tracingParse && fl->tracingOn(); } diff --git a/src/V3Task.cpp b/src/V3Task.cpp index f92d11c5b..32ae1ee83 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -1598,6 +1598,29 @@ class TaskVisitor final : public VNVisitor { beginp = createInlinedFTask(nodep, namePrefix, outvscp); ++m_statInlines; } + // When a function call has inlinedDots (from V3Inline's cell hierarchy), + // propagate that info to: + // 1. Any AstDumpCtl/AstScopeName in the inlined body (direct $dumpvars) + // 2. Any nested AstNodeFTaskRef in the inlined body (indirect $dumpvars) + if (!nodep->inlinedDots().empty()) { + const string& callerDots = nodep->inlinedDots(); + string dots = callerDots; + string::size_type pos; + while ((pos = dots.find('.')) != string::npos) dots.replace(pos, 1, "__DOT__"); + const string scopePath = "__DOT__"s + m_scopep->name() + "__DOT__" + dots; + beginp->foreachAndNext([&](AstDumpCtl* dcp) { + if (AstScopeName* const snp = dcp->scopeNamep()) { + snp->scopeAttr(scopePath); + snp->scopeEntr(scopePath); + } + }); + // Propagate inlinedDots to nested task references + beginp->foreachAndNext([&](AstNodeFTaskRef* refp) { + if (refp->inlinedDots().empty()) { + refp->inlinedDots(callerDots); + } + }); + } if (VN_IS(nodep, New)) { // New not legal as while() condition insertBeforeStmt(nodep, beginp); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index eec39fe8a..8545842fb 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -6202,7 +6202,14 @@ class WidthVisitor final : public VNVisitor { } void visit(AstDumpCtl* nodep) override { assertAtStatement(nodep); - if (nodep->exprp()) iterateCheckString(nodep, "LHS", nodep->exprp(), BOTH); + if (nodep->exprp()) { + if (nodep->ctlType() == VDumpCtlType::VARS) { + // $dumpvars level argument is an integer + userIterateAndNext(nodep->exprp(), WidthVP{SELF, BOTH}.p()); + } else { + iterateCheckString(nodep, "LHS", nodep->exprp(), BOTH); + } + } } void visit(AstFOpen* nodep) override { // Although a system function in IEEE, here a statement which sets the file pointer (MCD) diff --git a/src/verilog.y b/src/verilog.y index bb23f452c..38ae6e802 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -4223,7 +4223,7 @@ system_t_stmt_call: // IEEE: part of system_tf_call (as task returni | yD_DUMPVARS parenE { $$ = new AstDumpCtl{$1, VDumpCtlType::VARS, new AstConst{$1, 0}}; } | yD_DUMPVARS '(' expr ')' { $$ = new AstDumpCtl{$1, VDumpCtlType::VARS, $3}; } - | yD_DUMPVARS '(' expr ',' exprList ')' { $$ = new AstDumpCtl{$1, VDumpCtlType::VARS, $3}; DEL($5); } + | yD_DUMPVARS '(' expr ',' exprList ')' { $$ = GRAMMARP->createDumpVarsScoped($1, $3, $5); } | yD_DUMPALL parenE { $$ = new AstDumpCtl{$1, VDumpCtlType::ALL}; } | yD_DUMPALL '(' expr ')' { $$ = new AstDumpCtl{$1, VDumpCtlType::ALL}; DEL($3); } | yD_DUMPFLUSH parenE { $$ = new AstDumpCtl{$1, VDumpCtlType::FLUSH}; } diff --git a/test_regress/t/t_trace_dumpvars.out b/test_regress/t/t_trace_dumpvars.out new file mode 100644 index 000000000..652dd879a --- /dev/null +++ b/test_regress/t/t_trace_dumpvars.out @@ -0,0 +1,28 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module $rootio $end + $upscope $end + $scope module t $end + $var wire 1 % clk $end + $var wire 32 " cyc [31:0] $end + $scope module sub_a $end + $var wire 32 & ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 # value [31:0] $end + $upscope $end + $scope module sub_b $end + $var wire 32 ' ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 $ value [31:0] $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 " +b00000000000000000000000000001010 # +b00000000000000000000000000010100 $ +0% +b00000000000000000000000000001010 & +b00000000000000000000000000010100 ' diff --git a/test_regress/t/t_trace_dumpvars.py b/test_regress/t/t_trace_dumpvars.py new file mode 100644 index 000000000..1eaecdb79 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --trace-vcd']) + +test.execute() + +test.vcd_identical(test.trace_filename, test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars.v b/test_regress/t/t_trace_dumpvars.v new file mode 100644 index 000000000..6a65753e0 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars.v @@ -0,0 +1,38 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +module t( + input clk +); + int cyc; + + sub #(10) sub_a(.*); + sub #(20) sub_b(.*); + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + initial begin + $dumpfile(`STRINGIFY(`TEST_DUMPFILE)); + $dumpvars(0); + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; +endmodule diff --git a/test_regress/t/t_trace_dumpvars_abs_scope.out b/test_regress/t/t_trace_dumpvars_abs_scope.out new file mode 100644 index 000000000..0a31846b7 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_abs_scope.out @@ -0,0 +1,29 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module $rootio $end + $upscope $end + $scope module t $end + $scope module sub_a $end + $var wire 32 ( ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 # value [31:0] $end + $scope module deep_i $end + $var wire 32 ) ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 $ inner [31:0] $end + $upscope $end + $upscope $end + $scope module sub_b $end + $scope module deep_i $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 " +b00000000000000000000000000001010 # +b00000000000000000000000000001011 $ +b00000000000000000000000000001010 ( +b00000000000000000000000000001011 ) diff --git a/test_regress/t/t_trace_dumpvars_abs_scope.py b/test_regress/t/t_trace_dumpvars_abs_scope.py new file mode 100644 index 000000000..1eaecdb79 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_abs_scope.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --trace-vcd']) + +test.execute() + +test.vcd_identical(test.trace_filename, test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars_abs_scope.v b/test_regress/t/t_trace_dumpvars_abs_scope.v new file mode 100644 index 000000000..aa9d28fa2 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_abs_scope.v @@ -0,0 +1,50 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +module t( + input clk +); + int cyc; + + sub #(10) sub_a(.*); + sub #(20) sub_b(.*); + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + initial begin + $dumpfile(`STRINGIFY(`TEST_DUMPFILE)); + // Test $dumpvars with absolute hierarchical scope path + $dumpvars(0, t.sub_a); + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; + + deep #(ADD + 1) deep_i(.*); +endmodule + +module deep #( + parameter int ADD +)( + input int cyc +); + int inner; + always_comb inner = cyc + ADD; +endmodule diff --git a/test_regress/t/t_trace_dumpvars_add_module.py b/test_regress/t/t_trace_dumpvars_add_module.py new file mode 100644 index 000000000..51c1f9091 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_add_module.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --timing --trace-vcd']) + +test.execute() + +test.vcd_identical(test.obj_dir + '/simx0.vcd', test.t_dir + '/t_trace_dumpvars_add_module_0.out') +test.vcd_identical(test.obj_dir + '/simx1.vcd', test.t_dir + '/t_trace_dumpvars_add_module_1.out') + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars_add_module.v b/test_regress/t/t_trace_dumpvars_add_module.v new file mode 100644 index 000000000..26f7acbac --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_add_module.v @@ -0,0 +1,58 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +module t( +); + logic clk; + int cyc; + + sub #(10) sub_a(.*); + sub #(20) sub_b(.*); + + initial begin + clk = 0; + forever #1 clk = !clk; + end + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 1) begin + $dumpfile({`STRINGIFY(`TEST_OBJ_DIR), "/simx1.vcd"}); + $dumpvars(0, sub_b); + end + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + initial begin + $dumpfile({`STRINGIFY(`TEST_OBJ_DIR), "/simx0.vcd"}); + $dumpvars(1, sub_a); + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; + + deep #(ADD + 1) deep_i(.*); +endmodule + +module deep #( + parameter int ADD +)( + input int cyc +); + int inner; + always_comb inner = cyc + ADD; +endmodule diff --git a/test_regress/t/t_trace_dumpvars_add_module_0.out b/test_regress/t/t_trace_dumpvars_add_module_0.out new file mode 100644 index 000000000..7a2a58e70 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_add_module_0.out @@ -0,0 +1,26 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module t $end + $scope module sub_a $end + $var wire 32 ( ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 # value [31:0] $end + $scope module deep_i $end + $upscope $end + $upscope $end + $scope module sub_b $end + $scope module deep_i $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 " +b00000000000000000000000000001010 # +b00000000000000000000000000001010 ( +#1 +b00000000000000000000000000000001 " +b00000000000000000000000000001011 # +#2 diff --git a/test_regress/t/t_trace_dumpvars_add_module_1.out b/test_regress/t/t_trace_dumpvars_add_module_1.out new file mode 100644 index 000000000..023264f2f --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_add_module_1.out @@ -0,0 +1,53 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module t $end + $scope module sub_a $end + $var wire 32 ( ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 # value [31:0] $end + $scope module deep_i $end + $upscope $end + $upscope $end + $scope module sub_b $end + $var wire 32 * ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 % value [31:0] $end + $scope module deep_i $end + $var wire 32 + ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 & inner [31:0] $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#3 +b00000000000000000000000000000010 " +b00000000000000000000000000001100 # +b00000000000000000000000000010110 % +b00000000000000000000000000010111 & +b00000000000000000000000000001010 ( +b00000000000000000000000000010100 * +b00000000000000000000000000010101 + +#5 +b00000000000000000000000000000011 " +b00000000000000000000000000001101 # +b00000000000000000000000000010111 % +b00000000000000000000000000011000 & +#7 +b00000000000000000000000000000100 " +b00000000000000000000000000001110 # +b00000000000000000000000000011000 % +b00000000000000000000000000011001 & +#9 +b00000000000000000000000000000101 " +b00000000000000000000000000001111 # +b00000000000000000000000000011001 % +b00000000000000000000000000011010 & +#11 +b00000000000000000000000000000110 " +b00000000000000000000000000010000 # +b00000000000000000000000000011010 % +b00000000000000000000000000011011 & + diff --git a/test_regress/t/t_trace_dumpvars_func.out b/test_regress/t/t_trace_dumpvars_func.out new file mode 100644 index 000000000..73b55a8a8 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_func.out @@ -0,0 +1,29 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module $rootio $end + $upscope $end + $scope module t $end + $scope module sub_a $end + $var wire 32 ( ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 # value [31:0] $end + $scope module deep_i $end + $upscope $end + $upscope $end + $scope module sub_b $end + $var wire 32 * ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 % value [31:0] $end + $scope module deep_i $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 " +b00000000000000000000000000001010 # +b00000000000000000000000000010100 % +b00000000000000000000000000001010 ( +b00000000000000000000000000010100 * diff --git a/test_regress/t/t_trace_dumpvars_func.py b/test_regress/t/t_trace_dumpvars_func.py new file mode 100644 index 000000000..1eaecdb79 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_func.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --trace-vcd']) + +test.execute() + +test.vcd_identical(test.trace_filename, test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars_func.v b/test_regress/t/t_trace_dumpvars_func.v new file mode 100644 index 000000000..1a5def5eb --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_func.v @@ -0,0 +1,61 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +function int get_trace_level; + return 1; +endfunction + +function void varsdump; + $dumpvars(get_trace_level()); +endfunction + +function void setup_trace; + $dumpfile(`STRINGIFY(`TEST_DUMPFILE)); + varsdump(); +endfunction + +module t( + input clk +); + int cyc; + + sub #(10) sub_a(.*); + sub #(20) sub_b(.*); + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; + + initial begin + setup_trace; + end + + deep #(ADD + 1) deep_i(.*); +endmodule + +module deep #( + parameter int ADD +)( + input int cyc +); + int inner; + always_comb inner = cyc + ADD; +endmodule diff --git a/test_regress/t/t_trace_dumpvars_hier_scope.out b/test_regress/t/t_trace_dumpvars_hier_scope.out new file mode 100644 index 000000000..033f569da --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_hier_scope.out @@ -0,0 +1,24 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module $rootio $end + $upscope $end + $scope module t $end + $scope module sub_a $end + $scope module deep_i $end + $var wire 32 ) ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 $ inner [31:0] $end + $upscope $end + $upscope $end + $scope module sub_b $end + $scope module deep_i $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 " +b00000000000000000000000000001011 $ +b00000000000000000000000000001011 ) diff --git a/test_regress/t/t_trace_dumpvars_hier_scope.py b/test_regress/t/t_trace_dumpvars_hier_scope.py new file mode 100644 index 000000000..1eaecdb79 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_hier_scope.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --trace-vcd']) + +test.execute() + +test.vcd_identical(test.trace_filename, test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars_hier_scope.v b/test_regress/t/t_trace_dumpvars_hier_scope.v new file mode 100644 index 000000000..899bbeea9 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_hier_scope.v @@ -0,0 +1,50 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +module t( + input clk +); + int cyc; + + sub #(10) sub_a(.*); + sub #(20) sub_b(.*); + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + initial begin + $dumpfile(`STRINGIFY(`TEST_DUMPFILE)); + // Test $dumpvars with hierarchical scope: level 1 limits to direct signals of sub_a.deep_i + $dumpvars(1, sub_a.deep_i); + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; + + deep #(ADD + 1) deep_i(.*); +endmodule + +module deep #( + parameter int ADD +)( + input int cyc +); + int inner; + always_comb inner = cyc + ADD; +endmodule diff --git a/test_regress/t/t_trace_dumpvars_level.out b/test_regress/t/t_trace_dumpvars_level.out new file mode 100644 index 000000000..b64676095 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_level.out @@ -0,0 +1,22 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module $rootio $end + $upscope $end + $scope module t $end + $var wire 1 ' clk $end + $var wire 32 " cyc [31:0] $end + $scope module sub_a $end + $scope module deep_i $end + $upscope $end + $upscope $end + $scope module sub_b $end + $scope module deep_i $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 " +0' diff --git a/test_regress/t/t_trace_dumpvars_level.py b/test_regress/t/t_trace_dumpvars_level.py new file mode 100644 index 000000000..1eaecdb79 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_level.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --trace-vcd']) + +test.execute() + +test.vcd_identical(test.trace_filename, test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars_level.v b/test_regress/t/t_trace_dumpvars_level.v new file mode 100644 index 000000000..55c3ccc64 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_level.v @@ -0,0 +1,50 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +module t( + input clk +); + int cyc; + + sub #(10) sub_a(.*); + sub #(20) sub_b(.*); + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + initial begin + $dumpfile(`STRINGIFY(`TEST_DUMPFILE)); + // Test $dumpvars with level argument (level 1 = top-level signals only) + $dumpvars(1); + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; + + deep #(ADD + 1) deep_i(.*); +endmodule + +module deep #( + parameter int ADD +)( + input int cyc +); + int inner; + always_comb inner = cyc + ADD; +endmodule diff --git a/test_regress/t/t_trace_dumpvars_level_scope.out b/test_regress/t/t_trace_dumpvars_level_scope.out new file mode 100644 index 000000000..f2b9e53a4 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_level_scope.out @@ -0,0 +1,24 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module $rootio $end + $upscope $end + $scope module t $end + $scope module sub_a $end + $var wire 32 ( ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 # value [31:0] $end + $scope module deep_i $end + $upscope $end + $upscope $end + $scope module sub_b $end + $scope module deep_i $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 " +b00000000000000000000000000001010 # +b00000000000000000000000000001010 ( diff --git a/test_regress/t/t_trace_dumpvars_level_scope.py b/test_regress/t/t_trace_dumpvars_level_scope.py new file mode 100644 index 000000000..1eaecdb79 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_level_scope.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --trace-vcd']) + +test.execute() + +test.vcd_identical(test.trace_filename, test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars_level_scope.v b/test_regress/t/t_trace_dumpvars_level_scope.v new file mode 100644 index 000000000..64c074c27 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_level_scope.v @@ -0,0 +1,50 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +module t( + input clk +); + int cyc; + + sub #(10) sub_a(.*); + sub #(20) sub_b(.*); + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + initial begin + $dumpfile(`STRINGIFY(`TEST_DUMPFILE)); + // Test $dumpvars with level AND scope: level 1 limits to sub_a direct signals only + $dumpvars(1, sub_a); + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; + + deep #(ADD + 1) deep_i(.*); +endmodule + +module deep #( + parameter int ADD +)( + input int cyc +); + int inner; + always_comb inner = cyc + ADD; +endmodule diff --git a/test_regress/t/t_trace_dumpvars_missing_scope.out b/test_regress/t/t_trace_dumpvars_missing_scope.out new file mode 100644 index 000000000..8bda5d834 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_missing_scope.out @@ -0,0 +1,15 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module $rootio $end + $upscope $end + $scope module t $end + $scope module sub_a $end + $scope module deep_i $end + $upscope $end + $upscope $end + $scope module sub_b $end + $scope module deep_i $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end diff --git a/test_regress/t/t_trace_dumpvars_missing_scope.py b/test_regress/t/t_trace_dumpvars_missing_scope.py new file mode 100644 index 000000000..d38577388 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_missing_scope.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --trace-vcd']) + +test.execute() + +test.file_grep(test.trace_filename, r'^\$enddefinitions \$end') +test.file_grep_not(test.trace_filename, r'^\s*\$var\s') + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars_missing_scope.v b/test_regress/t/t_trace_dumpvars_missing_scope.v new file mode 100644 index 000000000..aac875054 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_missing_scope.v @@ -0,0 +1,50 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +module t( + input clk +); + int cyc; + + sub #(10) sub_a(.*); + sub #(20) sub_b(.*); + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + initial begin + $dumpfile(`STRINGIFY(`TEST_DUMPFILE)); + // Test $dumpvars with a non-existent module scope argument + $dumpvars(0, missing_module); + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; + + deep #(ADD + 1) deep_i(.*); +endmodule + +module deep #( + parameter int ADD +)( + input int cyc +); + int inner; + always_comb inner = cyc + ADD; +endmodule diff --git a/test_regress/t/t_trace_dumpvars_multi_scope.out b/test_regress/t/t_trace_dumpvars_multi_scope.out new file mode 100644 index 000000000..1fc4774b1 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_multi_scope.out @@ -0,0 +1,27 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module $rootio $end + $upscope $end + $scope module t $end + $var wire 1 ' clk $end + $var wire 32 " cyc [31:0] $end + $scope module sub_a $end + $scope module deep_i $end + $var wire 32 ) ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 $ inner [31:0] $end + $upscope $end + $upscope $end + $scope module sub_b $end + $scope module deep_i $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 " +b00000000000000000000000000001011 $ +0' +b00000000000000000000000000001011 ) diff --git a/test_regress/t/t_trace_dumpvars_multi_scope.py b/test_regress/t/t_trace_dumpvars_multi_scope.py new file mode 100644 index 000000000..1eaecdb79 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_multi_scope.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --trace-vcd']) + +test.execute() + +test.vcd_identical(test.trace_filename, test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars_multi_scope.v b/test_regress/t/t_trace_dumpvars_multi_scope.v new file mode 100644 index 000000000..56a1fdbee --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_multi_scope.v @@ -0,0 +1,50 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +module t( + input clk +); + int cyc; + + sub #(10) sub_a(.*); + sub #(20) sub_b(.*); + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + initial begin + $dumpfile(`STRINGIFY(`TEST_DUMPFILE)); + // Test multiple scopes with non-constant level expression + $dumpvars(0+1, t, t.sub_a.deep_i); + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; + + deep #(ADD + 1) deep_i(.*); +endmodule + +module deep #( + parameter int ADD +)( + input int cyc +); + int inner; + always_comb inner = cyc + ADD; +endmodule diff --git a/test_regress/t/t_trace_dumpvars_nonconst_scope.out b/test_regress/t/t_trace_dumpvars_nonconst_scope.out new file mode 100644 index 000000000..b1f35509d --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_nonconst_scope.out @@ -0,0 +1,31 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module $rootio $end + $upscope $end + $scope module t $end + $scope module dumpblock $end + $upscope $end + $scope module sub_a $end + $var wire 32 ) ADD [31:0] $end + $var wire 32 # cyc [31:0] $end + $var wire 32 $ value [31:0] $end + $scope module deep_i $end + $var wire 32 * ADD [31:0] $end + $var wire 32 # cyc [31:0] $end + $var wire 32 % inner [31:0] $end + $upscope $end + $upscope $end + $scope module sub_b $end + $scope module deep_i $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 # +b00000000000000000000000000001010 $ +b00000000000000000000000000001011 % +b00000000000000000000000000001010 ) +b00000000000000000000000000001011 * diff --git a/test_regress/t/t_trace_dumpvars_nonconst_scope.py b/test_regress/t/t_trace_dumpvars_nonconst_scope.py new file mode 100644 index 000000000..07e99a967 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_nonconst_scope.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --trace-vcd']) + +test.execute(all_run_flags=['+LEVEL=0']) + +test.vcd_identical(test.trace_filename, test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars_nonconst_scope.v b/test_regress/t/t_trace_dumpvars_nonconst_scope.v new file mode 100644 index 000000000..82310bb9e --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_nonconst_scope.v @@ -0,0 +1,52 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +module t( + input clk +); + int cyc; + + sub #(10) sub_a(.*); + sub #(20) sub_b(.*); + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + initial begin: dumpblock + int level; + if (!$value$plusargs("LEVEL=%d", level)) level = 0; + $dumpfile(`STRINGIFY(`TEST_DUMPFILE)); + // Test $dumpvars with non-constant level expression and scope argument + $dumpvars(level, t.sub_a); + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; + + deep #(ADD + 1) deep_i(.*); +endmodule + +module deep #( + parameter int ADD +)( + input int cyc +); + int inner; + always_comb inner = cyc + ADD; +endmodule diff --git a/test_regress/t/t_trace_dumpvars_override.out b/test_regress/t/t_trace_dumpvars_override.out new file mode 100644 index 000000000..2d2474dc9 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_override.out @@ -0,0 +1,42 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module $rootio $end + $upscope $end + $scope module t $end + $var wire 1 ' clk $end + $var wire 32 " cyc [31:0] $end + $scope module sub_a $end + $var wire 32 ( ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 # value [31:0] $end + $scope module deep_i $end + $var wire 32 ) ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 $ inner [31:0] $end + $upscope $end + $upscope $end + $scope module sub_b $end + $var wire 32 * ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 % value [31:0] $end + $scope module deep_i $end + $var wire 32 + ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 & inner [31:0] $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 " +b00000000000000000000000000001010 # +b00000000000000000000000000001011 $ +b00000000000000000000000000010100 % +b00000000000000000000000000010101 & +0' +b00000000000000000000000000001010 ( +b00000000000000000000000000001011 ) +b00000000000000000000000000010100 * +b00000000000000000000000000010101 + diff --git a/test_regress/t/t_trace_dumpvars_override.py b/test_regress/t/t_trace_dumpvars_override.py new file mode 100644 index 000000000..1eaecdb79 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_override.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --trace-vcd']) + +test.execute() + +test.vcd_identical(test.trace_filename, test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars_override.v b/test_regress/t/t_trace_dumpvars_override.v new file mode 100644 index 000000000..ca4c1fad9 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_override.v @@ -0,0 +1,51 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +module t( + input clk +); + int cyc; + + sub #(10) sub_a(.*); + sub #(20) sub_b(.*); + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + initial begin + $dumpfile(`STRINGIFY(`TEST_DUMPFILE)); + // First restrict to deep_i only, then override with $dumpvars(0) to dump all + $dumpvars(1, t.sub_a.deep_i); + $dumpvars(0); + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; + + deep #(ADD + 1) deep_i(.*); +endmodule + +module deep #( + parameter int ADD +)( + input int cyc +); + int inner; + always_comb inner = cyc + ADD; +endmodule diff --git a/test_regress/t/t_trace_dumpvars_scope.out b/test_regress/t/t_trace_dumpvars_scope.out new file mode 100644 index 000000000..0a31846b7 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_scope.out @@ -0,0 +1,29 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module $rootio $end + $upscope $end + $scope module t $end + $scope module sub_a $end + $var wire 32 ( ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 # value [31:0] $end + $scope module deep_i $end + $var wire 32 ) ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 $ inner [31:0] $end + $upscope $end + $upscope $end + $scope module sub_b $end + $scope module deep_i $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 " +b00000000000000000000000000001010 # +b00000000000000000000000000001011 $ +b00000000000000000000000000001010 ( +b00000000000000000000000000001011 ) diff --git a/test_regress/t/t_trace_dumpvars_scope.py b/test_regress/t/t_trace_dumpvars_scope.py new file mode 100644 index 000000000..1eaecdb79 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_scope.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --trace-vcd']) + +test.execute() + +test.vcd_identical(test.trace_filename, test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars_scope.v b/test_regress/t/t_trace_dumpvars_scope.v new file mode 100644 index 000000000..fb2155d2e --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_scope.v @@ -0,0 +1,50 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +module t( + input clk +); + int cyc; + + sub #(10) sub_a(.*); + sub #(20) sub_b(.*); + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + initial begin + $dumpfile(`STRINGIFY(`TEST_DUMPFILE)); + // Test $dumpvars with module scope argument + $dumpvars(0, sub_a); + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; + + deep #(ADD + 1) deep_i(.*); +endmodule + +module deep #( + parameter int ADD +)( + input int cyc +); + int inner; + always_comb inner = cyc + ADD; +endmodule diff --git a/test_regress/t/t_trace_dumpvars_struct.out b/test_regress/t/t_trace_dumpvars_struct.out new file mode 100644 index 000000000..48d50a1af --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_struct.out @@ -0,0 +1,36 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module $rootio $end + $upscope $end + $scope module t $end + $var wire 1 * clk $end + $var wire 32 " cyc [31:0] $end + $scope module rect $end + $scope module origin $end + $var wire 8 # x [7:0] $end + $var wire 8 $ y [7:0] $end + $upscope $end + $scope module size $end + $var wire 8 % x [7:0] $end + $var wire 8 & y [7:0] $end + $upscope $end + $upscope $end + $scope module pt $end + $var wire 8 ' x [7:0] $end + $var wire 8 ( y [7:0] $end + $upscope $end + $scope module sub_a $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 " +b00000000 # +b00000000 $ +b00000000 % +b00000000 & +b00000000 ' +b00000000 ( +0* diff --git a/test_regress/t/t_trace_dumpvars_struct.py b/test_regress/t/t_trace_dumpvars_struct.py new file mode 100644 index 000000000..3768a51af --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_struct.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --trace-vcd --trace-structs']) + +test.execute() + +test.vcd_identical(test.trace_filename, test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars_struct.v b/test_regress/t/t_trace_dumpvars_struct.v new file mode 100644 index 000000000..132e3438f --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_struct.v @@ -0,0 +1,57 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +module t( + input clk +); + typedef struct packed { + logic [7:0] x; + logic [7:0] y; + } point_t; + + typedef struct packed { + point_t origin; + point_t size; + } rect_t; + + int cyc; + rect_t rect; + point_t pt; + + sub #(10) sub_a(.*); + + always @(posedge clk) begin + cyc <= cyc + 1; + pt.x <= pt.x + 1; + pt.y <= pt.y + 2; + rect.origin.x <= rect.origin.x + 1; + rect.origin.y <= rect.origin.y + 2; + rect.size.x <= 8'd100; + rect.size.y <= 8'd200; + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + initial begin + $dumpfile(`STRINGIFY(`TEST_DUMPFILE)); + // Level 1 counts only module nesting, so nested struct members under t + // are dumped, but sub_a's signals are still excluded. + $dumpvars(1); + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; +endmodule diff --git a/test_regress/t/t_trace_dumpvars_sub.out b/test_regress/t/t_trace_dumpvars_sub.out new file mode 100644 index 000000000..73b55a8a8 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_sub.out @@ -0,0 +1,29 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module $rootio $end + $upscope $end + $scope module t $end + $scope module sub_a $end + $var wire 32 ( ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 # value [31:0] $end + $scope module deep_i $end + $upscope $end + $upscope $end + $scope module sub_b $end + $var wire 32 * ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 % value [31:0] $end + $scope module deep_i $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 " +b00000000000000000000000000001010 # +b00000000000000000000000000010100 % +b00000000000000000000000000001010 ( +b00000000000000000000000000010100 * diff --git a/test_regress/t/t_trace_dumpvars_sub.py b/test_regress/t/t_trace_dumpvars_sub.py new file mode 100644 index 000000000..1eaecdb79 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_sub.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --trace-vcd']) + +test.execute() + +test.vcd_identical(test.trace_filename, test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars_sub.v b/test_regress/t/t_trace_dumpvars_sub.v new file mode 100644 index 000000000..dcddf9c90 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_sub.v @@ -0,0 +1,54 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +module t( + input clk +); + int cyc; + + sub #(10) sub_a(.*); + sub #(20) sub_b(.*); + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + initial begin + $dumpfile(`STRINGIFY(`TEST_DUMPFILE)); + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; + + deep #(ADD + 1) deep_i(.*); + + // $dumpvars called from sub module scope with level 1 + // Should dump only this sub module's direct signals, not deep_i's + initial begin + $dumpvars(1); + end +endmodule + +module deep #( + parameter int ADD +)( + input int cyc +); + int inner; + always_comb inner = cyc + ADD; +endmodule diff --git a/test_regress/t/t_trace_dumpvars_sub0.out b/test_regress/t/t_trace_dumpvars_sub0.out new file mode 100644 index 000000000..7418ac167 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_sub0.out @@ -0,0 +1,39 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module $rootio $end + $upscope $end + $scope module t $end + $scope module sub_a $end + $var wire 32 ( ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 # value [31:0] $end + $scope module deep_i $end + $var wire 32 ) ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 $ inner [31:0] $end + $upscope $end + $upscope $end + $scope module sub_b $end + $var wire 32 * ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 % value [31:0] $end + $scope module deep_i $end + $var wire 32 + ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 & inner [31:0] $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 " +b00000000000000000000000000001010 # +b00000000000000000000000000001011 $ +b00000000000000000000000000010100 % +b00000000000000000000000000010101 & +b00000000000000000000000000001010 ( +b00000000000000000000000000001011 ) +b00000000000000000000000000010100 * +b00000000000000000000000000010101 + diff --git a/test_regress/t/t_trace_dumpvars_sub0.py b/test_regress/t/t_trace_dumpvars_sub0.py new file mode 100644 index 000000000..1eaecdb79 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_sub0.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --trace-vcd']) + +test.execute() + +test.vcd_identical(test.trace_filename, test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars_sub0.v b/test_regress/t/t_trace_dumpvars_sub0.v new file mode 100644 index 000000000..ca936cd7e --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_sub0.v @@ -0,0 +1,54 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +module t( + input clk +); + int cyc; + + sub #(10) sub_a(.*); + sub #(20) sub_b(.*); + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + initial begin + $dumpfile(`STRINGIFY(`TEST_DUMPFILE)); + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; + + deep #(ADD + 1) deep_i(.*); + + // $dumpvars called from sub module scope with level 0 + // Should dump all signals in this sub module and below (including deep_i) + initial begin + $dumpvars(0); + end +endmodule + +module deep #( + parameter int ADD +)( + input int cyc +); + int inner; + always_comb inner = cyc + ADD; +endmodule diff --git a/test_regress/t/t_trace_dumpvars_task.out b/test_regress/t/t_trace_dumpvars_task.out new file mode 100644 index 000000000..73b55a8a8 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_task.out @@ -0,0 +1,29 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module $rootio $end + $upscope $end + $scope module t $end + $scope module sub_a $end + $var wire 32 ( ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 # value [31:0] $end + $scope module deep_i $end + $upscope $end + $upscope $end + $scope module sub_b $end + $var wire 32 * ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 % value [31:0] $end + $scope module deep_i $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 " +b00000000000000000000000000001010 # +b00000000000000000000000000010100 % +b00000000000000000000000000001010 ( +b00000000000000000000000000010100 * diff --git a/test_regress/t/t_trace_dumpvars_task.py b/test_regress/t/t_trace_dumpvars_task.py new file mode 100644 index 000000000..1eaecdb79 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_task.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --trace-vcd']) + +test.execute() + +test.vcd_identical(test.trace_filename, test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars_task.v b/test_regress/t/t_trace_dumpvars_task.v new file mode 100644 index 000000000..74e64feb7 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_task.v @@ -0,0 +1,61 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +function int get_trace_level; + return 1; +endfunction + +function void varsdump; + $dumpvars(get_trace_level()); +endfunction + +task setup_trace; + $dumpfile(`STRINGIFY(`TEST_DUMPFILE)); + varsdump(); +endtask + +module t( + input clk +); + int cyc; + + sub #(10) sub_a(.*); + sub #(20) sub_b(.*); + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; + + initial begin + setup_trace; + end + + deep #(ADD + 1) deep_i(.*); +endmodule + +module deep #( + parameter int ADD +)( + input int cyc +); + int inner; + always_comb inner = cyc + ADD; +endmodule diff --git a/test_regress/t/t_trace_dumpvars_task2.out b/test_regress/t/t_trace_dumpvars_task2.out new file mode 100644 index 000000000..73b55a8a8 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_task2.out @@ -0,0 +1,29 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module $rootio $end + $upscope $end + $scope module t $end + $scope module sub_a $end + $var wire 32 ( ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 # value [31:0] $end + $scope module deep_i $end + $upscope $end + $upscope $end + $scope module sub_b $end + $var wire 32 * ADD [31:0] $end + $var wire 32 " cyc [31:0] $end + $var wire 32 % value [31:0] $end + $scope module deep_i $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 " +b00000000000000000000000000001010 # +b00000000000000000000000000010100 % +b00000000000000000000000000001010 ( +b00000000000000000000000000010100 * diff --git a/test_regress/t/t_trace_dumpvars_task2.py b/test_regress/t/t_trace_dumpvars_task2.py new file mode 100644 index 000000000..1eaecdb79 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_task2.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --trace-vcd']) + +test.execute() + +test.vcd_identical(test.trace_filename, test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars_task2.v b/test_regress/t/t_trace_dumpvars_task2.v new file mode 100644 index 000000000..6b0fe071e --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_task2.v @@ -0,0 +1,65 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +function int get_trace_level; + return 1; +endfunction + +function void varsdump; + $dumpvars(get_trace_level()); +endfunction + +task setup_trace; + $dumpfile(`STRINGIFY(`TEST_DUMPFILE)); + varsdump(); +endtask + +task setup_trace_nested; + setup_trace(); +endtask + +module t( + input clk +); + int cyc; + + sub #(10) sub_a(.*); + sub #(20) sub_b(.*); + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; + + initial begin + setup_trace_nested; + end + + deep #(ADD + 1) deep_i(.*); +endmodule + +module deep #( + parameter int ADD +)( + input int cyc +); + int inner; + always_comb inner = cyc + ADD; +endmodule diff --git a/test_regress/t/t_trace_dumpvars_wire.out b/test_regress/t/t_trace_dumpvars_wire.out new file mode 100644 index 000000000..d10cfb434 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_wire.out @@ -0,0 +1,18 @@ +$version Generated by VerilatedVcd $end +$timescale 1ps $end + $scope module $rootio $end + $upscope $end + $scope module t $end + $var wire 32 " cyc [31:0] $end + $var wire 32 # counter [31:0] $end + $scope module sub_a $end + $upscope $end + $scope module sub_b $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 " +b00000000000000000000000000000000 # diff --git a/test_regress/t/t_trace_dumpvars_wire.py b/test_regress/t/t_trace_dumpvars_wire.py new file mode 100644 index 000000000..1eaecdb79 --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_wire.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 by Marco Bartoli. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--binary --trace-vcd']) + +test.execute() + +test.vcd_identical(test.trace_filename, test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_trace_dumpvars_wire.v b/test_regress/t/t_trace_dumpvars_wire.v new file mode 100644 index 000000000..2ec84035c --- /dev/null +++ b/test_regress/t/t_trace_dumpvars_wire.v @@ -0,0 +1,41 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 by Marco Bartoli. +// SPDX-License-Identifier: CC0-1.0 + +`define STRINGIFY(x) `"x`" + +module t( + input clk +); + int cyc; + int counter; + + sub #(10) sub_a(.*); + sub #(20) sub_b(.*); + + always @(posedge clk) begin + cyc <= cyc + 1; + counter <= counter + 2; + if (cyc == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + initial begin + $dumpfile(`STRINGIFY(`TEST_DUMPFILE)); + // Test $dumpvars with specific wire names + $dumpvars(0, cyc, counter); + end +endmodule + +module sub #( + parameter int ADD +)( + input int cyc +); + int value; + always_comb value = cyc + ADD; +endmodule