From 656c460605dae5dbab468c25d0d0925ec1d2108d Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Sat, 23 May 2020 18:31:30 +0100 Subject: [PATCH] Add --dump-tree-addrids developer option --- bin/verilator | 9 +++++++++ docs/internals.adoc | 5 ++++- src/V3AstNodes.cpp | 37 +++++++++++++++++++++++-------------- src/V3Global.cpp | 17 +++++++++++++++++ src/V3Global.h | 6 ++++++ src/V3Options.cpp | 2 ++ src/V3Options.h | 2 ++ 7 files changed, 63 insertions(+), 15 deletions(-) diff --git a/bin/verilator b/bin/verilator index f61a271f9..cd0f84583 100755 --- a/bin/verilator +++ b/bin/verilator @@ -300,6 +300,7 @@ detailed descriptions in L for more information. --dump-tree Enable dumping .tree files --dump-treei Enable dumping .tree files at a level --dump-treei- Enable dumping .tree file at a source file at a level + --dump-tree-addrids Use short identifiers instead of addresses -E Preprocess, but do not compile --error-limit Abort after this number of errors --exe Link to create executable @@ -812,6 +813,14 @@ file to the specified tree dumping level (e.g. C<--dump-treei-V3Order 9>). Level 0 disbles dumps and is equivalent to "--no-dump-tree". Level 9 enables dumping of every stage. +=item --dump-tree-addrids + +Rarely needed - for developer use. Replace AST node addresses with short +identifiers in tree dumps to enhance readability. Each unique pointer value +is mapped to a unique identifier, but note that this is not necessarily +unique per node instance as an address might get reused by a newly allocated +node after a node with the same address has been dumped then freed. + =item -E Preprocess the source code, but do not compile, as with 'gcc -E'. Output diff --git a/docs/internals.adoc b/docs/internals.adoc index b2a1a0723..d5c41a954 100644 --- a/docs/internals.adoc +++ b/docs/internals.adoc @@ -850,7 +850,10 @@ correspond directly to Verilog entities (for example `MODULE` and Address of the node:: A hexadecimal address of the node in memory. Useful for examining with the -debugger. +debugger. If the actual address values are not important, then using the +`--dump-tree-addrids` option will convert address values to short identifiers +of the form `([A-Z]*)`, which is hopefully easier for the reader to cross +reference throughout the dump. Last edit number:: diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 8c98444db..b1041f601 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -964,28 +964,37 @@ void AstWhile::addNextStmt(AstNode* newp, AstNode* belowp) { //====================================================================== // Per-type Debugging +// Render node address for dumps. By default this is just the address +// printed as hex, but with --dump-tree-addrids we map addresses to short +// strings with a bijection to aid human readability. Observe that this might +// not actually be a unique identifier as the address can get reused after a +// node has been freed. +static std::string nodeAddr(const AstNode* nodep) { + return v3Global.opt.dumpTreeAddrids() ? v3Global.ptrToId(nodep) : cvtToHex(nodep); +} + void AstNode::dump(std::ostream& str) const { str << typeName() << " " - << cvtToHex(this) - //<<" "<m_backp + << nodeAddr(this) + //<< " " << nodeAddr(m_backp) << " = editCountLast()) ? "#>" : ">") << " {" << fileline()->filenameLetters() << std::dec << fileline()->lastLineno() << fileline()->firstColumnLetters() << "}"; - if (user1p()) str << " u1=" << cvtToHex(user1p()); - if (user2p()) str << " u2=" << cvtToHex(user2p()); - if (user3p()) str << " u3=" << cvtToHex(user3p()); - if (user4p()) str << " u4=" << cvtToHex(user4p()); - if (user5p()) str << " u5=" << cvtToHex(user5p()); + if (user1p()) str << " u1=" << nodeAddr(user1p()); + if (user2p()) str << " u2=" << nodeAddr(user2p()); + if (user3p()) str << " u3=" << nodeAddr(user3p()); + if (user4p()) str << " u4=" << nodeAddr(user4p()); + if (user5p()) str << " u5=" << nodeAddr(user5p()); if (hasDType()) { // Final @ so less likely to by accident read it as a nodep if (dtypep() == this) { str << " @dt=this@"; } else { - str << " @dt=" << cvtToHex(dtypep()) << "@"; + str << " @dt=" << nodeAddr(dtypep()) << "@"; } if (AstNodeDType* dtp = dtypep()) { dtp->dumpSmall(str); } } else { // V3Broken will throw an error - if (dtypep()) str << " %Error-dtype-exp=null,got=" << cvtToHex(dtypep()); + if (dtypep()) str << " %Error-dtype-exp=null,got=" << nodeAddr(dtypep()); } if (name() != "") { if (VN_IS(this, Const)) { @@ -1240,7 +1249,7 @@ void AstNodeDType::dump(std::ostream& str) const { this->AstNode::dump(str); if (generic()) str << " [GENERIC]"; if (AstNodeDType* dtp = virtRefDTypep()) { - str << " refdt=" << cvtToHex(dtp); + str << " refdt=" << nodeAddr(dtp); dtp->dumpSmall(str); } } @@ -1385,7 +1394,7 @@ void AstVarScope::dump(std::ostream& str) const { } void AstVarXRef::dump(std::ostream& str) const { this->AstNode::dump(str); - if (packagep()) { str << " pkg=" << cvtToHex(packagep()); } + if (packagep()) { str << " pkg=" << nodeAddr(packagep()); } if (lvalue()) { str << " [LV] => "; } else { @@ -1403,7 +1412,7 @@ void AstVarXRef::dump(std::ostream& str) const { } void AstVarRef::dump(std::ostream& str) const { this->AstNode::dump(str); - if (packagep()) { str << " pkg=" << cvtToHex(packagep()); } + if (packagep()) { str << " pkg=" << nodeAddr(packagep()); } if (lvalue()) { str << " [LV] => "; } else { @@ -1455,7 +1464,7 @@ void AstParseRef::dump(std::ostream& str) const { } void AstPackageRef::dump(std::ostream& str) const { this->AstNode::dump(str); - if (packagep()) { str << " pkg=" << cvtToHex(packagep()); } + if (packagep()) { str << " pkg=" << nodeAddr(packagep()); } str << " -> "; if (packagep()) { packagep()->dump(str); @@ -1478,7 +1487,7 @@ void AstActive::dump(std::ostream& str) const { } void AstNodeFTaskRef::dump(std::ostream& str) const { this->AstNode::dump(str); - if (packagep()) { str << " pkg=" << cvtToHex(packagep()); } + if (packagep()) { str << " pkg=" << nodeAddr(packagep()); } str << " -> "; if (dotted() != "") { str << ".=" << dotted() << " "; } if (taskp()) { diff --git a/src/V3Global.cpp b/src/V3Global.cpp index 54d20cb5d..553e248fe 100644 --- a/src/V3Global.cpp +++ b/src/V3Global.cpp @@ -80,3 +80,20 @@ void V3Global::dumpCheckGlobalTree(const string& stagename, int newNumber, bool doDump); if (v3Global.opt.stats()) V3Stats::statsStage(stagename); } + +const std::string& V3Global::ptrToId(const void* p) { + PtrToIdMap::iterator it = m_ptrToId.find(p); + if (it == m_ptrToId.end()) { + std::ostringstream os; + if (p) { + os << "("; + unsigned id = m_ptrToId.size(); + do { os << static_cast('A' + id % 26); } while (id /= 26); + os << ")"; + } else { + os << "0"; + } + it = m_ptrToId.insert(std::make_pair(p, os.str())).first; + } + return it->second; +} diff --git a/src/V3Global.h b/src/V3Global.h index bc7fe5454..b1b4b9184 100644 --- a/src/V3Global.h +++ b/src/V3Global.h @@ -31,6 +31,7 @@ #include "V3Options.h" #include +#include VL_INCLUDE_UNORDERED_MAP class AstNetlist; @@ -79,6 +80,10 @@ class V3Global { bool m_dpi; // Need __Dpi include files bool m_useParallelBuild; // Use parallel build for model + // Memory address to short string mapping (for debug) + typedef vl_unordered_map PtrToIdMap; // The map type + PtrToIdMap m_ptrToId; // The actual 'address' <=> 'short string' bijection + public: // Options V3Options opt; // All options; let user see them directly @@ -133,6 +138,7 @@ public: void dpi(bool flag) { m_dpi = flag; } void useParallelBuild(bool flag) { m_useParallelBuild = flag; } bool useParallelBuild() const { return m_useParallelBuild; } + const std::string& ptrToId(const void* p); }; extern V3Global v3Global; diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 364917adc..95e8ee583 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -856,6 +856,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char else if ( onoff (sw, "-dpi-hdr-only", flag/*ref*/)) { m_dpiHdrOnly = flag; } else if ( onoff (sw, "-dump-defines", flag/*ref*/)) { m_dumpDefines = flag; } else if ( onoff (sw, "-dump-tree", flag/*ref*/)) { m_dumpTree = flag ? 3 : 0; } // Also see --dump-treei + else if ( onoff (sw, "-dump-tree-addrids", flag/*ref*/)){ m_dumpTreeAddrids = flag; } else if ( onoff (sw, "-exe", flag/*ref*/)) { m_exe = flag; } else if ( onoff (sw, "-flatten", flag/*ref*/)) { m_flatten = flag; } else if ( onoff (sw, "-ignc", flag/*ref*/)) { m_ignc = flag; } @@ -1612,6 +1613,7 @@ V3Options::V3Options() { m_buildJobs = 1; m_convergeLimit = 100; m_dumpTree = 0; + m_dumpTreeAddrids = false; m_gateStmts = 100; m_ifDepth = 0; m_inlineMult = 2000; diff --git a/src/V3Options.h b/src/V3Options.h index 368070cff..46ea32569 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -276,6 +276,7 @@ private: int m_buildJobs; // main switch: -j int m_convergeLimit;// main switch: --converge-limit int m_dumpTree; // main switch: --dump-tree + bool m_dumpTreeAddrids;// main switch: --dump-tree-addrids int m_gateStmts; // main switch: --gate-stmts int m_ifDepth; // main switch: --if-depth int m_inlineMult; // main switch: --inline-mult @@ -468,6 +469,7 @@ public: int buildJobs() const { return m_buildJobs; } int convergeLimit() const { return m_convergeLimit; } int dumpTree() const { return m_dumpTree; } + bool dumpTreeAddrids() const { return m_dumpTreeAddrids; } int gateStmts() const { return m_gateStmts; } int ifDepth() const { return m_ifDepth; } int inlineMult() const { return m_inlineMult; }