From c6dae40cf64497ba783a33b6d810823af9b2b38d Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 26 Nov 2021 20:38:48 -0500 Subject: [PATCH] Support task name in $display %m (#3211). --- Changes | 1 + src/V3Assert.cpp | 2 +- src/V3AstNodes.cpp | 5 +++++ src/V3AstNodes.h | 12 +++++++--- src/V3Begin.cpp | 15 ++++++++++--- src/V3LinkResolve.cpp | 6 ++--- src/V3Width.cpp | 2 +- test_regress/t/t_class_name.v | 27 ++++++++--------------- test_regress/t/t_display.out | 8 +++---- test_regress/t/t_dpi_qw_c.cpp | 11 ++++++++- test_regress/t/t_var_nonamebegin__log.out | 4 ++-- 11 files changed, 57 insertions(+), 36 deletions(-) diff --git a/Changes b/Changes index ba85d7c42..186505ec4 100644 --- a/Changes +++ b/Changes @@ -19,6 +19,7 @@ Verilator 4.215 devel * Internal code cleanups and improvements. [Geza Lore] * Improve --thread verilation-time performance. +* Support task name in $display %m (#3211). [Julie Schwartz] * Fix array method names with parenthesis (#3181) (#3183). [Teng Huang] * Fix split_var assign merging (#3177) (#3179). [Yutetsu TAKATSUKASA] * Fix nested generate if genblk naming (#3189). [yanx21] diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index 9bb03a37b..59a675d0f 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -62,7 +62,7 @@ private: } nodep->fmtp()->addExprsp(timenewp); if (!nodep->fmtp()->scopeNamep() && nodep->fmtp()->formatScopeTracking()) { - nodep->fmtp()->scopeNamep(new AstScopeName(nodep->fileline())); + nodep->fmtp()->scopeNamep(new AstScopeName{nodep->fileline(), true}); } } AstVarRef* newMonitorNumVarRefp(AstNode* nodep, VAccess access) { diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 9235cb14e..a1f2ad2d0 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1700,6 +1700,11 @@ void AstScope::dump(std::ostream& str) const { str << " [cellp=" << reinterpret_cast(aboveCellp()) << "]"; str << " [modp=" << reinterpret_cast(modp()) << "]"; } +void AstScopeName::dump(std::ostream& str) const { + this->AstNode::dump(str); + if (dpiExport()) str << " [DPIEX]"; + if (forFormat()) str << " [FMT]"; +} void AstSenTree::dump(std::ostream& str) const { this->AstNode::dump(str); if (isMulti()) str << " [MULTI]"; diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index b116d72c9..e6f028df6 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -5379,21 +5379,26 @@ class AstScopeName final : public AstNodeMath { // Children: TEXT private: bool m_dpiExport = false; // Is for dpiExport + const bool m_forFormat = false; // Is for a format %m string scopeNameFormatter(AstText* scopeTextp) const; string scopePrettyNameFormatter(AstText* scopeTextp) const; public: - explicit AstScopeName(FileLine* fl) - : ASTGEN_SUPER_ScopeName(fl) { + class ForFormat {}; + AstScopeName(FileLine* fl, bool forFormat) + : ASTGEN_SUPER_ScopeName(fl) + , m_forFormat{forFormat} { dtypeSetUInt64(); } ASTNODE_NODE_FUNCS(ScopeName) virtual bool same(const AstNode* samep) const override { - return m_dpiExport == static_cast(samep)->m_dpiExport; + return (m_dpiExport == static_cast(samep)->m_dpiExport + && m_forFormat == static_cast(samep)->m_forFormat); } virtual string emitVerilog() override { return ""; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const override { return true; } + virtual void dump(std::ostream& str = std::cout) const override; AstText* scopeAttrp() const { return VN_AS(op1p(), Text); } void scopeAttrp(AstNode* nodep) { addOp1p(nodep); } AstText* scopeEntrp() const { return VN_AS(op2p(), Text); } @@ -5412,6 +5417,7 @@ public: } bool dpiExport() const { return m_dpiExport; } void dpiExport(bool flag) { m_dpiExport = flag; } + bool forFormat() const { return m_forFormat; } }; class AstUdpTable final : public AstNode { diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index 05ab4072c..76e540747 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -63,6 +63,7 @@ private: AstNodeModule* m_modp = nullptr; // Current module const AstNodeFTask* m_ftaskp = nullptr; // Current function/task AstNode* m_liftedp = nullptr; // Local nodes we are lifting into m_ftaskp + string m_displayScope; // Name of %m in $display/AstScopeName string m_namedScope; // Name of begin blocks above us string m_unnamedScope; // Name of begin blocks, including unnamed blocks int m_ifDepth = 0; // Current if depth @@ -111,9 +112,11 @@ private: // naming; so that any begin's inside the function will rename // inside the function. // Process children + VL_RESTORER(m_displayScope); VL_RESTORER(m_namedScope); VL_RESTORER(m_unnamedScope); { + m_displayScope = dot(m_displayScope, nodep->name()); m_namedScope = ""; m_unnamedScope = ""; m_ftaskp = nodep; @@ -134,6 +137,7 @@ private: virtual void visit(AstBegin* nodep) override { // Begin blocks were only useful in variable creation, change names and delete UINFO(8, " " << nodep << endl); + VL_RESTORER(m_displayScope); VL_RESTORER(m_namedScope); VL_RESTORER(m_unnamedScope); { @@ -145,7 +149,10 @@ private: while ((pos = dottedname.find("__DOT__")) != string::npos) { const string ident = dottedname.substr(0, pos); dottedname = dottedname.substr(pos + strlen("__DOT__")); - if (nodep->name() != "") m_namedScope = dot(m_namedScope, ident); + if (nodep->name() != "") { + m_displayScope = dot(m_displayScope, ident); + m_namedScope = dot(m_namedScope, ident); + } m_unnamedScope = dot(m_unnamedScope, ident); // Create CellInline for dotted var resolution if (!m_ftaskp) { @@ -220,11 +227,13 @@ private: // 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 - if (m_namedScope != "") { + // DPI svGetScope doesn't include function name, but %m does + const string scname = nodep->forFormat() ? m_displayScope : m_namedScope; + if (!scname.empty()) { // To keep correct visual order, must add before other Text's AstNode* const afterp = nodep->scopeAttrp(); if (afterp) afterp->unlinkFrBackWithNext(); - nodep->scopeAttrp(new AstText(nodep->fileline(), string("__DOT__") + m_namedScope)); + nodep->scopeAttrp(new AstText{nodep->fileline(), string("__DOT__") + scname}); if (afterp) nodep->scopeAttrp(afterp); } iterateChildren(nodep); diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index ed7cc4db3..434baf566 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -136,12 +136,12 @@ private: iterateChildren(nodep); } m_ftaskp = nullptr; - if (nodep->dpiExport()) nodep->scopeNamep(new AstScopeName(nodep->fileline())); + if (nodep->dpiExport()) nodep->scopeNamep(new AstScopeName{nodep->fileline(), false}); } virtual void visit(AstNodeFTaskRef* nodep) override { iterateChildren(nodep); if (nodep->taskp() && (nodep->taskp()->dpiContext() || nodep->taskp()->dpiExport())) { - nodep->scopeNamep(new AstScopeName(nodep->fileline())); + nodep->scopeNamep(new AstScopeName{nodep->fileline(), false}); } } @@ -459,7 +459,7 @@ private: if ((VN_IS(nodep->backp(), Display) && VN_AS(nodep->backp(), Display)->displayType().needScopeTracking()) || nodep->formatScopeTracking()) { - nodep->scopeNamep(new AstScopeName(nodep->fileline())); + nodep->scopeNamep(new AstScopeName{nodep->fileline(), true}); } } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index bffbeb9d8..0fcb1d7d3 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -4493,7 +4493,7 @@ private: AstSFormatF* const newp = new AstSFormatF(nodep->fileline(), format, false, argsp); if (!newp->scopeNamep() && newp->formatScopeTracking()) { - newp->scopeNamep(new AstScopeName(newp->fileline())); + newp->scopeNamep(new AstScopeName{newp->fileline(), true}); } handle.relink(new AstArg(newp->fileline(), "", newp)); // Connection list is now incorrect (has extra args in it). diff --git a/test_regress/t/t_class_name.v b/test_regress/t/t_class_name.v index 0be89d598..cece02916 100644 --- a/test_regress/t/t_class_name.v +++ b/test_regress/t/t_class_name.v @@ -92,12 +92,10 @@ module t (/*AUTOARG*/); c = new; s = mod_func_name(); - `checks(s, "tmf top.t"); - // UNSUP `checks(s, "tmf top.t.mod_func_name"); + `checks(s, "tmf top.t.mod_func_name"); s = unit_name(); - `checks(s, "u top.$unit"); - // UNSUP `checks(s, "u top.$unit.unit_name"); + `checks(s, "u top.$unit.unit_name"); // Others: "u $unit_????::unit_name // Others: "u $unit::unit_name // Others: "u \\package UnitScopePackage_1\ .UnitScopePackage_1.unit_name @@ -105,14 +103,12 @@ module t (/*AUTOARG*/); // *** Below results vary with simulator. s = Cls::static_name(); - `checks(s, "c top.$unit.Cls"); - // UNSUP `checks(s, "c top.$unit.Cls.static_name"); + `checks(s, "c top.$unit.Cls.static_name"); // Others: "c $unit_????.Cls.static_name // Others: "c $unit::\Cls::static_name // Others: "c Cls.static_name s = c.c_auto_name(); - `checks(s, "c top.$unit.Cls"); - // UNSUP `checks(s, "c top.$unit.Cls.c_auto_name"); + `checks(s, "c top.$unit.Cls.c_auto_name"); // Others: "c $unit_????.Cls.c_auto_name // Others: "c $unit::\Cls::c_auto_name // Others: "c Cls.c_auto_name @@ -126,33 +122,28 @@ module t (/*AUTOARG*/); // Others: "p \\package P\ .Cls.static_name s = p.p_auto_name(); - `checks(s, "p top.P.Cls"); - // UNSUP `checks(s, "p top.P.Cls.p_auto_name"); + `checks(s, "p top.P.Cls.p_auto_name"); // Others: "p P.Cls.p_auto_name // Others: "p P::Cls.p_auto_name // Others: "p P::\Cls::p_auto_name // Others: "p \\package P\ .Cls.p_auto_name s = m.cls_static_name(); - `checks(s, "m top.t.m.Cls"); - // UNSUP `checks(s, "m top.t.m.Cls.static_name"); + `checks(s, "m top.t.m.Cls.static_name"); // Others: "m top.t.m.Cls.static_name // Others: "m top.t.m.\Cls::static_name s = m.cls_auto_name(); - `checks(s, "m top.t.m.Cls"); - // UNSUP `checks(s, "m top.t.m.Cls.m_auto_name"); + `checks(s, "m top.t.m.Cls.m_auto_name"); // Others: "m top.t.m.Cls.m_auto_name // Others: "m top.t.m.\Cls::m_auto_name s = m.sub.cls_static_name(); - `checks(s, "ms top.t.m.sub.Cls"); - // UNSUP `checks(s, "ms top.t.m.sub.Cls.static_name"); + `checks(s, "ms top.t.m.sub.Cls.static_name"); // Others: "ms top.t.m.sub.Cls.static_name // Others: "ms top.t.m.sub.\Cls::static_name s = m.sub.cls_auto_name(); - `checks(s, "ms top.t.m.sub.Cls"); - // UNSUP `checks(s, "ms top.t.m.sub.Cls.ms_auto_name"); + `checks(s, "ms top.t.m.sub.Cls.ms_auto_name"); // Others: "ms top.t.m.sub.Cls.ms_auto_name // Others: "ms top.t.m.sub.\Cls::ms_auto_name diff --git a/test_regress/t/t_display.out b/test_regress/t/t_display.out index 7774e9e34..375c5dfc9 100644 --- a/test_regress/t/t_display.out +++ b/test_regress/t/t_display.out @@ -1,8 +1,8 @@ [0] In top.t: Hi -[0] In top.t.sub (sub) -[0] In top.t.sub.subblock (sub) -[0] In top.t.sub2 (sub2) -[0] In top.t.sub2.subblock2 (sub2) +[0] In top.t.sub.write_m (sub) +[0] In top.t.sub.write_m.subblock (sub) +[0] In top.t.sub2.write_m (sub2) +[0] In top.t.sub2.write_m.subblock2 (sub2) [0] Back \ Quote " [0] %b=000001100 %0b=1100 %b=00000101010111011101110111100110011001100 %0b=101010111011101110111100110011001100 %b=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0b=1010101111000001001000110100010101100111100000010010001101000101011001111000 [0] %B=000001100 %0B=1100 %B=00000101010111011101110111100110011001100 %0B=101010111011101110111100110011001100 %B=000001010101111000001001000110100010101100111100000010010001101000101011001111000 %0B=1010101111000001001000110100010101100111100000010010001101000101011001111000 diff --git a/test_regress/t/t_dpi_qw_c.cpp b/test_regress/t/t_dpi_qw_c.cpp index 01a927848..49e15cf0f 100644 --- a/test_regress/t/t_dpi_qw_c.cpp +++ b/test_regress/t/t_dpi_qw_c.cpp @@ -15,13 +15,22 @@ //====================================================================== +#ifdef VERILATOR #include "Vt_dpi_qw__Dpi.h" +#else +extern "C" { +extern void set_value(const svBitVecVal* v); +extern void poke_value(int i); +} +#endif //====================================================================== // Called from our Verilog code to run the tests void poke_value(int i) { printf("poke_value(%d)\n", i); + const char* const scopeNamep = svGetNameFromScope(svGetScope()); + printf("svGetNameFromScope=\"%s\"\n", scopeNamep); // clang-format off #ifdef VERILATOR @@ -34,7 +43,7 @@ void poke_value(int i) { #endif // clang-format on - svScope scope = svGetScopeFromName("top.t.a"); + const svScope scope = svGetScopeFromName("top.t.a"); if (scope == NULL) { printf("%%Error: null scope for top.t.a\n"); return; diff --git a/test_regress/t/t_var_nonamebegin__log.out b/test_regress/t/t_var_nonamebegin__log.out index 441195db4..8e4898268 100644 --- a/test_regress/t/t_var_nonamebegin__log.out +++ b/test_regress/t/t_var_nonamebegin__log.out @@ -4,6 +4,6 @@ b2: {mod} top.t.unnamedblk2 b3n: {mod}.b3named: top.t.unnamedblk2.b3named b3: {mod} top.t.unnamedblk2.unnamedblk3 b4: {mod} top.t.unnamedblk2.unnamedblk3.unnamedblk4 -t1 {mod}.tsk top.t -t2 {mod}.tsk top.t.unnamedblk7 +t1 {mod}.tsk top.t.tsk +t2 {mod}.tsk top.t.tsk.unnamedblk7 *-* All Finished *-*