diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 8c56d41d4..aa2c33526 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -21,6 +21,7 @@ #include "V3File.h" #include "V3Global.h" #include "V3Broken.h" +#include "V3EmitV.h" #include "V3String.h" #include @@ -1141,6 +1142,7 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump, boo } } } + if (doDump && v3Global.opt.debugEmitV()) V3EmitV::debugEmitV(filename + ".v"); if (doCheck && (v3Global.opt.debugCheck() || v3Global.opt.dumpTree())) { // Error check checkTree(); diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index ed3685433..3ccddb659 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -305,7 +305,7 @@ public: AstClassPackage(FileLine* fl, const string& name) : ASTGEN_SUPER_ClassPackage(fl, name) {} ASTNODE_NODE_FUNCS(ClassPackage) - virtual string verilogKwd() const override { return "/*class*/package"; } + virtual string verilogKwd() const override { return "classpackage"; } virtual const char* broken() const override; virtual void cloneRelink() override; virtual bool timescaleMatters() const override { return false; } @@ -2730,6 +2730,7 @@ public: ASTNODE_NODE_FUNCS(Iface) // Interfaces have `timescale applicability but lots of code seems to // get false warnings if we enable this + virtual string verilogKwd() const override { return "interface"; } virtual bool timescaleMatters() const override { return false; } }; diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index cff6f3c3d..14596c79b 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -65,9 +65,8 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { puts(nodep->prettyName()); puts(";\n"); // Only putfs the first time for each visitor; later for same node is putqs - putqs(nodep, "begin\n"); iterateAndNextNull(nodep->stmtsp()); - putqs(nodep, "end\n"); + putfs(nodep, nodep->isFunction() ? "endfunction\n" : "endtask\n"); } virtual void visit(AstBegin* nodep) override { @@ -599,6 +598,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { puts(nodep->verilogKwd() + " "); if (nodep->packed()) puts("packed "); puts("\n"); + puts("{"); iterateAndNextNull(nodep->membersp()); puts("}"); } @@ -606,7 +606,6 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { iterate(nodep->subDTypep()); puts(" "); puts(nodep->name()); - puts("}"); } virtual void visit(AstNodeFTaskRef* nodep) override { if (nodep->dotted() != "") { @@ -631,18 +630,26 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { if (nodep->varScopep()) { putfs(nodep, nodep->varScopep()->prettyName()); } else { - if (nodep->selfPointer().empty()) { - putfs(nodep, nodep->varp()->prettyName()); + if (nodep->varp()) { + if (nodep->selfPointer().empty()) { + putfs(nodep, nodep->varp()->prettyName()); + } else { + putfs(nodep, nodep->selfPointer() + "->"); + puts(nodep->varp()->prettyName()); + } } else { - putfs(nodep, nodep->selfPointer() + "->"); - puts(nodep->varp()->prettyName()); + putfs(nodep, nodep->name()); } } } virtual void visit(AstVarXRef* nodep) override { putfs(nodep, nodep->dotted()); puts("."); - puts(nodep->varp()->prettyName()); + if (nodep->varp()) { + puts(nodep->varp()->prettyName()); + } else { + puts(nodep->prettyName()); + } } virtual void visit(AstConst* nodep) override { putfs(nodep, nodep->num().ascii(true, true)); } @@ -682,6 +689,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { iterateAndNextNull(nodep->stmtsp()); m_sensesp = nullptr; } + virtual void visit(AstParseRef* nodep) override { puts(nodep->prettyName()); } virtual void visit(AstVarScope*) override {} virtual void visit(AstNodeText*) override {} virtual void visit(AstTraceDecl*) override {} @@ -856,10 +864,8 @@ void V3EmitV::emitvFiles() { } } -void V3EmitV::debugEmitV(const string& stage) { +void V3EmitV::debugEmitV(const string& filename) { UINFO(2, __FUNCTION__ << ": " << endl); - const string filename - = v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "__" + stage + ".v"; V3OutVFile of(filename); { EmitVFileVisitor{v3Global.rootp(), &of, true, true}; } } diff --git a/src/V3EmitV.h b/src/V3EmitV.h index eb1ef7250..e2be6ab25 100644 --- a/src/V3EmitV.h +++ b/src/V3EmitV.h @@ -31,7 +31,7 @@ public: static void verilogPrefixedTree(AstNode* nodep, std::ostream& os, const string& prefix, int flWidth, AstSenTree* domainp, bool user3mark); static void emitvFiles(); - static void debugEmitV(const string& stage); + static void debugEmitV(const string& filename); }; #endif // Guard diff --git a/src/V3File.cpp b/src/V3File.cpp index a910a2490..1d5062f65 100644 --- a/src/V3File.cpp +++ b/src/V3File.cpp @@ -636,8 +636,8 @@ string V3OutFormatter::indentSpaces(int num) { return st; } -bool V3OutFormatter::tokenStart(const char* cp, const char* cmp) { - while (*cmp == *cp) { +bool V3OutFormatter::tokenMatch(const char* cp, const char* cmp) { + while (*cmp && *cmp == *cp) { ++cp; ++cmp; } @@ -646,8 +646,18 @@ bool V3OutFormatter::tokenStart(const char* cp, const char* cmp) { return true; } +bool V3OutFormatter::tokenStart(const char* cp) { + return (tokenMatch(cp, "begin") || tokenMatch(cp, "case") || tokenMatch(cp, "casex") + || tokenMatch(cp, "casez") || tokenMatch(cp, "class") || tokenMatch(cp, "function") + || tokenMatch(cp, "interface") || tokenMatch(cp, "module") || tokenMatch(cp, "package") + || tokenMatch(cp, "task")); +} + bool V3OutFormatter::tokenEnd(const char* cp) { - return (tokenStart(cp, "end") || tokenStart(cp, "endcase") || tokenStart(cp, "endmodule")); + return (tokenMatch(cp, "end") || tokenMatch(cp, "endcase") || tokenMatch(cp, "endclass") + || tokenMatch(cp, "endfunction") || tokenMatch(cp, "endinterface") + || tokenMatch(cp, "endmodule") || tokenMatch(cp, "endpackage") + || tokenMatch(cp, "endtask")); } int V3OutFormatter::endLevels(const char* strg) { @@ -698,6 +708,10 @@ void V3OutFormatter::puts(const char* strg) { bool equalsForBracket = false; // Looking for "= {" for (const char* cp = strg; *cp; cp++) { putcNoTracking(*cp); + if (isalpha(*cp)) { + if (wordstart && m_lang == LA_VERILOG && tokenStart(cp)) indentInc(); + if (wordstart && m_lang == LA_VERILOG && tokenEnd(cp)) indentDec(); + } switch (*cp) { case '\n': m_lineno++; @@ -775,26 +789,6 @@ void V3OutFormatter::puts(const char* strg) { if (cp > strg && cp[-1] == '/') indentDec(); // < ..... /> stays same level } break; - case 'b': - if (wordstart && m_lang == LA_VERILOG && tokenStart(cp, "begin")) indentInc(); - wordstart = false; - break; - case 'c': - if (wordstart && m_lang == LA_VERILOG - && (tokenStart(cp, "case") || tokenStart(cp, "casex") - || tokenStart(cp, "casez"))) { - indentInc(); - } - wordstart = false; - break; - case 'e': - if (wordstart && m_lang == LA_VERILOG && tokenEnd(cp)) indentDec(); - wordstart = false; - break; - case 'm': - if (wordstart && m_lang == LA_VERILOG && tokenStart(cp, "module")) indentInc(); - wordstart = false; - break; default: wordstart = false; break; } diff --git a/src/V3File.h b/src/V3File.h index c13f01fef..d3d54e4f4 100644 --- a/src/V3File.h +++ b/src/V3File.h @@ -154,7 +154,8 @@ public: puts(strg); } bool exceededWidth() const { return m_column > m_commaWidth; } - bool tokenStart(const char* cp, const char* cmp); + bool tokenMatch(const char* cp, const char* cmp); + bool tokenStart(const char* cp); bool tokenEnd(const char* cp); void indentInc() { m_indentLevel += m_blockIndent; } void indentDec() { diff --git a/src/Verilator.cpp b/src/Verilator.cpp index e63305c74..c68fd11ef 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -111,7 +111,6 @@ static void reportStatsIfEnabled() { V3Stats::statsFinalAll(v3Global.rootp()); V3Stats::statsReport(); } - if (v3Global.opt.debugEmitV()) V3EmitV::debugEmitV("final"); } static void process() { @@ -376,7 +375,6 @@ static void process() { V3ActiveTop::activeTopAll(v3Global.rootp()); if (v3Global.opt.stats()) V3Stats::statsStageAll(v3Global.rootp(), "PreOrder"); - if (v3Global.opt.debugEmitV()) V3EmitV::debugEmitV("preorder"); // Order the code; form SBLOCKs and BLOCKCALLs V3Order::orderAll(v3Global.rootp());