diff --git a/src/V3Cdc.cpp b/src/V3Cdc.cpp index 7a43c4652..30feef8d6 100644 --- a/src/V3Cdc.cpp +++ b/src/V3Cdc.cpp @@ -110,15 +110,19 @@ public: class CdcLogicVertex : public CdcEitherVertex { bool m_safe; + bool m_isFlop; public: CdcLogicVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep, AstSenTree* sensenodep) - : CdcEitherVertex(graphp,scopep,nodep), m_safe(true) { srcDomainp(sensenodep); dstDomainp(sensenodep); } + : CdcEitherVertex(graphp,scopep,nodep), m_safe(true), m_isFlop(false) + { srcDomainp(sensenodep); dstDomainp(sensenodep); } virtual ~CdcLogicVertex() {} // Accessors virtual string name() const { return (cvtToStr((void*)nodep())+"@"+scopep()->prettyName()); } virtual string dotColor() const { return safe() ? "black" : "yellow"; } bool safe() const { return m_safe; } void clearSafe(AstNode* nodep) { m_safe = false; nodep->user3(true); } + bool isFlop() const { return m_isFlop; } + void isFlop(bool flag) { m_isFlop = flag; } }; //###################################################################### @@ -158,6 +162,42 @@ public: virtual ~CdcDumpVisitor() {} }; +//###################################################################### + +class CdcWidthVisitor : public CdcBaseVisitor { +private: + int m_maxLineno; + int m_maxFilenameLen; + + virtual void visit(AstNode* nodep, AstNUser*) { + nodep->iterateChildren(*this); + // Keeping line+filename lengths separate is much faster than calling ascii().length() + if (nodep->fileline()->lineno() >= m_maxLineno) { + m_maxLineno = nodep->fileline()->lineno()+1; + } + if (nodep->fileline()->filename().length() >= m_maxFilenameLen) { + m_maxFilenameLen = nodep->fileline()->filename().length()+1; + } + } +public: + // CONSTUCTORS + CdcWidthVisitor(AstNode* nodep) { + m_maxLineno = 0; + m_maxFilenameLen = 0; + nodep->accept(*this); + } + virtual ~CdcWidthVisitor() {} + // ACCESSORS + int maxWidth() { + int width=1; + width += m_maxFilenameLen; + width += 1; // The : + width += cvtToStr(m_maxLineno).length(); + width += 1; // Final : + return width; + } +}; + //###################################################################### // Cdc class functions @@ -182,6 +222,7 @@ private: string m_ofFilename; // Output filename ofstream* m_ofp; // Output file uint32_t m_userGeneration; // Generation count to avoid slow userClearVertices + int m_filelineWidth; // Characters in longest fileline // METHODS void iterateNewStmt(AstNode* nodep) { @@ -189,6 +230,7 @@ private: UINFO(4," STMT "<hasClocked()) { // To/from a flop + m_logicVertexp->isFlop(true); m_logicVertexp->srcDomainp(m_domainp); m_logicVertexp->srcDomainSet(true); m_logicVertexp->dstDomainp(m_domainp); @@ -266,6 +308,14 @@ private: analyzeReset(); } + int filelineWidth() { + if (!m_filelineWidth) { + CdcWidthVisitor visitor (v3Global.rootp()); + m_filelineWidth = visitor.maxWidth(); + } + return m_filelineWidth; + } + //---------------------------------------- // RESET REPORT @@ -344,9 +394,15 @@ private: *m_ofp<<"\n"; *m_ofp<<"\n"; CdcEitherVertex* targetp = vertexp; // One example destination flop (of possibly many) - if (V3GraphEdge* edgep = vertexp->outBeginp()) { + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { CdcEitherVertex* eToVertexp = (CdcEitherVertex*)edgep->top(); - targetp = eToVertexp; + if (!eToVertexp) targetp = eToVertexp; + if (CdcLogicVertex* vvertexp = dynamic_cast(eToVertexp)) { + if (vvertexp->isFlop()) { + targetp = eToVertexp; + break; + } + } // else it might be random logic that's not relevant } warnAndFile(markp->nodep(),V3ErrorCode::CDCRSTLOGIC,"Logic in path that feeds async reset, via signal: "+nodep->prettyName()); dumpAsyncRecurse(targetp, "", " ",0); @@ -372,19 +428,20 @@ private: // Dump single variable/logic block // See also OrderGraph::loopsVertexCb(V3GraphVertex* vertexp) AstNode* nodep = vertexp->nodep(); - string front = pad(40,nodep->fileline()->ascii()+":")+" "+prefix+" +- "; + string front = pad(filelineWidth(),nodep->fileline()->ascii()+":")+" "+prefix+" +- "; if (nodep->castVarScope()) { *m_ofp<prettyName()<srcDomainp(), true); + V3EmitV::verilogPrefixedTree(nodep, *m_ofp, prefix+" +- ", filelineWidth(), + vertexp->srcDomainp(), true); if (debug()) { CdcDumpVisitor visitor (nodep, m_ofp, front+"DBG: "); } } nextsep = " | "; - if (level) *m_ofp<srcDomainp()) V3EmitV::verilogForTree(vvertexp->srcDomainp(), os); os<<" DST="; if (vvertexp->dstDomainp()) V3EmitV::verilogForTree(vvertexp->dstDomainp(), os); - os<<"\n"; + os<ascii()+":"; - m_os<ascii().length()+1)); + m_os<ascii().length()+1)); m_os<<" "; m_os<fileline(); // NETLIST's fileline instead of NULL to avoid NULL checks } @@ -598,9 +599,9 @@ class EmitVPrefixedVisitor : public EmitVBaseVisitor { } public: - EmitVPrefixedVisitor(AstNode* nodep, ostream& os, const string& prefix, + EmitVPrefixedVisitor(AstNode* nodep, ostream& os, const string& prefix, int flWidth, AstSenTree* domainp, bool user3mark) - : EmitVBaseVisitor(domainp), m_formatter(os, prefix), m_user3mark(user3mark) { + : EmitVBaseVisitor(domainp), m_formatter(os, prefix, flWidth), m_user3mark(user3mark) { if (user3mark) { AstUser3InUse::check(); } nodep->accept(*this); } @@ -633,7 +634,7 @@ void V3EmitV::verilogForTree(AstNode* nodep, ostream& os) { EmitVStreamVisitor(nodep, os); } -void V3EmitV::verilogPrefixedTree(AstNode* nodep, ostream& os, const string& prefix, +void V3EmitV::verilogPrefixedTree(AstNode* nodep, ostream& os, const string& prefix, int flWidth, AstSenTree* domainp, bool user3mark) { - EmitVPrefixedVisitor(nodep, os, prefix, domainp, user3mark); + EmitVPrefixedVisitor(nodep, os, prefix, flWidth, domainp, user3mark); } diff --git a/src/V3EmitV.h b/src/V3EmitV.h index 6ccfe35b8..0c64d1cf5 100644 --- a/src/V3EmitV.h +++ b/src/V3EmitV.h @@ -33,7 +33,7 @@ class V3EmitV { public: static void emitv(); static void verilogForTree(AstNode* nodep, ostream& os=cout); - static void verilogPrefixedTree(AstNode* nodep, ostream& os, const string& prefix, + static void verilogPrefixedTree(AstNode* nodep, ostream& os, const string& prefix, int flWidth, AstSenTree* domainp, bool user3percent); };