From f3308d236b5ae329241f4b16c3b39c282c351d9a Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 15 Apr 2020 07:58:34 -0400 Subject: [PATCH] clang-format remaining sources. No functional change. --- Makefile.in | 6 + nodist/clang_formatter | 236 --- src/V3Active.cpp | 4 +- src/V3Assert.cpp | 2 +- src/V3Ast.cpp | 490 ++++--- src/V3Ast.h | 1568 +++++++++++--------- src/V3AstNodes.cpp | 854 ++++++----- src/V3AstNodes.h | 3101 +++++++++++++++++++++++++++------------- src/V3Begin.cpp | 117 +- src/V3Broken.cpp | 94 +- src/V3CCtors.cpp | 57 +- src/V3Case.cpp | 218 +-- src/V3Cast.cpp | 51 +- src/V3Cdc.cpp | 368 ++--- src/V3Changed.cpp | 122 +- src/V3Clean.cpp | 95 +- src/V3Clock.cpp | 150 +- src/V3Combine.cpp | 191 ++- src/V3Config.cpp | 4 +- src/V3Const.cpp | 1056 +++++++------- src/V3Dead.cpp | 199 ++- src/V3Delayed.cpp | 211 +-- src/V3Depth.cpp | 2 +- src/V3Descope.cpp | 2 +- src/V3EmitC.cpp | 1509 ++++++++++--------- src/V3EmitCBase.h | 40 +- src/V3EmitCMake.cpp | 66 +- src/V3EmitMk.cpp | 174 +-- src/V3EmitV.cpp | 264 ++-- src/V3EmitXml.cpp | 189 ++- src/V3Error.cpp | 152 +- src/V3Error.h | 215 +-- src/V3Expand.cpp | 545 +++---- src/V3File.cpp | 591 ++++---- src/V3File.h | 59 +- src/V3FileLine.cpp | 136 +- src/V3FileLine.h | 91 +- src/V3Gate.cpp | 602 ++++---- src/V3GenClk.cpp | 55 +- src/V3Graph.cpp | 184 ++- src/V3GraphAcyc.cpp | 196 +-- src/V3GraphAlg.cpp | 168 +-- src/V3GraphTest.cpp | 136 +- src/V3Hashed.cpp | 77 +- src/V3Inline.cpp | 63 +- src/V3Inst.cpp | 243 ++-- src/V3Life.cpp | 124 +- src/V3LifePost.cpp | 61 +- src/V3LinkCells.cpp | 177 +-- src/V3LinkDot.cpp | 1284 +++++++++-------- src/V3LinkJump.cpp | 132 +- src/V3LinkLevel.cpp | 67 +- src/V3LinkParse.cpp | 228 ++- src/V3LinkResolve.cpp | 132 +- src/V3Number.cpp | 1165 ++++++++------- src/V3Number.h | 402 +++--- src/V3Order.cpp | 776 +++++----- src/V3Param.cpp | 365 ++--- src/V3ParseGrammar.cpp | 121 +- src/V3ParseImp.cpp | 81 +- src/V3ParseImp.h | 127 +- src/V3Partition.cpp | 702 ++++----- src/V3PreLex.l | 4 +- src/V3PreProc.cpp | 857 +++++------ src/V3Premit.cpp | 154 +- src/V3ProtectLib.cpp | 280 ++-- src/V3Scope.cpp | 135 +- src/V3SenTree.h | 5 +- src/V3Simulate.h | 303 ++-- src/V3Slice.cpp | 143 +- src/V3Split.cpp | 245 ++-- src/V3SplitAs.cpp | 62 +- src/V3SplitVar.cpp | 47 +- src/V3Subst.cpp | 162 +-- src/V3TSP.cpp | 204 ++- src/V3Table.cpp | 184 ++- src/V3Task.cpp | 526 ++++--- src/V3Trace.cpp | 2 +- src/V3Tristate.cpp | 549 ++++--- src/V3Undriven.cpp | 168 ++- src/V3Unknown.cpp | 210 ++- src/V3Unroll.cpp | 209 +-- src/V3Width.cpp | 2027 +++++++++++++------------- src/V3WidthCommit.h | 8 +- src/V3WidthSel.cpp | 358 +++-- 85 files changed, 14640 insertions(+), 13099 deletions(-) delete mode 100755 nodist/clang_formatter diff --git a/Makefile.in b/Makefile.in index dfb5d3c0f..f96f4c85c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -456,6 +456,12 @@ analyzer-include: -rm -rf examples/*/obj* scan-build $(MAKE) -k examples +CLANGFORMAT = clang-format +CLANGFORMAT_FLAGS = -i + +clang-format: + $(CLANGFORMAT) $(CLANGFORMAT_FLAGS) $(CPPCHECK_CPP) $(CPPCHECK_H) + ftp: info install-msg: diff --git a/nodist/clang_formatter b/nodist/clang_formatter deleted file mode 100755 index c9ee2b72a..000000000 --- a/nodist/clang_formatter +++ /dev/null @@ -1,236 +0,0 @@ -#!/bin/bash -# -# clang-format is used to standardize the indentation of the internal C++ -# code. -# -# For the most part clang-format changes provide good consistency, the two -# main exceptions being the indentation of preprocessor directives, and -# tables of statements. Reformatting is generally performed only before -# other large changes are to be made to a file. -# -# "##" files commented out below are not yet clang-format clean. -# "#" files commented out hit a clang-format limitation with ifdefs. - -clang-format -i examples/make_hello_c/sim_main.cpp -clang-format -i examples/make_hello_sc/sc_main.cpp -#clang-format -i examples/make_protect_lib/sim_main.cpp -clang-format -i examples/make_tracing_c/sim_main.cpp -clang-format -i examples/make_tracing_sc/sc_main.cpp -clang-format -i include/*.cpp -clang-format -i include/*.h -clang-format -i include/verilated_config.h.in -clang-format -i nodist/fuzzer/wrapper.cpp -clang-format -i src/V3Active.cpp -clang-format -i src/V3Active.h -clang-format -i src/V3ActiveTop.cpp -clang-format -i src/V3ActiveTop.h -clang-format -i src/V3Assert.cpp -clang-format -i src/V3Assert.h -clang-format -i src/V3AssertPre.cpp -clang-format -i src/V3AssertPre.h -##clang-format -i src/V3Ast.cpp -##clang-format -i src/V3Ast.h -clang-format -i src/V3AstConstOnly.h -##clang-format -i src/V3AstNodes.cpp -##clang-format -i src/V3AstNodes.h -##clang-format -i src/V3Begin.cpp -clang-format -i src/V3Begin.h -clang-format -i src/V3Branch.cpp -clang-format -i src/V3Branch.h -##clang-format -i src/V3Broken.cpp -clang-format -i src/V3Broken.h -##clang-format -i src/V3CCtors.cpp -clang-format -i src/V3CCtors.h -clang-format -i src/V3CUse.cpp -clang-format -i src/V3CUse.h -##clang-format -i src/V3Case.cpp -clang-format -i src/V3Case.h -##clang-format -i src/V3Cast.cpp -clang-format -i src/V3Cast.h -##clang-format -i src/V3Cdc.cpp -clang-format -i src/V3Cdc.h -##clang-format -i src/V3Changed.cpp -clang-format -i src/V3Changed.h -clang-format -i src/V3Class.cpp -clang-format -i src/V3Class.h -##clang-format -i src/V3Clean.cpp -clang-format -i src/V3Clean.h -##clang-format -i src/V3Clock.cpp -clang-format -i src/V3Clock.h -##clang-format -i src/V3Combine.cpp -clang-format -i src/V3Combine.h -clang-format -i src/V3Config.cpp -clang-format -i src/V3Config.h -##clang-format -i src/V3Const.cpp -clang-format -i src/V3Const.h -clang-format -i src/V3Coverage.cpp -clang-format -i src/V3Coverage.h -clang-format -i src/V3CoverageJoin.cpp -clang-format -i src/V3CoverageJoin.h -##clang-format -i src/V3Dead.cpp -clang-format -i src/V3Dead.h -##clang-format -i src/V3Delayed.cpp -clang-format -i src/V3Delayed.h -clang-format -i src/V3Depth.cpp -clang-format -i src/V3Depth.h -clang-format -i src/V3DepthBlock.cpp -clang-format -i src/V3DepthBlock.h -clang-format -i src/V3Descope.cpp -clang-format -i src/V3Descope.h -##clang-format -i src/V3EmitC.cpp -clang-format -i src/V3EmitC.h -##clang-format -i src/V3EmitCBase.h -clang-format -i src/V3EmitCInlines.cpp -##clang-format -i src/V3EmitCMake.cpp -clang-format -i src/V3EmitCMake.h -clang-format -i src/V3EmitCSyms.cpp -##clang-format -i src/V3EmitMk.cpp -clang-format -i src/V3EmitMk.h -##clang-format -i src/V3EmitV.cpp -clang-format -i src/V3EmitV.h -##clang-format -i src/V3EmitXml.cpp -clang-format -i src/V3EmitXml.h -##clang-format -i src/V3Error.cpp -##clang-format -i src/V3Error.h -##clang-format -i src/V3Expand.cpp -clang-format -i src/V3Expand.h -##clang-format -i src/V3File.cpp -##clang-format -i src/V3File.h -##clang-format -i src/V3FileLine.cpp -##clang-format -i src/V3FileLine.h -##clang-format -i src/V3Gate.cpp -clang-format -i src/V3Gate.h -##clang-format -i src/V3GenClk.cpp -clang-format -i src/V3GenClk.h -clang-format -i src/V3Global.cpp -clang-format -i src/V3Global.h -##clang-format -i src/V3Graph.cpp -clang-format -i src/V3Graph.h -##clang-format -i src/V3GraphAcyc.cpp -##clang-format -i src/V3GraphAlg.cpp -clang-format -i src/V3GraphAlg.h -clang-format -i src/V3GraphDfa.cpp -clang-format -i src/V3GraphDfa.h -clang-format -i src/V3GraphPathChecker.cpp -clang-format -i src/V3GraphPathChecker.h -clang-format -i src/V3GraphStream.h -##clang-format -i src/V3GraphTest.cpp -##clang-format -i src/V3Hashed.cpp -clang-format -i src/V3Hashed.h -##clang-format -i src/V3Inline.cpp -clang-format -i src/V3Inline.h -##clang-format -i src/V3Inst.cpp -clang-format -i src/V3Inst.h -clang-format -i src/V3InstrCount.cpp -clang-format -i src/V3InstrCount.h -clang-format -i src/V3LangCode.h -clang-format -i src/V3LanguageWords.h -##clang-format -i src/V3Life.cpp -clang-format -i src/V3Life.h -##clang-format -i src/V3LifePost.cpp -clang-format -i src/V3LifePost.h -##clang-format -i src/V3LinkCells.cpp -clang-format -i src/V3LinkCells.h -##clang-format -i src/V3LinkDot.cpp -clang-format -i src/V3LinkDot.h -##clang-format -i src/V3LinkJump.cpp -clang-format -i src/V3LinkJump.h -clang-format -i src/V3LinkLValue.cpp -clang-format -i src/V3LinkLValue.h -##clang-format -i src/V3LinkLevel.cpp -clang-format -i src/V3LinkLevel.h -##clang-format -i src/V3LinkParse.cpp -clang-format -i src/V3LinkParse.h -##clang-format -i src/V3LinkResolve.cpp -clang-format -i src/V3LinkResolve.h -clang-format -i src/V3List.h -clang-format -i src/V3Localize.cpp -clang-format -i src/V3Localize.h -clang-format -i src/V3Name.cpp -clang-format -i src/V3Name.h -##clang-format -i src/V3Number.cpp -##clang-format -i src/V3Number.h -clang-format -i src/V3Number_test.cpp -clang-format -i src/V3Options.cpp -clang-format -i src/V3Options.h -##clang-format -i src/V3Order.cpp -clang-format -i src/V3Order.h -clang-format -i src/V3OrderGraph.h -clang-format -i src/V3Os.cpp -clang-format -i src/V3Os.h -##clang-format -i src/V3Param.cpp -clang-format -i src/V3Param.h -clang-format -i src/V3Parse.h -##clang-format -i src/V3ParseGrammar.cpp -##clang-format -i src/V3ParseImp.cpp -##clang-format -i src/V3ParseImp.h -clang-format -i src/V3ParseLex.cpp -clang-format -i src/V3ParseSym.h -##clang-format -i src/V3Partition.cpp -clang-format -i src/V3Partition.h -clang-format -i src/V3PartitionGraph.h -clang-format -i src/V3PreLex.h -##clang-format -i src/V3PreProc.cpp -clang-format -i src/V3PreProc.h -clang-format -i src/V3PreShell.cpp -clang-format -i src/V3PreShell.h -##clang-format -i src/V3Premit.cpp -clang-format -i src/V3Premit.h -##clang-format -i src/V3ProtectLib.cpp -clang-format -i src/V3ProtectLib.h -clang-format -i src/V3Reloop.cpp -clang-format -i src/V3Reloop.h -##clang-format -i src/V3Scope.cpp -clang-format -i src/V3Scope.h -clang-format -i src/V3Scoreboard.cpp -clang-format -i src/V3Scoreboard.h -clang-format -i src/V3SenTree.h -##clang-format -i src/V3Simulate.h -##clang-format -i src/V3Slice.cpp -clang-format -i src/V3Slice.h -##clang-format -i src/V3Split.cpp -clang-format -i src/V3Split.h -##clang-format -i src/V3SplitAs.cpp -clang-format -i src/V3SplitAs.h -##clang-format -i src/V3SplitVar.cpp -clang-format -i src/V3SplitVar.h -clang-format -i src/V3Stats.cpp -clang-format -i src/V3Stats.h -clang-format -i src/V3StatsReport.cpp -clang-format -i src/V3String.cpp -clang-format -i src/V3String.h -##clang-format -i src/V3Subst.cpp -clang-format -i src/V3Subst.h -clang-format -i src/V3SymTable.h -##clang-format -i src/V3TSP.cpp -clang-format -i src/V3TSP.h -##clang-format -i src/V3Table.cpp -clang-format -i src/V3Table.h -##clang-format -i src/V3Task.cpp -clang-format -i src/V3Task.h -clang-format -i src/V3Trace.cpp -clang-format -i src/V3Trace.h -clang-format -i src/V3TraceDecl.cpp -clang-format -i src/V3TraceDecl.h -##clang-format -i src/V3Tristate.cpp -clang-format -i src/V3Tristate.h -##clang-format -i src/V3Undriven.cpp -clang-format -i src/V3Undriven.h -##clang-format -i src/V3Unknown.cpp -clang-format -i src/V3Unknown.h -##clang-format -i src/V3Unroll.cpp -clang-format -i src/V3Unroll.h -##clang-format -i src/V3Width.cpp -clang-format -i src/V3Width.h -clang-format -i src/V3WidthCommit.h -##clang-format -i src/V3WidthSel.cpp -clang-format -i src/Verilator.cpp -clang-format -i src/VlcBucket.h -clang-format -i src/VlcMain.cpp -clang-format -i src/VlcOptions.h -clang-format -i src/VlcPoint.h -clang-format -i src/VlcSource.h -clang-format -i src/VlcTest.h -clang-format -i src/VlcTop.cpp -clang-format -i src/VlcTop.h -clang-format -i src/config_build.h.in diff --git a/src/V3Active.cpp b/src/V3Active.cpp index efc8eef8e..42c3ea5d1 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -364,7 +364,7 @@ private: virtual void visit(AstAlways* nodep) VL_OVERRIDE { // Move always to appropriate ACTIVE based on its sense list UINFO(4, " ALW " << nodep << endl); - // if (debug()>=9) nodep->dumpTree(cout, " Alw: "); + // if (debug() >= 9) nodep->dumpTree(cout, " Alw: "); if (!nodep->bodysp()) { // Empty always. Kill it. @@ -376,7 +376,7 @@ private: virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE { // Move always to appropriate ACTIVE based on its sense list UINFO(4, " ALWPub " << nodep << endl); - // if (debug()>=9) nodep->dumpTree(cout, " Alw: "); + // if (debug() >= 9) nodep->dumpTree(cout, " Alw: "); visitAlways(nodep, nodep->sensesp(), VAlwaysKwd::ALWAYS); } virtual void visit(AstSenGate* nodep) VL_OVERRIDE { diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index 37377ac38..1dd64a7da 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -322,7 +322,7 @@ private: AstNode* assp = new AstAssignDly(nodep->fileline(), new AstVarRef(nodep->fileline(), outvarp, true), inp); alwaysp->addStmtp(assp); - // if (debug()>-9) assp->dumpTree(cout, "-ass: "); + // if (debug() >= 9) assp->dumpTree(cout, "-ass: "); invarp = outvarp; inp = new AstVarRef(nodep->fileline(), invarp, false); } diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 7d7e1b1f4..8f0a5373e 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -51,7 +51,6 @@ bool AstUser5InUse::s_userBusy = false; int AstNodeDType::s_uniqueNum = 0; - //###################################################################### // V3AstType @@ -102,15 +101,16 @@ AstNode* AstNode::abovep() const { string AstNode::encodeName(const string& namein) { // Encode signal name raw from parser, then not called again on same signal string out; - for (string::const_iterator pos = namein.begin(); pos!=namein.end(); ++pos) { - if ((pos==namein.begin()) ? isalpha(pos[0]) // digits can't lead identifiers - : isalnum(pos[0])) { + for (string::const_iterator pos = namein.begin(); pos != namein.end(); ++pos) { + if ((pos == namein.begin()) ? isalpha(pos[0]) // digits can't lead identifiers + : isalnum(pos[0])) { out += pos[0]; - } else if (pos[0]=='_') { - if (pos[1]=='_') { - out += "_"; out += "__05F"; // hex(_) = 0x5F + } else if (pos[0] == '_') { + if (pos[1] == '_') { + out += "_"; + out += "__05F"; // hex(_) = 0x5F ++pos; - if (pos==namein.end()) break; + if (pos == namein.end()) break; } else { out += pos[0]; } @@ -120,7 +120,8 @@ string AstNode::encodeName(const string& namein) { // We also do *NOT* use __DOT__ etc, as we search for those // in some replacements, and don't want to mangle the user's names. unsigned val = pos[0] & 0xff; // Mask to avoid sign extension - char hex[10]; sprintf(hex, "__0%02X", val); + char hex[10]; + sprintf(hex, "__0%02X", val); out += hex; } } @@ -133,34 +134,26 @@ string AstNode::encodeName(const string& namein) { string AstNode::encodeNumber(vlsint64_t num) { if (num < 0) { - return "__02D"+cvtToStr(-num); // 2D=- + return "__02D" + cvtToStr(-num); // 2D=- } else { return cvtToStr(num); } } -string AstNode::nameProtect() const { - return VIdProtect::protectIf(name(), protect()); -} -string AstNode::origNameProtect() const { - return VIdProtect::protectIf(origName(), protect()); -} +string AstNode::nameProtect() const { return VIdProtect::protectIf(name(), protect()); } +string AstNode::origNameProtect() const { return VIdProtect::protectIf(origName(), protect()); } string AstNode::shortName() const { string pretty = name(); string::size_type pos; - while ((pos = pretty.find("__PVT__")) != string::npos) { - pretty.replace(pos, 7, ""); - } + while ((pos = pretty.find("__PVT__")) != string::npos) pretty.replace(pos, 7, ""); return pretty; } string AstNode::dedotName(const string& namein) { string pretty = namein; string::size_type pos; - while ((pos = pretty.find("__DOT__")) != string::npos) { - pretty.replace(pos, 7, "."); - } + while ((pos = pretty.find("__DOT__")) != string::npos) pretty.replace(pos, 7, "."); if (pretty.substr(0, 4) == "TOP.") pretty.replace(0, 4, ""); return pretty; } @@ -170,12 +163,8 @@ string AstNode::vcdName(const string& namein) { // Dots are reserved for dots the user put in the name string pretty = namein; string::size_type pos; - while ((pos = pretty.find("__DOT__")) != string::npos) { - pretty.replace(pos, 7, " "); - } - while ((pos = pretty.find('.')) != string::npos) { - pretty.replace(pos, 1, " "); - } + while ((pos = pretty.find("__DOT__")) != string::npos) pretty.replace(pos, 7, " "); + while ((pos = pretty.find('.')) != string::npos) pretty.replace(pos, 1, " "); // Now convert escaped special characters, etc return prettyName(pretty); } @@ -185,38 +174,38 @@ string AstNode::prettyName(const string& namein) { string pretty; pretty = ""; pretty.reserve(namein.length()); - for (const char* pos = namein.c_str(); *pos; ) { - if (pos[0]=='-' && pos[1]=='>') { // -> + for (const char* pos = namein.c_str(); *pos;) { + if (pos[0] == '-' && pos[1] == '>') { // -> pretty += "."; pos += 2; continue; } - if (pos[0]=='_' && pos[1]=='_') { // Short-circuit - if (0==strncmp(pos, "__BRA__", 7)) { + if (pos[0] == '_' && pos[1] == '_') { // Short-circuit + if (0 == strncmp(pos, "__BRA__", 7)) { pretty += "["; pos += 7; continue; } - if (0==strncmp(pos, "__KET__", 7)) { + if (0 == strncmp(pos, "__KET__", 7)) { pretty += "]"; pos += 7; continue; } - if (0==strncmp(pos, "__DOT__", 7)) { + if (0 == strncmp(pos, "__DOT__", 7)) { pretty += "."; pos += 7; continue; } - if (0==strncmp(pos, "__PVT__", 7)) { + if (0 == strncmp(pos, "__PVT__", 7)) { pretty += ""; pos += 7; continue; } - if (pos[0]=='_' && pos[1]=='_' && pos[2]=='0' - && isxdigit(pos[3]) && isxdigit(pos[4])) { + if (pos[0] == '_' && pos[1] == '_' && pos[2] == '0' && isxdigit(pos[3]) + && isxdigit(pos[4])) { char value = 0; - value += 16*(isdigit(pos[3]) ? (pos[3]-'0') : (tolower(pos[3])-'a'+10)); - value += (isdigit(pos[4]) ? (pos[4]-'0') : (tolower(pos[4])-'a'+10)); + value += 16 * (isdigit(pos[3]) ? (pos[3] - '0') : (tolower(pos[3]) - 'a' + 10)); + value += (isdigit(pos[4]) ? (pos[4] - '0') : (tolower(pos[4]) - 'a' + 10)); pretty += value; pos += 5; continue; @@ -226,37 +215,37 @@ string AstNode::prettyName(const string& namein) { pretty += pos[0]; ++pos; } - if (pretty[0]=='T' && pretty.substr(0, 4) == "TOP.") pretty.replace(0, 4, ""); - if (pretty[0]=='T' && pretty.substr(0, 5) == "TOP->") pretty.replace(0, 5, ""); + if (pretty[0] == 'T' && pretty.substr(0, 4) == "TOP.") pretty.replace(0, 4, ""); + if (pretty[0] == 'T' && pretty.substr(0, 5) == "TOP->") pretty.replace(0, 5, ""); return pretty; } string AstNode::prettyTypeName() const { - if (name()=="") return typeName(); - return string(typeName())+" '"+prettyName()+"'"; + if (name() == "") return typeName(); + return string(typeName()) + " '" + prettyName() + "'"; } //###################################################################### // Insertion -inline void AstNode::debugTreeChange(const char* prefix, int lineno, bool next) { +inline void AstNode::debugTreeChange(const char* prefix, int lineno, bool next){ #ifdef VL_DEBUG - // Called on all major tree changers. - // Only for use for those really nasty bugs relating to internals - // Note this may be null. - //if (debug()) cout<<"-treeChange: V3Ast.cpp:"<"<dumpTree(cout, "-treeChange: "); - // if (next||1) this->dumpTreeAndNext(cout, prefix); - // else this->dumpTree(cout, prefix); - // this->checkTree(); - // v3Global.rootp()->checkTree(); - //} +// Called on all major tree changers. +// Only for use for those really nasty bugs relating to internals +// Note this may be null. +// if (debug()) cout<<"-treeChange: V3Ast.cpp:"<"<dumpTree(cout, "-treeChange: "); +// if (next||1) this->dumpTreeAndNext(cout, prefix); +// else this->dumpTree(cout, prefix); +// this->checkTree(); +// v3Global.rootp()->checkTree(); +//} #endif } @@ -276,8 +265,9 @@ AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp) { UDEBUGONLY(UASSERT_OBJ(!oldtailp->m_nextp, nodep, "Node had next, but headtail says it shouldn't");); } else { - // Though inefficient, we are occasionally passed a addNext in the middle of a list. - while (oldtailp->m_nextp != NULL) oldtailp = oldtailp->m_nextp; + // Though inefficient, we are occasionally passed an + // addNext in the middle of a list. + while (oldtailp->m_nextp) oldtailp = oldtailp->m_nextp; } } // Link it in @@ -328,15 +318,15 @@ void AstNode::addNextHere(AstNode* newp) { AstNode* oldheadtailp = this->m_headtailp; // (!oldheadtailp) // this was&is middle of list // (oldheadtailp==this && !oldnext)// this was head AND tail (one node long list) - // (oldheadtailp && oldnextp) // this was&is head of list of not just one node, not tail - // (oldheadtailp && !oldnextp) // this was tail of list, might also + // (oldheadtailp && oldnextp) // this was&is head of list of not just one node, not + // tail (oldheadtailp && !oldnextp) // this was tail of list, might also // be head of one-node list // newp->m_headtailp = NULL; // Not at head any longer addlastp->m_headtailp = NULL; // Presume middle of list // newp might happen to be head/tail after all, if so will be set again below if (oldheadtailp) { // else in middle of list, no change - if (oldheadtailp==this) { // this was one node + if (oldheadtailp == this) { // this was one node this->m_headtailp = addlastp; // Was head/tail, now a tail addlastp->m_headtailp = oldheadtailp; // Tail needs to remember head (or NULL) } else if (!oldnextp) { // this was tail @@ -404,26 +394,38 @@ void AstNode::setOp4p(AstNode* newp) { void AstNode::addOp1p(AstNode* newp) { UASSERT(newp, "Null item passed to addOp1p"); - if (!m_op1p) { op1p(newp); } - else { m_op1p->addNext(newp); } + if (!m_op1p) { + op1p(newp); + } else { + m_op1p->addNext(newp); + } } void AstNode::addOp2p(AstNode* newp) { UASSERT(newp, "Null item passed to addOp2p"); - if (!m_op2p) { op2p(newp); } - else { m_op2p->addNext(newp); } + if (!m_op2p) { + op2p(newp); + } else { + m_op2p->addNext(newp); + } } void AstNode::addOp3p(AstNode* newp) { UASSERT(newp, "Null item passed to addOp3p"); - if (!m_op3p) { op3p(newp); } - else { m_op3p->addNext(newp); } + if (!m_op3p) { + op3p(newp); + } else { + m_op3p->addNext(newp); + } } void AstNode::addOp4p(AstNode* newp) { UASSERT(newp, "Null item passed to addOp4p"); - if (!m_op4p) { op4p(newp); } - else { m_op4p->addNext(newp); } + if (!m_op4p) { + op4p(newp); + } else { + m_op4p->addNext(newp); + } } void AstNode::replaceWith(AstNode* newp) { @@ -435,13 +437,13 @@ void AstNode::replaceWith(AstNode* newp) { } void AstNRelinker::dump(std::ostream& str) const { - str<<" BK="<(m_backp); - str<<" ITER="<(m_iterpp); - str<<" CHG="<<(m_chg==RELINK_NEXT?"[NEXT] ":""); - str<<(m_chg==RELINK_OP1?"[OP1] ":""); - str<<(m_chg==RELINK_OP2?"[OP2] ":""); - str<<(m_chg==RELINK_OP3?"[OP3] ":""); - str<<(m_chg==RELINK_OP4?"[OP4] ":""); + str << " BK=" << reinterpret_cast(m_backp); + str << " ITER=" << reinterpret_cast(m_iterpp); + str << " CHG=" << (m_chg == RELINK_NEXT ? "[NEXT] " : ""); + str << (m_chg == RELINK_OP1 ? "[OP1] " : ""); + str << (m_chg == RELINK_OP2 ? "[OP2] " : ""); + str << (m_chg == RELINK_OP3 ? "[OP3] " : ""); + str << (m_chg == RELINK_OP4 ? "[OP4] " : ""); } AstNode* AstNode::unlinkFrBackWithNext(AstNRelinker* linkerp) { @@ -452,17 +454,24 @@ AstNode* AstNode::unlinkFrBackWithNext(AstNRelinker* linkerp) { AstNode* backp = oldp->m_backp; if (linkerp) { linkerp->m_oldp = oldp; - linkerp->m_backp = backp; + linkerp->m_backp = backp; linkerp->m_iterpp = oldp->m_iterpp; - if (backp->m_nextp == oldp) linkerp->m_chg = AstNRelinker::RELINK_NEXT; - else if (backp->m_op1p == oldp) linkerp->m_chg = AstNRelinker::RELINK_OP1; - else if (backp->m_op2p == oldp) linkerp->m_chg = AstNRelinker::RELINK_OP2; - else if (backp->m_op3p == oldp) linkerp->m_chg = AstNRelinker::RELINK_OP3; - else if (backp->m_op4p == oldp) linkerp->m_chg = AstNRelinker::RELINK_OP4; - else oldp->v3fatalSrc("Unlink of node with back not pointing to it."); + if (backp->m_nextp == oldp) { + linkerp->m_chg = AstNRelinker::RELINK_NEXT; + } else if (backp->m_op1p == oldp) { + linkerp->m_chg = AstNRelinker::RELINK_OP1; + } else if (backp->m_op2p == oldp) { + linkerp->m_chg = AstNRelinker::RELINK_OP2; + } else if (backp->m_op3p == oldp) { + linkerp->m_chg = AstNRelinker::RELINK_OP3; + } else if (backp->m_op4p == oldp) { + linkerp->m_chg = AstNRelinker::RELINK_OP4; + } else { + oldp->v3fatalSrc("Unlink of node with back not pointing to it."); + } } - if (backp->m_nextp== oldp) { - backp->m_nextp= NULL; + if (backp->m_nextp == oldp) { + backp->m_nextp = NULL; // Old list gets truncated // New list becomes a list upon itself // Most common case is unlinking a entire operand tree @@ -477,12 +486,17 @@ AstNode* AstNode::unlinkFrBackWithNext(AstNRelinker* linkerp) { // Create new head/tail of extracted list oldp->m_headtailp = oldtailp; oldp->m_headtailp->m_headtailp = oldp; + } else if (backp->m_op1p == oldp) { + backp->m_op1p = NULL; + } else if (backp->m_op2p == oldp) { + backp->m_op2p = NULL; + } else if (backp->m_op3p == oldp) { + backp->m_op3p = NULL; + } else if (backp->m_op4p == oldp) { + backp->m_op4p = NULL; + } else { + this->v3fatalSrc("Unlink of node with back not pointing to it."); } - else if (backp->m_op1p == oldp) backp->m_op1p = NULL; - else if (backp->m_op2p == oldp) backp->m_op2p = NULL; - else if (backp->m_op3p == oldp) backp->m_op3p = NULL; - else if (backp->m_op4p == oldp) backp->m_op4p = NULL; - else this->v3fatalSrc("Unlink of node with back not pointing to it."); // Relink oldp->m_backp = NULL; // Iterator fixup @@ -500,32 +514,44 @@ AstNode* AstNode::unlinkFrBack(AstNRelinker* linkerp) { AstNode* backp = oldp->m_backp; if (linkerp) { linkerp->m_oldp = oldp; - linkerp->m_backp = backp; + linkerp->m_backp = backp; linkerp->m_iterpp = oldp->m_iterpp; - if (backp->m_nextp == oldp) linkerp->m_chg = AstNRelinker::RELINK_NEXT; - else if (backp->m_op1p == oldp) linkerp->m_chg = AstNRelinker::RELINK_OP1; - else if (backp->m_op2p == oldp) linkerp->m_chg = AstNRelinker::RELINK_OP2; - else if (backp->m_op3p == oldp) linkerp->m_chg = AstNRelinker::RELINK_OP3; - else if (backp->m_op4p == oldp) linkerp->m_chg = AstNRelinker::RELINK_OP4; - else this->v3fatalSrc("Unlink of node with back not pointing to it."); + if (backp->m_nextp == oldp) { + linkerp->m_chg = AstNRelinker::RELINK_NEXT; + } else if (backp->m_op1p == oldp) { + linkerp->m_chg = AstNRelinker::RELINK_OP1; + } else if (backp->m_op2p == oldp) { + linkerp->m_chg = AstNRelinker::RELINK_OP2; + } else if (backp->m_op3p == oldp) { + linkerp->m_chg = AstNRelinker::RELINK_OP3; + } else if (backp->m_op4p == oldp) { + linkerp->m_chg = AstNRelinker::RELINK_OP4; + } else { + this->v3fatalSrc("Unlink of node with back not pointing to it."); + } } - if (backp->m_nextp== oldp) { + if (backp->m_nextp == oldp) { // This node gets removed from middle (or tail) of list // Not head, since then oldp wouldn't be a next of backp... - backp->m_nextp= oldp->m_nextp; + backp->m_nextp = oldp->m_nextp; if (backp->m_nextp) backp->m_nextp->m_backp = backp; // If it was a tail, back becomes new tail if (oldp->m_headtailp) { backp->m_headtailp = oldp->m_headtailp; backp->m_headtailp->m_headtailp = backp; } - } - else { - if (backp->m_op1p == oldp) backp->m_op1p = oldp->m_nextp; - else if (backp->m_op2p == oldp) backp->m_op2p = oldp->m_nextp; - else if (backp->m_op3p == oldp) backp->m_op3p = oldp->m_nextp; - else if (backp->m_op4p == oldp) backp->m_op4p = oldp->m_nextp; - else this->v3fatalSrc("Unlink of node with back not pointing to it."); + } else { + if (backp->m_op1p == oldp) { + backp->m_op1p = oldp->m_nextp; + } else if (backp->m_op2p == oldp) { + backp->m_op2p = oldp->m_nextp; + } else if (backp->m_op3p == oldp) { + backp->m_op3p = oldp->m_nextp; + } else if (backp->m_op4p == oldp) { + backp->m_op4p = oldp->m_nextp; + } else { + this->v3fatalSrc("Unlink of node with back not pointing to it."); + } if (oldp->m_nextp) { AstNode* newheadp = oldp->m_nextp; newheadp->m_backp = backp; @@ -545,13 +571,19 @@ AstNode* AstNode::unlinkFrBack(AstNRelinker* linkerp) { } void AstNode::relink(AstNRelinker* linkerp) { - if (debug()>8) { UINFO(0," EDIT: relink: "); dumpPtrs(); } + if (debug() > 8) { + UINFO(0, " EDIT: relink: "); + dumpPtrs(); + } AstNode* newp = this; UASSERT(linkerp && linkerp->m_backp, "Need non-empty linker"); UASSERT(!newp->backp(), "New node already linked?"); newp->editCountInc(); - if (debug()>8) { linkerp->dump(cout); cout< 8) { + linkerp->dump(cout); + cout << endl; + } AstNode* backp = linkerp->m_backp; this->debugTreeChange("-relinkNew: ", __LINE__, true); @@ -563,9 +595,7 @@ void AstNode::relink(AstNRelinker* linkerp) { case AstNRelinker::RELINK_OP2: relinkOneLink(backp->m_op2p /*ref*/, newp); break; case AstNRelinker::RELINK_OP3: relinkOneLink(backp->m_op3p /*ref*/, newp); break; case AstNRelinker::RELINK_OP4: relinkOneLink(backp->m_op4p /*ref*/, newp); break; - default: - this->v3fatalSrc("Relink of node without any link to change."); - break; + default: this->v3fatalSrc("Relink of node without any link to change."); break; } // Relink newp->m_backp = backp; @@ -595,10 +625,10 @@ void AstNode::relinkOneLink(AstNode*& pointpr, // Ref to pointer that gets set // Insert the whole old list following the new node's list. // Thus a unlink without next, followed by relink, gives the same list. AstNode* newlistlastp = newp->m_headtailp; - UASSERT_OBJ(!(newlistlastp->m_nextp && newlistlastp!=newp), newp, + UASSERT_OBJ(!(newlistlastp->m_nextp && newlistlastp != newp), newp, "Headtailp tail isn't at the tail"); AstNode* oldlistlastp = pointpr->m_headtailp; - UASSERT_OBJ(!(oldlistlastp->m_nextp && oldlistlastp!=pointpr), newp, + UASSERT_OBJ(!(oldlistlastp->m_nextp && oldlistlastp != pointpr), newp, "Old headtailp tail isn't at the tail"); // Next links newlistlastp->m_nextp = pointpr; @@ -650,7 +680,7 @@ AstNode* AstNode::cloneTreeIterList() { AstNode* newheadp = NULL; AstNode* newtailp = NULL; // Audited to make sure this is never NULL - for (AstNode* oldp = this; oldp; oldp=oldp->m_nextp) { + for (AstNode* oldp = this; oldp; oldp = oldp->m_nextp) { AstNode* newp = oldp->cloneTreeIter(); newp->m_headtailp = NULL; newp->m_backp = newtailp; @@ -701,7 +731,7 @@ void AstNode::deleteNode() { #else !v3Global.opt.debugLeak() #endif - ) { + ) { delete this; } // Else leak massively, so each pointer is unique @@ -711,7 +741,7 @@ void AstNode::deleteNode() { void AstNode::deleteTreeIter() { // private: Delete list of nodes. Publicly call deleteTree() instead. // Audited to make sure this is never NULL - for (AstNode* nodep=this, *nnextp; nodep; nodep=nnextp) { + for (AstNode *nodep = this, *nnextp; nodep; nodep = nnextp) { nnextp = nodep->m_nextp; // MUST be depth first! if (nodep->m_op1p) nodep->m_op1p->deleteTreeIter(); @@ -789,26 +819,25 @@ void AstNode::iterateAndNext(AstNVisitor& v) { // there's no lower level reason yet though the back must exist. AstNode* nodep = this; #ifdef VL_DEBUG // Otherwise too hot of a function for debug - UASSERT_OBJ(!(nodep && !nodep->m_backp), nodep, - "iterateAndNext node has no back"); + UASSERT_OBJ(!(nodep && !nodep->m_backp), nodep, "iterateAndNext node has no back"); #endif if (nodep) ASTNODE_PREFETCH(nodep->m_nextp); - while (nodep) { // effectively: if (!this) return; // Callers rely on this + while (nodep) { // effectively: if (!this) return; // Callers rely on this if (nodep->m_nextp) ASTNODE_PREFETCH(nodep->m_nextp->m_nextp); - AstNode* niterp = nodep; // This address may get stomped via m_iterpp if the node is edited + AstNode* niterp = nodep; // Pointer may get stomped via m_iterpp if the node is edited // Desirable check, but many places where multiple iterations are OK - // UASSERT_OBJ(!niterp->m_iterpp, niterp, "IterateAndNext under iterateAndNext may miss edits"); - // Optimization note: Doing PREFETCH_RW on m_iterpp is a net even + // UASSERT_OBJ(!niterp->m_iterpp, niterp, "IterateAndNext under iterateAndNext may miss + // edits"); Optimization note: Doing PREFETCH_RW on m_iterpp is a net even // cppcheck-suppress nullPointer niterp->m_iterpp = &niterp; niterp->accept(v); // accept may do a replaceNode and change niterp on us... // niterp maybe NULL, so need cast if printing - //if (niterp != nodep) UINFO(1,"iterateAndNext edited "<m_iterpp = NULL; - if (VL_UNLIKELY(niterp!=nodep)) { // Edited node inside accept + if (VL_UNLIKELY(niterp != nodep)) { // Edited node inside accept nodep = niterp; } else { // Unchanged node, just continue loop nodep = niterp->m_nextp; @@ -822,8 +851,11 @@ void AstNode::iterateListBackwards(AstNVisitor& v) { while (nodep) { // Edits not supported: nodep->m_iterpp = &nodep; nodep->accept(v); - if (nodep->backp()->m_nextp == nodep) nodep = nodep->backp(); - else nodep = NULL; // else: backp points up the tree. + if (nodep->backp()->m_nextp == nodep) { + nodep = nodep->backp(); + } else { + nodep = NULL; + } // else: backp points up the tree. } } @@ -861,7 +893,8 @@ AstNode* AstNode::iterateSubtreeReturnEdits(AstNVisitor& v) { // track, then delete it on completion AstBegin* tempp = new AstBegin(nodep->fileline(), "[EditWrapper]", nodep); { - VL_DO_DANGLING(tempp->stmtsp()->accept(v), nodep); // nodep to null as may be replaced + VL_DO_DANGLING(tempp->stmtsp()->accept(v), + nodep); // nodep to null as may be replaced } nodep = tempp->stmtsp()->unlinkFrBackWithNext(); VL_DO_DANGLING(tempp->deleteTree(), tempp); @@ -869,11 +902,17 @@ AstNode* AstNode::iterateSubtreeReturnEdits(AstNVisitor& v) { // Use back to determine who's pointing at us (IE assume new node // grafts into same place as old one) AstNode** nextnodepp = NULL; - if (this->m_backp->m_op1p == this) nextnodepp = &(this->m_backp->m_op1p); - else if (this->m_backp->m_op2p == this) nextnodepp = &(this->m_backp->m_op2p); - else if (this->m_backp->m_op3p == this) nextnodepp = &(this->m_backp->m_op3p); - else if (this->m_backp->m_op4p == this) nextnodepp = &(this->m_backp->m_op4p); - else if (this->m_backp->m_nextp == this) nextnodepp = &(this->m_backp->m_nextp); + if (this->m_backp->m_op1p == this) { + nextnodepp = &(this->m_backp->m_op1p); + } else if (this->m_backp->m_op2p == this) { + nextnodepp = &(this->m_backp->m_op2p); + } else if (this->m_backp->m_op3p == this) { + nextnodepp = &(this->m_backp->m_op3p); + } else if (this->m_backp->m_op4p == this) { + nextnodepp = &(this->m_backp->m_op4p); + } else if (this->m_backp->m_nextp == this) { + nextnodepp = &(this->m_backp->m_nextp); + } UASSERT_OBJ(nextnodepp, this, "Node's back doesn't point to forward to node itself"); { VL_DO_DANGLING(nodep->accept(v), nodep); // nodep to null as may be replaced @@ -887,10 +926,8 @@ AstNode* AstNode::iterateSubtreeReturnEdits(AstNVisitor& v) { void AstNode::cloneRelinkTree() { // private: Cleanup clone() operation on whole tree. Publicly call cloneTree() instead. - for (AstNode* nodep=this; nodep; nodep = nodep->m_nextp) { - if (m_dtypep && m_dtypep->clonep()) { - m_dtypep = m_dtypep->clonep(); - } + for (AstNode* nodep = this; nodep; nodep = nodep->m_nextp) { + if (m_dtypep && m_dtypep->clonep()) m_dtypep = m_dtypep->clonep(); nodep->cloneRelink(); if (nodep->m_op1p) nodep->m_op1p->cloneRelinkTree(); if (nodep->m_op2p) nodep->m_op2p->cloneRelinkTree(); @@ -912,37 +949,34 @@ bool AstNode::gateTreeIter() const { return true; } -bool AstNode::sameTreeIter(const AstNode* node1p, const AstNode* node2p, - bool ignNext, bool gateOnly) { +bool AstNode::sameTreeIter(const AstNode* node1p, const AstNode* node2p, bool ignNext, + bool gateOnly) { // private: Return true if the two trees are identical if (!node1p && !node2p) return true; if (!node1p || !node2p) return false; - if (node1p->type() != node2p->type() - || node1p->dtypep() != node2p->dtypep() - || !node1p->same(node2p) - || (gateOnly && !node1p->isGateOptimizable())) { + if (node1p->type() != node2p->type() || node1p->dtypep() != node2p->dtypep() + || !node1p->same(node2p) || (gateOnly && !node1p->isGateOptimizable())) { return false; } return (sameTreeIter(node1p->m_op1p, node2p->m_op1p, false, gateOnly) && sameTreeIter(node1p->m_op2p, node2p->m_op2p, false, gateOnly) && sameTreeIter(node1p->m_op3p, node2p->m_op3p, false, gateOnly) && sameTreeIter(node1p->m_op4p, node2p->m_op4p, false, gateOnly) - && (ignNext || sameTreeIter(node1p->m_nextp, node2p->m_nextp, false, gateOnly)) - ); + && (ignNext || sameTreeIter(node1p->m_nextp, node2p->m_nextp, false, gateOnly))); } //====================================================================== // Static utilities std::ostream& operator<<(std::ostream& os, const V3Hash& rhs) { - return os<backp(), this, "Back node inconsistent"); if (VN_IS(this, NodeTermop) || VN_IS(this, NodeVarRef)) { // Termops have a short-circuited iterateChildren, so check usage - UASSERT_OBJ(!(op1p()||op2p()||op3p()||op4p()), this, + UASSERT_OBJ(!(op1p() || op2p() || op3p() || op4p()), this, "Terminal operation with non-terminals"); } if (m_op1p) m_op1p->checkTreeIterList(this); @@ -969,9 +1003,9 @@ void AstNode::checkTreeIterList(AstNode* backp) { // Audited to make sure this is never NULL AstNode* headp = this; AstNode* tailp = this; - for (AstNode* nodep=headp; nodep; nodep=nodep->nextp()) { + for (AstNode* nodep = headp; nodep; nodep = nodep->nextp()) { nodep->checkTreeIter(backp); - UASSERT_OBJ(headp==this || !nextp(), this, + UASSERT_OBJ(headp == this || !nextp(), this, "Headtailp should be null in middle of lists"); tailp = nodep; backp = nodep; @@ -993,12 +1027,14 @@ void AstNode::checkTree() { // cppcheck-suppress unusedFunction // Debug only void AstNode::dumpGdb() { // For GDB only // LCOV_EXCL_LINE dumpGdbHeader(); // LCOV_EXCL_LINE - cout<<" "; dump(cout); cout<dumpTreeFile(filename); // LCOV_EXCL_LINE } @@ -1021,45 +1058,53 @@ void AstNode::checkIter() const { } void AstNode::dumpPtrs(std::ostream& os) const { - os<<"This="<8) { os<= 9) { - os<warnContextSecondary(); + os << indent << " " << this << endl; + if (debug() > 8) { + os << indent << " "; + dumpPtrs(os); } - if (maxDepth==1) { - if (op1p()||op2p()||op3p()||op4p()) { os<= 9) { os << fileline()->warnContextSecondary(); } + if (maxDepth == 1) { + if (op1p() || op2p() || op3p() || op4p()) { os << indent << "1: ...(maxDepth)" << endl; } } else { - for (const AstNode* nodep=op1p(); nodep; nodep=nodep->nextp()) { - nodep->dumpTree(os, indent+"1:", maxDepth-1); } - for (const AstNode* nodep=op2p(); nodep; nodep=nodep->nextp()) { - nodep->dumpTree(os, indent+"2:", maxDepth-1); } - for (const AstNode* nodep=op3p(); nodep; nodep=nodep->nextp()) { - nodep->dumpTree(os, indent+"3:", maxDepth-1); } - for (const AstNode* nodep=op4p(); nodep; nodep=nodep->nextp()) { - nodep->dumpTree(os, indent+"4:", maxDepth-1); } + for (const AstNode* nodep = op1p(); nodep; nodep = nodep->nextp()) { + nodep->dumpTree(os, indent + "1:", maxDepth - 1); + } + for (const AstNode* nodep = op2p(); nodep; nodep = nodep->nextp()) { + nodep->dumpTree(os, indent + "2:", maxDepth - 1); + } + for (const AstNode* nodep = op3p(); nodep; nodep = nodep->nextp()) { + nodep->dumpTree(os, indent + "3:", maxDepth - 1); + } + for (const AstNode* nodep = op4p(); nodep; nodep = nodep->nextp()) { + nodep->dumpTree(os, indent + "4:", maxDepth - 1); + } } } @@ -1073,16 +1118,15 @@ void AstNode::dumpTreeAndNext(std::ostream& os, const string& indent, int maxDep void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump) { // Not const function as calls checkTree if (doDump) { - { // Write log & close - UINFO(2,"Dumping "< logsp (V3File::new_ofstream(filename, append)); - if (logsp->fail()) v3fatal("Can't write "<"; - *logsp<<" to "<=9)) { - *logsp< logsp(V3File::new_ofstream(filename, append)); + if (logsp->fail()) v3fatal("Can't write " << filename); + *logsp << "Verilator Tree Dump (format 0x3900) from to " << endl; + if (editCountGbl() == editCountLast() && !(v3Global.opt.dumpTree() >= 9)) { + *logsp << endl; + *logsp << "No changes since last dump!\n"; } else { dumpTree(*logsp); } @@ -1100,7 +1144,9 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump) { } void AstNode::v3errorEndFatal(std::ostringstream& str) const { - v3errorEnd(str); assert(0); VL_UNREACHABLE + v3errorEnd(str); + assert(0); + VL_UNREACHABLE } string AstNode::locationStr() const { @@ -1148,12 +1194,12 @@ void AstNode::v3errorEnd(std::ostringstream& str) const { V3Error::v3errorEnd(str, locationStr()); } else { std::ostringstream nsstr; - nsstr<(this)->dump(nsstr); - nsstr<v3errorEnd(nsstr, locationStr()); } @@ -1164,8 +1210,7 @@ void AstNode::v3errorEnd(std::ostringstream& str) const { void AstNode::dtypeChgSigned(bool flag) { UASSERT_OBJ(dtypep(), this, "No dtype when changing to (un)signed"); - dtypeChgWidthSigned(dtypep()->width(), dtypep()->widthMin(), - AstNumeric::fromBool(flag)); + dtypeChgWidthSigned(dtypep()->width(), dtypep()->widthMin(), AstNumeric::fromBool(flag)); } void AstNode::dtypeChgWidth(int width, int widthMin) { UASSERT_OBJ(dtypep(), this, @@ -1178,9 +1223,9 @@ void AstNode::dtypeChgWidthSigned(int width, int widthMin, AstNumeric numeric) { // We allow dtypep() to be null, as before/during widthing dtypes are not resolved dtypeSetLogicUnsized(width, widthMin, numeric); } else { - if (width==dtypep()->width() - && widthMin==dtypep()->widthMin() - && numeric==dtypep()->numeric()) return; // Correct already + if (width == dtypep()->width() && widthMin == dtypep()->widthMin() + && numeric == dtypep()->numeric()) + return; // Correct already // FUTURE: We may be pointing at a two state data type, and this may // convert it to logic. Since the AstVar remains correct, we // work OK but this assumption may break in the future. @@ -1193,34 +1238,31 @@ void AstNode::dtypeChgWidthSigned(int width, int widthMin, AstNumeric numeric) { AstNodeDType* AstNode::findBasicDType(AstBasicDTypeKwd kwd) const { // For 'simple' types we use the global directory. These are all unsized. // More advanced types land under the module/task/etc - return v3Global.rootp()->typeTablep() - ->findBasicDType(fileline(), kwd); + return v3Global.rootp()->typeTablep()->findBasicDType(fileline(), kwd); } AstNodeDType* AstNode::findBitDType(int width, int widthMin, AstNumeric numeric) const { - return v3Global.rootp()->typeTablep() - ->findLogicBitDType(fileline(), AstBasicDTypeKwd::BIT, width, widthMin, numeric); + return v3Global.rootp()->typeTablep()->findLogicBitDType(fileline(), AstBasicDTypeKwd::BIT, + width, widthMin, numeric); } AstNodeDType* AstNode::findLogicDType(int width, int widthMin, AstNumeric numeric) const { - return v3Global.rootp()->typeTablep() - ->findLogicBitDType(fileline(), AstBasicDTypeKwd::LOGIC, width, widthMin, numeric); + return v3Global.rootp()->typeTablep()->findLogicBitDType(fileline(), AstBasicDTypeKwd::LOGIC, + width, widthMin, numeric); } AstNodeDType* AstNode::findLogicRangeDType(const VNumRange& range, int widthMin, AstNumeric numeric) const { - return v3Global.rootp()->typeTablep() - ->findLogicBitDType(fileline(), AstBasicDTypeKwd::LOGIC, range, widthMin, numeric); + return v3Global.rootp()->typeTablep()->findLogicBitDType(fileline(), AstBasicDTypeKwd::LOGIC, + range, widthMin, numeric); } AstNodeDType* AstNode::findBitRangeDType(const VNumRange& range, int widthMin, AstNumeric numeric) const { - return v3Global.rootp()->typeTablep() - ->findLogicBitDType(fileline(), AstBasicDTypeKwd::BIT, range, widthMin, numeric); + return v3Global.rootp()->typeTablep()->findLogicBitDType(fileline(), AstBasicDTypeKwd::BIT, + range, widthMin, numeric); } AstBasicDType* AstNode::findInsertSameDType(AstBasicDType* nodep) { - return v3Global.rootp()->typeTablep() - ->findInsertSameDType(nodep); + return v3Global.rootp()->typeTablep()->findInsertSameDType(nodep); } AstNodeDType* AstNode::findVoidDType() const { - return v3Global.rootp()->typeTablep() - ->findVoidDType(fileline()); + return v3Global.rootp()->typeTablep()->findVoidDType(fileline()); } //###################################################################### diff --git a/src/V3Ast.h b/src/V3Ast.h index b73b1840e..3f461b777 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -59,12 +59,12 @@ typedef std::set MTaskIdSet; // Set of mtaskIds for Var sorting } while (false) // (V)erilator (N)ode is: True if AstNode is of a a given AstType -#define VN_IS(nodep,nodetypename) (AstNode::privateIs(nodep)) +#define VN_IS(nodep, nodetypename) (AstNode::privateIs(nodep)) // (V)erilator (N)ode cast: Cast to given type if can; effectively // dynamic_cast(nodep) -#define VN_CAST(nodep,nodetypename) (AstNode::privateCast(nodep)) -#define VN_CAST_CONST(nodep,nodetypename) (AstNode::privateConstCast(nodep)) +#define VN_CAST(nodep, nodetypename) (AstNode::privateCast(nodep)) +#define VN_CAST_CONST(nodep, nodetypename) (AstNode::privateConstCast(nodep)) // (V)erilator (N)ode deleted: Reference to deleted child (for assertions only) #define VN_DELETED(nodep) VL_UNLIKELY((vluint64_t)(nodep) == 0x1) @@ -81,8 +81,10 @@ public: // cppcheck-suppress uninitVar // responsibility of each subclass inline AstType() {} // cppcheck-suppress noExplicitConstructor - inline AstType(en _e) : m_e(_e) {} - explicit inline AstType(int _e) : m_e(static_cast(_e)) {} + inline AstType(en _e) + : m_e(_e) {} + explicit inline AstType(int _e) + : m_e(static_cast(_e)) {} operator en() const { return m_e; } }; inline bool operator==(const AstType& lhs, const AstType& rhs) { return lhs.m_e == rhs.m_e; } @@ -94,7 +96,9 @@ inline std::ostream& operator<<(std::ostream& os, const AstType& rhs) { return o enum VSignedState { // This can't be in the fancy class as the lexer union will get upset - signedst_UNSIGNED = 0, signedst_SIGNED = 1, signedst_NOSIGN = 2 + signedst_UNSIGNED = 0, + signedst_SIGNED = 1, + signedst_NOSIGN = 2 }; //###################################################################### @@ -109,26 +113,32 @@ public: }; enum en m_e; const char* ascii() const { - static const char* const names[] = { - "UNSIGNED", "SIGNED", "NOSIGN" - }; + static const char* const names[] = {"UNSIGNED", "SIGNED", "NOSIGN"}; return names[m_e]; } - inline AstNumeric() : m_e(UNSIGNED) {} + inline AstNumeric() + : m_e(UNSIGNED) {} // cppcheck-suppress noExplicitConstructor - inline AstNumeric(en _e) : m_e(_e) {} + inline AstNumeric(en _e) + : m_e(_e) {} // cppcheck-suppress noExplicitConstructor inline AstNumeric(VSignedState signst) { - if (signst==signedst_UNSIGNED) m_e = UNSIGNED; - else if (signst==signedst_SIGNED) m_e = SIGNED; - else m_e = NOSIGN; + if (signst == signedst_UNSIGNED) { + m_e = UNSIGNED; + } else if (signst == signedst_SIGNED) { + m_e = SIGNED; + } else { + m_e = NOSIGN; + } } static inline AstNumeric fromBool(bool isSigned) { // Factory method - return isSigned ? AstNumeric(SIGNED) : AstNumeric(UNSIGNED); } - explicit inline AstNumeric(int _e) : m_e(static_cast(_e)) {} + return isSigned ? AstNumeric(SIGNED) : AstNumeric(UNSIGNED); + } + explicit inline AstNumeric(int _e) + : m_e(static_cast(_e)) {} operator en() const { return m_e; } - inline bool isSigned() const { return m_e==SIGNED; } - inline bool isNosign() const { return m_e==NOSIGN; } + inline bool isSigned() const { return m_e == SIGNED; } + inline bool isNosign() const { return m_e == NOSIGN; } // No isUnsigned() as it's ambiguous if NOSIGN should be included or not. }; inline bool operator==(const AstNumeric& lhs, const AstNumeric& rhs) { return lhs.m_e == rhs.m_e; } @@ -155,10 +165,13 @@ public: ENUM_SIZE }; enum en m_e; - inline AstPragmaType() : m_e(ILLEGAL) {} + inline AstPragmaType() + : m_e(ILLEGAL) {} // cppcheck-suppress noExplicitConstructor - inline AstPragmaType(en _e) : m_e(_e) {} - explicit inline AstPragmaType(int _e) : m_e(static_cast(_e)) {} + inline AstPragmaType(en _e) + : m_e(_e) {} + explicit inline AstPragmaType(int _e) + : m_e(static_cast(_e)) {} operator en() const { return m_e; } }; inline bool operator==(const AstPragmaType& lhs, const AstPragmaType& rhs) { @@ -181,15 +194,19 @@ public: TRACE_CHANGE_SUB }; enum en m_e; - inline AstCFuncType() : m_e(FT_NORMAL) {} + inline AstCFuncType() + : m_e(FT_NORMAL) {} // cppcheck-suppress noExplicitConstructor - inline AstCFuncType(en _e) : m_e(_e) {} - explicit inline AstCFuncType(int _e) : m_e(static_cast(_e)) {} + inline AstCFuncType(en _e) + : m_e(_e) {} + explicit inline AstCFuncType(int _e) + : m_e(static_cast(_e)) {} operator en() const { return m_e; } // METHODS - bool isTrace() const { return (m_e==TRACE_INIT || m_e==TRACE_INIT_SUB - || m_e==TRACE_FULL || m_e==TRACE_FULL_SUB - || m_e==TRACE_CHANGE || m_e==TRACE_CHANGE_SUB); } + bool isTrace() const { + return (m_e == TRACE_INIT || m_e == TRACE_INIT_SUB || m_e == TRACE_FULL + || m_e == TRACE_FULL_SUB || m_e == TRACE_CHANGE || m_e == TRACE_CHANGE_SUB); + } }; inline bool operator==(const AstCFuncType& lhs, const AstCFuncType& rhs) { return lhs.m_e == rhs.m_e; @@ -201,56 +218,52 @@ inline bool operator==(AstCFuncType::en lhs, const AstCFuncType& rhs) { return l class VEdgeType { public: -// REMEMBER to edit the strings below too + // REMEMBER to edit the strings below too enum en { // These must be in general -> most specific order, as we sort by it // in V3Const::visit AstSenTree ET_ILLEGAL, // Involving a variable - ET_ANYEDGE, // Default for sensitivities; rip them out - ET_BOTHEDGE, // POSEDGE | NEGEDGE + ET_ANYEDGE, // Default for sensitivities; rip them out + ET_BOTHEDGE, // POSEDGE | NEGEDGE ET_POSEDGE, ET_NEGEDGE, - ET_HIGHEDGE, // Is high now (latches) - ET_LOWEDGE, // Is low now (latches) + ET_HIGHEDGE, // Is high now (latches) + ET_LOWEDGE, // Is low now (latches) // Not involving anything - ET_COMBO, // Sensitive to all combo inputs to this block - ET_INITIAL, // User initial statements - ET_SETTLE, // Like combo but for initial wire resolutions after initial statement - ET_NEVER // Never occurs (optimized away) + ET_COMBO, // Sensitive to all combo inputs to this block + ET_INITIAL, // User initial statements + ET_SETTLE, // Like combo but for initial wire resolutions after initial statement + ET_NEVER // Never occurs (optimized away) }; enum en m_e; bool clockedStmt() const { - static const bool clocked[] = { - false, false, true, true, true, true, true, - false, false, false - }; + static const bool clocked[] + = {false, false, true, true, true, true, true, false, false, false}; return clocked[m_e]; } VEdgeType invert() const { switch (m_e) { - case ET_ANYEDGE: return ET_ANYEDGE; - case ET_BOTHEDGE: return ET_BOTHEDGE; - case ET_POSEDGE: return ET_NEGEDGE; - case ET_NEGEDGE: return ET_POSEDGE; - case ET_HIGHEDGE: return ET_LOWEDGE; - case ET_LOWEDGE: return ET_HIGHEDGE; + case ET_ANYEDGE: return ET_ANYEDGE; + case ET_BOTHEDGE: return ET_BOTHEDGE; + case ET_POSEDGE: return ET_NEGEDGE; + case ET_NEGEDGE: return ET_POSEDGE; + case ET_HIGHEDGE: return ET_LOWEDGE; + case ET_LOWEDGE: return ET_HIGHEDGE; default: UASSERT_STATIC(0, "Inverting bad edgeType()"); }; return VEdgeType::ET_ILLEGAL; } const char* ascii() const { - static const char* const names[] = { - "%E-edge", "ANY", "BOTH", "POS", "NEG", "HIGH", "LOW", - "COMBO", "INITIAL", "SETTLE", "NEVER" - }; + static const char* const names[] + = {"%E-edge", "ANY", "BOTH", "POS", "NEG", "HIGH", + "LOW", "COMBO", "INITIAL", "SETTLE", "NEVER"}; return names[m_e]; } const char* verilogKwd() const { - static const char* const names[] = { - "%E-edge", "[any]", "edge", "posedge", "negedge", "[high]", "[low]", - "*", "[initial]", "[settle]", "[never]" - }; + static const char* const names[] + = {"%E-edge", "[any]", "edge", "posedge", "negedge", "[high]", + "[low]", "*", "[initial]", "[settle]", "[never]"}; return names[m_e]; } // Return true iff this and the other have mutually exclusive transitions @@ -259,16 +272,14 @@ public: case VEdgeType::ET_POSEDGE: switch (other.m_e) { case VEdgeType::ET_NEGEDGE: // FALLTHRU - case VEdgeType::ET_LOWEDGE: - return true; + case VEdgeType::ET_LOWEDGE: return true; default: {} } break; case VEdgeType::ET_NEGEDGE: switch (other.m_e) { case VEdgeType::ET_POSEDGE: // FALLTHRU - case VEdgeType::ET_HIGHEDGE: - return true; + case VEdgeType::ET_HIGHEDGE: return true; default: {} } break; @@ -276,10 +287,13 @@ public: } return false; } - inline VEdgeType() : m_e(ET_ILLEGAL) {} + inline VEdgeType() + : m_e(ET_ILLEGAL) {} // cppcheck-suppress noExplicitConstructor - inline VEdgeType(en _e) : m_e(_e) {} - explicit inline VEdgeType(int _e) : m_e(static_cast(_e)) {} + inline VEdgeType(en _e) + : m_e(_e) {} + explicit inline VEdgeType(int _e) + : m_e(static_cast(_e)) {} operator en() const { return m_e; } }; inline bool operator==(const VEdgeType& lhs, const VEdgeType& rhs) { return lhs.m_e == rhs.m_e; } @@ -290,6 +304,7 @@ inline bool operator==(VEdgeType::en lhs, const VEdgeType& rhs) { return lhs == class AstAttrType { public: + // clang-format off enum en { ILLEGAL, // @@ -331,8 +346,10 @@ public: VAR_NO_CLOCKER, // V3LinkParse moves to AstVar::attrClocker VAR_SPLIT_VAR // V3LinkParse moves to AstVar::attrSplitVar }; + // clang-format on enum en m_e; const char* ascii() const { + // clang-format off static const char* const names[] = { "%E-AT", "DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT", @@ -347,12 +364,16 @@ public: "VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT", "VAR_CLOCKER", "VAR_NO_CLOCKER", "VAR_SPLIT_VAR" }; + // clang-format on return names[m_e]; } - inline AstAttrType() : m_e(ILLEGAL) {} + inline AstAttrType() + : m_e(ILLEGAL) {} // cppcheck-suppress noExplicitConstructor - inline AstAttrType(en _e) : m_e(_e) {} - explicit inline AstAttrType(int _e) : m_e(static_cast(_e)) {} + inline AstAttrType(en _e) + : m_e(_e) {} + explicit inline AstAttrType(int _e) + : m_e(static_cast(_e)) {} operator en() const { return m_e; } }; inline bool operator==(const AstAttrType& lhs, const AstAttrType& rhs) { @@ -367,14 +388,25 @@ class AstBasicDTypeKwd { public: enum en { UNKNOWN, - BIT, BYTE, CHANDLE, INT, INTEGER, LOGIC, LONGINT, - DOUBLE, SHORTINT, FLOAT, TIME, + BIT, + BYTE, + CHANDLE, + INT, + INTEGER, + LOGIC, + LONGINT, + DOUBLE, + SHORTINT, + FLOAT, + TIME, // Closer to a class type, but limited usage STRING, // Internal types for mid-steps - SCOPEPTR, CHARPTR, + SCOPEPTR, + CHARPTR, // Unsigned and two state; fundamental types - UINT32, UINT64, + UINT32, + UINT64, // Internal types, eliminated after parsing LOGIC_IMPLICIT, // Leave last @@ -383,97 +415,92 @@ public: enum en m_e; const char* ascii() const { static const char* const names[] = { - "%E-unk", - "bit", "byte", "chandle", "int", "integer", "logic", "longint", - "real", "shortint", "shortreal", "time", - "string", - "VerilatedScope*", "char*", - "IData", "QData", - "LOGIC_IMPLICIT", - " MAX" - }; + "%E-unk", "bit", "byte", "chandle", "int", "integer", "logic", + "longint", "real", "shortint", "shortreal", "time", "string", "VerilatedScope*", + "char*", "IData", "QData", "LOGIC_IMPLICIT", " MAX"}; return names[m_e]; } const char* dpiType() const { - static const char* const names[] = { - "%E-unk", - "svBit", "char", "void*", "int", "%E-integer", "svLogic", "long long", - "double", "short", "float", "%E-time", - "const char*", - "dpiScope", "const char*", - "IData", "QData", - "%E-logic-implicit", - " MAX" - }; + static const char* const names[] + = {"%E-unk", "svBit", "char", "void*", "int", "%E-integer", + "svLogic", "long long", "double", "short", "float", "%E-time", + "const char*", "dpiScope", "const char*", "IData", "QData", "%E-logic-implicit", + " MAX"}; return names[m_e]; } static void selfTest() { - UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).ascii(), " MAX"), "SelfTest: Enum mismatch"); - UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).dpiType(), " MAX"), "SelfTest: Enum mismatch"); + UASSERT(0 == strcmp(AstBasicDTypeKwd(_ENUM_MAX).ascii(), " MAX"), + "SelfTest: Enum mismatch"); + UASSERT(0 == strcmp(AstBasicDTypeKwd(_ENUM_MAX).dpiType(), " MAX"), + "SelfTest: Enum mismatch"); } - inline AstBasicDTypeKwd() : m_e(UNKNOWN) {} + inline AstBasicDTypeKwd() + : m_e(UNKNOWN) {} // cppcheck-suppress noExplicitConstructor - inline AstBasicDTypeKwd(en _e) : m_e(_e) {} - explicit inline AstBasicDTypeKwd(int _e) : m_e(static_cast(_e)) {} + inline AstBasicDTypeKwd(en _e) + : m_e(_e) {} + explicit inline AstBasicDTypeKwd(int _e) + : m_e(static_cast(_e)) {} operator en() const { return m_e; } int width() const { switch (m_e) { - case BIT: return 1; // scalar, can't bit extract unless ranged - case BYTE: return 8; - case CHANDLE: return 64; - case INT: return 32; - case INTEGER: return 32; - case LOGIC: return 1; // scalar, can't bit extract unless ranged - case LONGINT: return 64; - case DOUBLE: return 64; // opaque - case FLOAT: return 32; // opaque - case SHORTINT: return 16; - case TIME: return 64; - case STRING: return 64; // opaque // Just the pointer, for today - case SCOPEPTR: return 0; // opaque - case CHARPTR: return 0; // opaque - case UINT32: return 32; - case UINT64: return 64; + case BIT: return 1; // scalar, can't bit extract unless ranged + case BYTE: return 8; + case CHANDLE: return 64; + case INT: return 32; + case INTEGER: return 32; + case LOGIC: return 1; // scalar, can't bit extract unless ranged + case LONGINT: return 64; + case DOUBLE: return 64; // opaque + case FLOAT: return 32; // opaque + case SHORTINT: return 16; + case TIME: return 64; + case STRING: return 64; // opaque // Just the pointer, for today + case SCOPEPTR: return 0; // opaque + case CHARPTR: return 0; // opaque + case UINT32: return 32; + case UINT64: return 64; default: return 0; } } bool isSigned() const { - return m_e==BYTE || m_e==SHORTINT || m_e==INT || m_e==LONGINT || m_e==INTEGER - || m_e==DOUBLE || m_e==FLOAT; + return m_e == BYTE || m_e == SHORTINT || m_e == INT || m_e == LONGINT || m_e == INTEGER + || m_e == DOUBLE || m_e == FLOAT; } bool isUnsigned() const { - return m_e==CHANDLE || m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR - || m_e==UINT32 || m_e==UINT64; + return m_e == CHANDLE || m_e == STRING || m_e == SCOPEPTR || m_e == CHARPTR + || m_e == UINT32 || m_e == UINT64; } bool isFourstate() const { return m_e == INTEGER || m_e == LOGIC || m_e == LOGIC_IMPLICIT || m_e == TIME; } bool isZeroInit() const { // Otherwise initializes to X - return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT || m_e==LONGINT || m_e==SHORTINT - || m_e==STRING || m_e==DOUBLE || m_e==FLOAT); + return (m_e == BIT || m_e == BYTE || m_e == CHANDLE || m_e == INT || m_e == LONGINT + || m_e == SHORTINT || m_e == STRING || m_e == DOUBLE || m_e == FLOAT); } bool isIntNumeric() const { // Enum increment supported - return (m_e==BIT || m_e==BYTE || m_e==INT || m_e==INTEGER || m_e==LOGIC - || m_e==LONGINT || m_e==SHORTINT || m_e==UINT32 || m_e==UINT64); + return (m_e == BIT || m_e == BYTE || m_e == INT || m_e == INTEGER || m_e == LOGIC + || m_e == LONGINT || m_e == SHORTINT || m_e == UINT32 || m_e == UINT64); } bool isSloppy() const { // Don't be as anal about width warnings - return !(m_e==LOGIC || m_e==BIT); + return !(m_e == LOGIC || m_e == BIT); } bool isBitLogic() const { // Bit/logic vector types; can form a packed array - return (m_e==LOGIC || m_e==BIT); + return (m_e == LOGIC || m_e == BIT); } bool isDpiUnsignable() const { // Can add "unsigned" to DPI - return (m_e==BYTE || m_e==SHORTINT || m_e==INT || m_e==LONGINT || m_e==INTEGER); + return (m_e == BYTE || m_e == SHORTINT || m_e == INT || m_e == LONGINT || m_e == INTEGER); } bool isDpiCLayout() const { // Uses standard C layout, for DPI runtime access - return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT - || m_e==LONGINT || m_e==DOUBLE || m_e==SHORTINT || m_e==UINT32 || m_e==UINT64); + return (m_e == BIT || m_e == BYTE || m_e == CHANDLE || m_e == INT || m_e == LONGINT + || m_e == DOUBLE || m_e == SHORTINT || m_e == UINT32 || m_e == UINT64); } bool isOpaque() const { // IE not a simple number we can bit optimize - return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR || m_e==DOUBLE || m_e==FLOAT); + return (m_e == STRING || m_e == SCOPEPTR || m_e == CHARPTR || m_e == DOUBLE + || m_e == FLOAT); } - bool isDouble() const { return m_e==DOUBLE; } - bool isString() const { return m_e==STRING; } + bool isDouble() const { return m_e == DOUBLE; } + bool isString() const { return m_e == STRING; } }; inline bool operator==(const AstBasicDTypeKwd& lhs, const AstBasicDTypeKwd& rhs) { return lhs.m_e == rhs.m_e; @@ -489,41 +516,37 @@ inline bool operator==(AstBasicDTypeKwd::en lhs, const AstBasicDTypeKwd& rhs) { class VDirection { public: - enum en { - NONE, - INPUT, - OUTPUT, - INOUT, - REF, - CONSTREF - }; + enum en { NONE, INPUT, OUTPUT, INOUT, REF, CONSTREF }; enum en m_e; - inline VDirection() : m_e(NONE) {} + inline VDirection() + : m_e(NONE) {} // cppcheck-suppress noExplicitConstructor - inline VDirection(en _e) : m_e(_e) {} - explicit inline VDirection(int _e) : m_e(static_cast(_e)) {} + inline VDirection(en _e) + : m_e(_e) {} + explicit inline VDirection(int _e) + : m_e(static_cast(_e)) {} operator en() const { return m_e; } const char* ascii() const { - static const char* const names[] = { - "NONE", "INPUT", "OUTPUT", "INOUT", "REF", "CONSTREF"}; - return names[m_e]; } + static const char* const names[] = {"NONE", "INPUT", "OUTPUT", "INOUT", "REF", "CONSTREF"}; + return names[m_e]; + } string verilogKwd() const { - static const char* const names[] = { - "", "input", "output", "inout", "ref", "const ref"}; - return names[m_e]; } + static const char* const names[] = {"", "input", "output", "inout", "ref", "const ref"}; + return names[m_e]; + } string xmlKwd() const { // For historical reasons no "put" suffix - static const char* const names[] = { - "", "in", "out", "inout", "ref", "const ref"}; - return names[m_e]; } + static const char* const names[] = {"", "in", "out", "inout", "ref", "const ref"}; + return names[m_e]; + } string prettyName() const { return verilogKwd(); } bool isAny() const { return m_e != NONE; } // Looks like inout - "ish" because not identical to being an INOUT bool isInoutish() const { return m_e == INOUT; } - bool isNonOutput() const { return m_e == INPUT || m_e == INOUT - || m_e == REF || m_e == CONSTREF; } + bool isNonOutput() const { + return m_e == INPUT || m_e == INOUT || m_e == REF || m_e == CONSTREF; + } bool isReadOnly() const { return m_e == INPUT || m_e == CONSTREF; } - bool isWritable() const { return m_e == OUTPUT || m_e == INOUT - || m_e == REF; } + bool isWritable() const { return m_e == OUTPUT || m_e == INOUT || m_e == REF; } bool isRefOrConstRef() const { return m_e == REF || m_e == CONSTREF; } }; inline bool operator==(const VDirection& lhs, const VDirection& rhs) { return lhs.m_e == rhs.m_e; } @@ -538,22 +561,20 @@ inline std::ostream& operator<<(std::ostream& os, const VDirection& rhs) { /// Boolean or unknown class VBoolOrUnknown { public: - enum en { - BU_FALSE=0, - BU_TRUE=1, - BU_UNKNOWN=2, - _ENUM_END - }; + enum en { BU_FALSE = 0, BU_TRUE = 1, BU_UNKNOWN = 2, _ENUM_END }; enum en m_e; // CONSTRUCTOR - note defaults to *UNKNOWN* - inline VBoolOrUnknown() : m_e(BU_UNKNOWN) {} + inline VBoolOrUnknown() + : m_e(BU_UNKNOWN) {} // cppcheck-suppress noExplicitConstructor - inline VBoolOrUnknown(en _e) : m_e(_e) {} - explicit inline VBoolOrUnknown(int _e) : m_e(static_cast(_e)) {} + inline VBoolOrUnknown(en _e) + : m_e(_e) {} + explicit inline VBoolOrUnknown(int _e) + : m_e(static_cast(_e)) {} const char* ascii() const { - static const char* const names[] = { - "FALSE", "TRUE", "UNK"}; - return names[m_e]; } + static const char* const names[] = {"FALSE", "TRUE", "UNK"}; + return names[m_e]; + } bool trueKnown() const { return m_e == BU_TRUE; } bool trueUnknown() const { return m_e == BU_TRUE || m_e == BU_UNKNOWN; } bool falseKnown() const { return m_e == BU_FALSE; } @@ -592,7 +613,7 @@ public: TRIWIRE, TRI0, TRI1, - PORT, // Temp type used in parser only + PORT, // Temp type used in parser only BLOCKTEMP, MODULETEMP, STMTTEMP, @@ -601,42 +622,38 @@ public: MEMBER }; enum en m_e; - inline AstVarType() : m_e(UNKNOWN) {} + inline AstVarType() + : m_e(UNKNOWN) {} // cppcheck-suppress noExplicitConstructor - inline AstVarType(en _e) : m_e(_e) {} - explicit inline AstVarType(int _e) : m_e(static_cast(_e)) {} + inline AstVarType(en _e) + : m_e(_e) {} + explicit inline AstVarType(int _e) + : m_e(static_cast(_e)) {} operator en() const { return m_e; } const char* ascii() const { static const char* const names[] = { - "?", "GPARAM", "LPARAM", "GENVAR", "VAR", - "SUPPLY0", "SUPPLY1", "WIRE", "WREAL", "IMPLICITWIRE", - "TRIWIRE", "TRI0", "TRI1", - "PORT", - "BLOCKTEMP", "MODULETEMP", "STMTTEMP", "XTEMP", - "IFACEREF", "MEMBER"}; - return names[m_e]; } + "?", "GPARAM", "LPARAM", "GENVAR", "VAR", "SUPPLY0", "SUPPLY1", + "WIRE", "WREAL", "IMPLICITWIRE", "TRIWIRE", "TRI0", "TRI1", "PORT", + "BLOCKTEMP", "MODULETEMP", "STMTTEMP", "XTEMP", "IFACEREF", "MEMBER"}; + return names[m_e]; + } bool isSignal() const { - return (m_e==WIRE || m_e==WREAL || m_e==IMPLICITWIRE - || m_e==TRIWIRE - || m_e==TRI0 || m_e==TRI1 || m_e==PORT - || m_e==SUPPLY0 || m_e==SUPPLY1 - || m_e==VAR); + return (m_e == WIRE || m_e == WREAL || m_e == IMPLICITWIRE || m_e == TRIWIRE || m_e == TRI0 + || m_e == TRI1 || m_e == PORT || m_e == SUPPLY0 || m_e == SUPPLY1 || m_e == VAR); } bool isContAssignable() const { // In Verilog, always ok in SystemVerilog - return (m_e==SUPPLY0 || m_e==SUPPLY1 - || m_e==WIRE || m_e==WREAL || m_e==IMPLICITWIRE - || m_e==TRIWIRE || m_e==TRI0 || m_e==TRI1 || m_e==PORT - || m_e==BLOCKTEMP || m_e==MODULETEMP || m_e==STMTTEMP - || m_e==XTEMP || m_e==IFACEREF); + return (m_e == SUPPLY0 || m_e == SUPPLY1 || m_e == WIRE || m_e == WREAL + || m_e == IMPLICITWIRE || m_e == TRIWIRE || m_e == TRI0 || m_e == TRI1 + || m_e == PORT || m_e == BLOCKTEMP || m_e == MODULETEMP || m_e == STMTTEMP + || m_e == XTEMP || m_e == IFACEREF); } bool isProcAssignable() const { - return (m_e==GPARAM || m_e==LPARAM || m_e==GENVAR - || m_e==VAR - || m_e==BLOCKTEMP || m_e==MODULETEMP || m_e==STMTTEMP - || m_e==XTEMP || m_e==IFACEREF || m_e==MEMBER); + return (m_e == GPARAM || m_e == LPARAM || m_e == GENVAR || m_e == VAR || m_e == BLOCKTEMP + || m_e == MODULETEMP || m_e == STMTTEMP || m_e == XTEMP || m_e == IFACEREF + || m_e == MEMBER); } bool isTemp() const { - return (m_e==BLOCKTEMP || m_e==MODULETEMP || m_e==STMTTEMP || m_e==XTEMP); + return (m_e == BLOCKTEMP || m_e == MODULETEMP || m_e == STMTTEMP || m_e == XTEMP); } }; inline bool operator==(const AstVarType& lhs, const AstVarType& rhs) { return lhs.m_e == rhs.m_e; } @@ -650,31 +667,33 @@ inline std::ostream& operator<<(std::ostream& os, const AstVarType& rhs) { class VBranchPred { public: - enum en { - BP_UNKNOWN=0, - BP_LIKELY, - BP_UNLIKELY, - _ENUM_END - }; + enum en { BP_UNKNOWN = 0, BP_LIKELY, BP_UNLIKELY, _ENUM_END }; enum en m_e; // CONSTRUCTOR - note defaults to *UNKNOWN* - inline VBranchPred() : m_e(BP_UNKNOWN) {} + inline VBranchPred() + : m_e(BP_UNKNOWN) {} // cppcheck-suppress noExplicitConstructor - inline VBranchPred(en _e) : m_e(_e) {} - explicit inline VBranchPred(int _e) : m_e(static_cast(_e)) {} + inline VBranchPred(en _e) + : m_e(_e) {} + explicit inline VBranchPred(int _e) + : m_e(static_cast(_e)) {} operator en() const { return m_e; } bool unknown() const { return m_e == BP_UNKNOWN; } bool likely() const { return m_e == BP_LIKELY; } bool unlikely() const { return m_e == BP_UNLIKELY; } VBranchPred invert() const { - if (m_e==BP_UNLIKELY) return BP_LIKELY; - else if (m_e==BP_LIKELY) return BP_UNLIKELY; - else return m_e; + if (m_e == BP_UNLIKELY) { + return BP_LIKELY; + } else if (m_e == BP_LIKELY) { + return BP_UNLIKELY; + } else { + return m_e; + } } const char* ascii() const { - static const char* const names[] = { - "", "VL_LIKELY", "VL_UNLIKELY"}; - return names[m_e]; } + static const char* const names[] = {"", "VL_LIKELY", "VL_UNLIKELY"}; + return names[m_e]; + } }; inline bool operator==(const VBranchPred& lhs, const VBranchPred& rhs) { return lhs.m_e == rhs.m_e; @@ -689,29 +708,31 @@ inline std::ostream& operator<<(std::ostream& os, const VBranchPred& rhs) { class VVarAttrClocker { public: - enum en { - CLOCKER_UNKNOWN=0, - CLOCKER_YES, - CLOCKER_NO, - _ENUM_END - }; + enum en { CLOCKER_UNKNOWN = 0, CLOCKER_YES, CLOCKER_NO, _ENUM_END }; enum en m_e; // CONSTRUCTOR - note defaults to *UNKNOWN* - inline VVarAttrClocker() : m_e(CLOCKER_UNKNOWN) {} + inline VVarAttrClocker() + : m_e(CLOCKER_UNKNOWN) {} // cppcheck-suppress noExplicitConstructor - inline VVarAttrClocker(en _e) : m_e(_e) {} - explicit inline VVarAttrClocker(int _e) : m_e(static_cast(_e)) {} + inline VVarAttrClocker(en _e) + : m_e(_e) {} + explicit inline VVarAttrClocker(int _e) + : m_e(static_cast(_e)) {} operator en() const { return m_e; } - bool unknown() const { return m_e==CLOCKER_UNKNOWN; } + bool unknown() const { return m_e == CLOCKER_UNKNOWN; } VVarAttrClocker invert() const { - if (m_e==CLOCKER_YES) return CLOCKER_NO; - else if (m_e==CLOCKER_NO) return CLOCKER_YES; - else return m_e; + if (m_e == CLOCKER_YES) { + return CLOCKER_NO; + } else if (m_e == CLOCKER_NO) { + return CLOCKER_YES; + } else { + return m_e; + } } const char* ascii() const { - static const char* const names[] = { - "", "clker", "non_clker"}; - return names[m_e]; } + static const char* const names[] = {"", "clker", "non_clker"}; + return names[m_e]; + } }; inline bool operator==(const VVarAttrClocker& lhs, const VVarAttrClocker& rhs) { return lhs.m_e == rhs.m_e; @@ -730,22 +751,20 @@ inline std::ostream& operator<<(std::ostream& os, const VVarAttrClocker& rhs) { class VAlwaysKwd { public: - enum en { - ALWAYS, - ALWAYS_FF, - ALWAYS_LATCH, - ALWAYS_COMB - }; + enum en { ALWAYS, ALWAYS_FF, ALWAYS_LATCH, ALWAYS_COMB }; enum en m_e; - inline VAlwaysKwd() : m_e(ALWAYS) {} + inline VAlwaysKwd() + : m_e(ALWAYS) {} // cppcheck-suppress noExplicitConstructor - inline VAlwaysKwd(en _e) : m_e(_e) {} - explicit inline VAlwaysKwd(int _e) : m_e(static_cast(_e)) {} + inline VAlwaysKwd(en _e) + : m_e(_e) {} + explicit inline VAlwaysKwd(int _e) + : m_e(static_cast(_e)) {} operator en() const { return m_e; } const char* ascii() const { - static const char* const names[] = { - "always", "always_ff", "always_latch", "always_comb"}; - return names[m_e]; } + static const char* const names[] = {"always", "always_ff", "always_latch", "always_comb"}; + return names[m_e]; + } }; inline bool operator==(const VAlwaysKwd& lhs, const VAlwaysKwd& rhs) { return lhs.m_e == rhs.m_e; } inline bool operator==(const VAlwaysKwd& lhs, VAlwaysKwd::en rhs) { return lhs.m_e == rhs; } @@ -755,17 +774,15 @@ inline bool operator==(VAlwaysKwd::en lhs, const VAlwaysKwd& rhs) { return lhs = class VCaseType { public: - enum en { - CT_CASE, - CT_CASEX, - CT_CASEZ, - CT_CASEINSIDE - }; + enum en { CT_CASE, CT_CASEX, CT_CASEZ, CT_CASEINSIDE }; enum en m_e; - inline VCaseType() : m_e(CT_CASE) {} + inline VCaseType() + : m_e(CT_CASE) {} // cppcheck-suppress noExplicitConstructor - inline VCaseType(en _e) : m_e(_e) {} - explicit inline VCaseType(int _e) : m_e(static_cast(_e)) {} + inline VCaseType(en _e) + : m_e(_e) {} + explicit inline VCaseType(int _e) + : m_e(static_cast(_e)) {} operator en() const { return m_e; } }; inline bool operator==(const VCaseType& lhs, const VCaseType& rhs) { return lhs.m_e == rhs.m_e; } @@ -776,26 +793,23 @@ inline bool operator==(VCaseType::en lhs, const VCaseType& rhs) { return lhs == class AstDisplayType { public: - enum en { - DT_DISPLAY, - DT_WRITE, - DT_INFO, - DT_ERROR, - DT_WARNING, - DT_FATAL - }; + enum en { DT_DISPLAY, DT_WRITE, DT_INFO, DT_ERROR, DT_WARNING, DT_FATAL }; enum en m_e; - inline AstDisplayType() : m_e(DT_DISPLAY) {} + inline AstDisplayType() + : m_e(DT_DISPLAY) {} // cppcheck-suppress noExplicitConstructor - inline AstDisplayType(en _e) : m_e(_e) {} - explicit inline AstDisplayType(int _e) : m_e(static_cast(_e)) {} + inline AstDisplayType(en _e) + : m_e(_e) {} + explicit inline AstDisplayType(int _e) + : m_e(static_cast(_e)) {} operator en() const { return m_e; } - bool addNewline() const { return m_e!=DT_WRITE; } - bool needScopeTracking() const { return m_e!=DT_DISPLAY && m_e!=DT_WRITE; } + bool addNewline() const { return m_e != DT_WRITE; } + bool needScopeTracking() const { return m_e != DT_DISPLAY && m_e != DT_WRITE; } const char* ascii() const { - static const char* const names[] = { - "display", "write", "info", "error", "warning", "fatal"}; - return names[m_e]; } + static const char* const names[] + = {"display", "write", "info", "error", "warning", "fatal"}; + return names[m_e]; + } }; inline bool operator==(const AstDisplayType& lhs, const AstDisplayType& rhs) { return lhs.m_e == rhs.m_e; @@ -822,8 +836,8 @@ public: : m_e(static_cast(_e)) {} operator en() const { return m_e; } const char* ascii() const { - static const char* const names[] = {"$dumpfile", "$dumpvars", "$dumpall", "$dumpflush", - "$dumplimit", "$dumpoff", "$dumpon"}; + static const char* const names[] = {"$dumpfile", "$dumpvars", "$dumpall", "$dumpflush", + "$dumplimit", "$dumpoff", "$dumpon"}; return names[m_e]; } }; @@ -838,19 +852,22 @@ inline bool operator==(VDumpCtlType::en lhs, const VDumpCtlType& rhs) { return l class VParseRefExp { public: enum en { - PX_NONE, // Used in V3LinkParse only - PX_TEXT // Unknown ID component + PX_NONE, // Used in V3LinkParse only + PX_TEXT // Unknown ID component }; enum en m_e; - inline VParseRefExp() : m_e(PX_NONE) {} + inline VParseRefExp() + : m_e(PX_NONE) {} // cppcheck-suppress noExplicitConstructor - inline VParseRefExp(en _e) : m_e(_e) {} - explicit inline VParseRefExp(int _e) : m_e(static_cast(_e)) {} + inline VParseRefExp(en _e) + : m_e(_e) {} + explicit inline VParseRefExp(int _e) + : m_e(static_cast(_e)) {} operator en() const { return m_e; } const char* ascii() const { - static const char* const names[] = { - "", "TEXT", "PREDOT"}; - return names[m_e]; } + static const char* const names[] = {"", "TEXT", "PREDOT"}; + return names[m_e]; + } }; inline bool operator==(const VParseRefExp& lhs, const VParseRefExp& rhs) { return lhs.m_e == rhs.m_e; @@ -872,52 +889,75 @@ public: union { int mu_flags; struct { - bool m_ranged:1; // Has a range - bool m_littleEndian:1; // Bit vector is little endian + bool m_ranged : 1; // Has a range + bool m_littleEndian : 1; // Bit vector is little endian }; }; inline bool operator==(const VNumRange& rhs) const { - return m_hi == rhs.m_hi - && m_lo == rhs.m_lo - && mu_flags == rhs.mu_flags; } - inline bool operator< (const VNumRange& rhs) const { - if ( (m_hi < rhs.m_hi)) return true; + return m_hi == rhs.m_hi && m_lo == rhs.m_lo && mu_flags == rhs.mu_flags; + } + inline bool operator<(const VNumRange& rhs) const { + if ((m_hi < rhs.m_hi)) return true; if (!(m_hi == rhs.m_hi)) return false; // lhs > rhs - if ( (m_lo < rhs.m_lo)) return true; + if ((m_lo < rhs.m_lo)) return true; if (!(m_lo == rhs.m_lo)) return false; // lhs > rhs - if ( (mu_flags < rhs.mu_flags)) return true; + if ((mu_flags < rhs.mu_flags)) return true; if (!(mu_flags == rhs.mu_flags)) return false; // lhs > rhs return false; } // class LeftRight {}; - VNumRange() : m_hi(0), m_lo(0), mu_flags(0) {} + VNumRange() + : m_hi(0) + , m_lo(0) + , mu_flags(0) {} VNumRange(int hi, int lo, bool littleEndian) - : m_hi(0), m_lo(0), mu_flags(0) - { init(hi, lo, littleEndian); } + : m_hi(0) + , m_lo(0) + , mu_flags(0) { + init(hi, lo, littleEndian); + } VNumRange(LeftRight, int left, int right) - : m_hi(0), m_lo(0), mu_flags(0) - { init((right>left)?right:left, (right>left)?left:right, (right>left)); } + : m_hi(0) + , m_lo(0) + , mu_flags(0) { + init((right > left) ? right : left, (right > left) ? left : right, (right > left)); + } ~VNumRange() {} // MEMBERS void init(int hi, int lo, bool littleEndian) { - m_hi = hi; m_lo = lo; mu_flags = 0; m_ranged = true; m_littleEndian = littleEndian; + m_hi = hi; + m_lo = lo; + mu_flags = 0; + m_ranged = true; + m_littleEndian = littleEndian; } int hi() const { return m_hi; } int lo() const { return m_lo; } - int left() const { return littleEndian()?lo():hi(); } // How to show a declaration - int right() const { return littleEndian()?hi():lo(); } - int leftToRightInc() const { return littleEndian()?1:-1; } - int elements() const { return hi()-lo()+1; } + int left() const { return littleEndian() ? lo() : hi(); } // How to show a declaration + int right() const { return littleEndian() ? hi() : lo(); } + int leftToRightInc() const { return littleEndian() ? 1 : -1; } + int elements() const { return hi() - lo() + 1; } bool ranged() const { return m_ranged; } bool littleEndian() const { return m_littleEndian; } - int hiMaxSelect() const { return (lo()<0 ? hi()-lo() : hi()); } // Maximum value a [] select may index + int hiMaxSelect() const { + return (lo() < 0 ? hi() - lo() : hi()); + } // Maximum value a [] select may index bool representableByWidth() const { // Could be represented by just width=1, or [width-1:0] - return (!m_ranged || (m_lo==0 && m_hi>=1 && !m_littleEndian)); } + return (!m_ranged || (m_lo == 0 && m_hi >= 1 && !m_littleEndian)); + } void dump(std::ostream& str) const { - if (ranged()) str<<"["<(_e)) {} + inline VUseType(en _e) + : m_e(_e) {} + explicit inline VUseType(int _e) + : m_e(static_cast(_e)) {} bool isInclude() const { return m_e == IMP_INCLUDE || m_e == INT_INCLUDE; } bool isFwdClass() const { return m_e == IMP_FWD_CLASS || m_e == INT_FWD_CLASS; } operator en() const { return m_e; } @@ -953,33 +996,35 @@ inline std::ostream& operator<<(std::ostream& os, const VUseType& rhs) { class VBasicTypeKey { public: - int m_width; // From AstNodeDType: Bit width of operation - int m_widthMin; // From AstNodeDType: If unsized, bitwidth of minimum implementation - AstNumeric m_numeric; // From AstNodeDType: Node is signed + int m_width; // From AstNodeDType: Bit width of operation + int m_widthMin; // From AstNodeDType: If unsized, bitwidth of minimum implementation + AstNumeric m_numeric; // From AstNodeDType: Node is signed AstBasicDTypeKwd m_keyword; // From AstBasicDType: What keyword created basic type - VNumRange m_nrange; // From AstBasicDType: Numeric msb/lsb (if non-opaque keyword) + VNumRange m_nrange; // From AstBasicDType: Numeric msb/lsb (if non-opaque keyword) inline bool operator==(const VBasicTypeKey& rhs) const { - return m_width == rhs.m_width - && m_widthMin == rhs.m_widthMin - && m_numeric == rhs.m_numeric - && m_keyword == rhs.m_keyword - && m_nrange == rhs.m_nrange; } - inline bool operator< (const VBasicTypeKey& rhs) const { - if ( (m_width < rhs.m_width)) return true; + return m_width == rhs.m_width && m_widthMin == rhs.m_widthMin && m_numeric == rhs.m_numeric + && m_keyword == rhs.m_keyword && m_nrange == rhs.m_nrange; + } + inline bool operator<(const VBasicTypeKey& rhs) const { + if ((m_width < rhs.m_width)) return true; if (!(m_width == rhs.m_width)) return false; // lhs > rhs - if ( (m_widthMin < rhs.m_widthMin)) return true; + if ((m_widthMin < rhs.m_widthMin)) return true; if (!(m_widthMin == rhs.m_widthMin)) return false; // lhs > rhs - if ( (m_numeric < rhs.m_numeric)) return true; + if ((m_numeric < rhs.m_numeric)) return true; if (!(m_numeric == rhs.m_numeric)) return false; // lhs > rhs - if ( (m_keyword < rhs.m_keyword)) return true; + if ((m_keyword < rhs.m_keyword)) return true; if (!(m_keyword == rhs.m_keyword)) return false; // lhs > rhs - if ( (m_nrange < rhs.m_nrange)) return true; + if ((m_nrange < rhs.m_nrange)) return true; if (!(m_nrange == rhs.m_nrange)) return false; // lhs > rhs - return false; } + return false; + } VBasicTypeKey(int width, int widthMin, AstNumeric numeric, AstBasicDTypeKwd kwd, const VNumRange& nrange) - : m_width(width), m_widthMin(widthMin), m_numeric(numeric), - m_keyword(kwd), m_nrange(nrange) {} + : m_width(width) + , m_widthMin(widthMin) + , m_numeric(numeric) + , m_keyword(kwd) + , m_nrange(nrange) {} ~VBasicTypeKey() {} }; @@ -999,11 +1044,15 @@ class VNUser { void* up; int ui; } m_u; + public: VNUser() {} // non-explicit: // cppcheck-suppress noExplicitConstructor - VNUser(int i) { m_u.up = 0; m_u.ui = i; } + VNUser(int i) { + m_u.up = 0; + m_u.ui = i; + } explicit VNUser(void* p) { m_u.up = p; } ~VNUser() {} // Casters @@ -1014,9 +1063,7 @@ public: OrderBlockNU* toOrderBlock() { return ((OrderBlockNU*)m_u.up); } OrderVarNU* toOrderVar() { return ((OrderVarNU*)m_u.up); } V3GraphVertex* toGraphVertex() { return ((V3GraphVertex*)m_u.up); } - inline int toInt() { - return m_u.ui; - } + inline int toInt() { return m_u.ui; } static inline VNUser fromZero() { return VNUser(0); } static inline VNUser fromInt(int i) { return VNUser(i); } }; @@ -1036,30 +1083,33 @@ class AstUserInUseBase { protected: static void allocate(int id, uint32_t& cntGblRef, bool& userBusyRef) { // Perhaps there's still a AstUserInUse in scope for this? - UASSERT_STATIC(!userBusyRef, "Conflicting user use; AstUser"+cvtToStr(id)+"InUse request when under another AstUserInUse"); + UASSERT_STATIC(!userBusyRef, "Conflicting user use; AstUser" + cvtToStr(id) + + "InUse request when under another AstUserInUse"); userBusyRef = true; clearcnt(id, cntGblRef, userBusyRef); } static void free(int id, uint32_t& cntGblRef, bool& userBusyRef) { - UASSERT_STATIC(userBusyRef, "Free of User"+cvtToStr(id)+"() not under AstUserInUse"); + UASSERT_STATIC(userBusyRef, "Free of User" + cvtToStr(id) + "() not under AstUserInUse"); clearcnt(id, cntGblRef, userBusyRef); // Includes a checkUse for us userBusyRef = false; } static void clearcnt(int id, uint32_t& cntGblRef, const bool& userBusyRef) { - UASSERT_STATIC(userBusyRef, "Clear of User"+cvtToStr(id)+"() not under AstUserInUse"); + UASSERT_STATIC(userBusyRef, "Clear of User" + cvtToStr(id) + "() not under AstUserInUse"); // If this really fires and is real (after 2^32 edits???) // we could just walk the tree and clear manually ++cntGblRef; UASSERT_STATIC(cntGblRef, "User*() overflowed!"); } static void checkcnt(int id, uint32_t&, const bool& userBusyRef) { - UASSERT_STATIC(userBusyRef, "Check of User"+cvtToStr(id)+"() failed, not under AstUserInUse"); + UASSERT_STATIC(userBusyRef, + "Check of User" + cvtToStr(id) + "() failed, not under AstUserInUse"); } }; // For each user() declare the in use structure // We let AstNode peek into here, because when under low optimization even // an accessor would be way too slow. +// clang-format off class AstUser1InUse : AstUserInUseBase { protected: friend class AstNode; @@ -1115,6 +1165,7 @@ public: static void clear() { clearcnt(5, s_userCntGbl/*ref*/, s_userBusy/*ref*/); } static void check() { checkcnt(5, s_userCntGbl/*ref*/, s_userBusy/*ref*/); } }; +// clang-format on //###################################################################### // AstNVisitor -- Allows new functions to be called on each node @@ -1126,21 +1177,19 @@ private: std::vector m_deleteps; // Nodes to delete when doDeletes() called protected: friend class AstNode; + public: // METHODS /// At the end of the visitor (or doDeletes()), delete this pushed node /// along with all children and next(s). This is often better to use /// than an immediate deleteTree, as any pointers into this node will /// persist for the lifetime of the visitor - void pushDeletep(AstNode* nodep) { - m_deleteps.push_back(nodep); - } + void pushDeletep(AstNode* nodep) { m_deleteps.push_back(nodep); } /// Call deleteTree on all previously pushDeletep()'ed nodes void doDeletes(); + public: - virtual ~AstNVisitor() { - doDeletes(); - } + virtual ~AstNVisitor() { doDeletes(); } /// Call visit()s on nodep void iterate(AstNode* nodep); /// Call visit()s on nodep's children @@ -1169,21 +1218,27 @@ public: class AstNRelinker { protected: friend class AstNode; - enum RelinkWhatEn { - RELINK_BAD, RELINK_NEXT, RELINK_OP1, RELINK_OP2, RELINK_OP3, RELINK_OP4 - }; + enum RelinkWhatEn { RELINK_BAD, RELINK_NEXT, RELINK_OP1, RELINK_OP2, RELINK_OP3, RELINK_OP4 }; AstNode* m_oldp; // The old node that was linked to this point in the tree AstNode* m_backp; RelinkWhatEn m_chg; AstNode** m_iterpp; + public: - AstNRelinker() { m_oldp = NULL; m_backp = NULL; m_chg = RELINK_BAD; m_iterpp = NULL; } + AstNRelinker() { + m_oldp = NULL; + m_backp = NULL; + m_chg = RELINK_BAD; + m_iterpp = NULL; + } void relink(AstNode* newp); AstNode* oldp() const { return m_oldp; } - void dump(std::ostream& str=std::cout) const; + void dump(std::ostream& str = std::cout) const; }; inline std::ostream& operator<<(std::ostream& os, const AstNRelinker& rhs) { - rhs.dump(os); return os; } + rhs.dump(os); + return os; +} //###################################################################### // V3Hash -- Node hashing for V3Combine @@ -1192,32 +1247,34 @@ class V3Hash { // A hash of a tree of nodes, consisting of 8 bits with the number of nodes in the hash // and 24 bit value hash of relevant information about the node. // A value of 0 is illegal - uint32_t m_both; - static const uint32_t M24 = ((1<<24)-1); + uint32_t m_both; + static const uint32_t M24 = ((1 << 24) - 1); void setBoth(uint32_t depth, uint32_t hshval) { - if (depth==0) depth = 1; - if (depth>255) depth = 255; - m_both = (depth<<24) | (hshval & M24); + if (depth == 0) depth = 1; + if (depth > 255) depth = 255; + m_both = (depth << 24) | (hshval & M24); } + public: // METHODS - bool isIllegal() const { return m_both==0; } + bool isIllegal() const { return m_both == 0; } uint32_t fullValue() const { return m_both; } uint32_t depth() const { return (m_both >> 24) & 255; } uint32_t hshval() const { return m_both & M24; } // OPERATORS - inline bool operator==(const V3Hash& rh) const { return m_both==rh.m_both; } - inline bool operator!=(const V3Hash& rh) const { return m_both!=rh.m_both; } - inline bool operator<(const V3Hash& rh) const { return m_bothm_nextp)); VL_PREFETCH_RD(&((nodep)->m_iterpp)); }} + { \ + if (nodep) { \ + VL_PREFETCH_RD(&((nodep)->m_nextp)); \ + VL_PREFETCH_RD(&((nodep)->m_iterpp)); \ + } \ + } class AstNode { // v ASTNODE_PREFETCH depends on below ordering of members - AstNode* m_nextp; // Next peer in the parent's list - AstNode* m_backp; // Node that points to this one (via next/op1/op2/...) - AstNode* m_op1p; // Generic pointer 1 - AstNode* m_op2p; // Generic pointer 2 - AstNode* m_op3p; // Generic pointer 3 - AstNode* m_op4p; // Generic pointer 4 - AstNode** m_iterpp; // Pointer to node iterating on, change it if we replace this node. + AstNode* m_nextp; // Next peer in the parent's list + AstNode* m_backp; // Node that points to this one (via next/op1/op2/...) + AstNode* m_op1p; // Generic pointer 1 + AstNode* m_op2p; // Generic pointer 2 + AstNode* m_op3p; // Generic pointer 3 + AstNode* m_op4p; // Generic pointer 4 + AstNode** m_iterpp; // Pointer to node iterating on, change it if we replace this node. // ^ ASTNODE_PREFETCH depends on above ordering of members - AstNode* m_headtailp; // When at begin/end of list, the opposite end of the list + AstNode* m_headtailp; // When at begin/end of list, the opposite end of the list - const AstType m_type; // Node sub-type identifier + const AstType m_type; // Node sub-type identifier - FileLine* m_fileline; // Where it was declared - vluint64_t m_editCount; // When it was last edited + FileLine* m_fileline; // Where it was declared + vluint64_t m_editCount; // When it was last edited static vluint64_t s_editCntGbl; // Global edit counter - static vluint64_t s_editCntLast; // Global edit counter, last value for printing * near node #s + // Global edit counter, last value for printing * near node #s + static vluint64_t s_editCntLast; - AstNodeDType* m_dtypep; // Data type of output or assignment (etc) + AstNodeDType* m_dtypep; // Data type of output or assignment (etc) - AstNode* m_clonep; // Pointer to clone of/ source of this module (for *LAST* cloneTree() ONLY) - int m_cloneCnt; // Mark of when userp was set - static int s_cloneCntGbl; // Count of which userp is set + AstNode* m_clonep; // Pointer to clone of/ source of this module (for *LAST* cloneTree() ONLY) + int m_cloneCnt; // Mark of when userp was set + static int s_cloneCntGbl; // Count of which userp is set // Attributes - bool m_didWidth:1; // Did V3Width computation - bool m_doingWidth:1; // Inside V3Width - bool m_protect:1; // Protect name if protection is on + bool m_didWidth : 1; // Did V3Width computation + bool m_doingWidth : 1; // Inside V3Width + bool m_protect : 1; // Protect name if protection is on // // Space for more bools here // This member ordering both allows 64 bit alignment and puts associated data together - VNUser m_user1u; // Contains any information the user iteration routine wants - uint32_t m_user1Cnt; // Mark of when userp was set - uint32_t m_user2Cnt; // Mark of when userp was set - VNUser m_user2u; // Contains any information the user iteration routine wants - VNUser m_user3u; // Contains any information the user iteration routine wants - uint32_t m_user3Cnt; // Mark of when userp was set - uint32_t m_user4Cnt; // Mark of when userp was set - VNUser m_user4u; // Contains any information the user iteration routine wants - VNUser m_user5u; // Contains any information the user iteration routine wants - uint32_t m_user5Cnt; // Mark of when userp was set + VNUser m_user1u; // Contains any information the user iteration routine wants + uint32_t m_user1Cnt; // Mark of when userp was set + uint32_t m_user2Cnt; // Mark of when userp was set + VNUser m_user2u; // Contains any information the user iteration routine wants + VNUser m_user3u; // Contains any information the user iteration routine wants + uint32_t m_user3Cnt; // Mark of when userp was set + uint32_t m_user4Cnt; // Mark of when userp was set + VNUser m_user4u; // Contains any information the user iteration routine wants + VNUser m_user5u; // Contains any information the user iteration routine wants + uint32_t m_user5Cnt; // Mark of when userp was set // METHODS - void op1p(AstNode* nodep) { m_op1p = nodep; if (nodep) nodep->m_backp = this; } - void op2p(AstNode* nodep) { m_op2p = nodep; if (nodep) nodep->m_backp = this; } - void op3p(AstNode* nodep) { m_op3p = nodep; if (nodep) nodep->m_backp = this; } - void op4p(AstNode* nodep) { m_op4p = nodep; if (nodep) nodep->m_backp = this; } + void op1p(AstNode* nodep) { + m_op1p = nodep; + if (nodep) nodep->m_backp = this; + } + void op2p(AstNode* nodep) { + m_op2p = nodep; + if (nodep) nodep->m_backp = this; + } + void op3p(AstNode* nodep) { + m_op3p = nodep; + if (nodep) nodep->m_backp = this; + } + void op4p(AstNode* nodep) { + m_op4p = nodep; + if (nodep) nodep->m_backp = this; + } - void init(); // initialize value of AstNode + void init(); // initialize value of AstNode private: - AstNode* cloneTreeIter(); - AstNode* cloneTreeIterList(); - void checkTreeIter(AstNode* backp); - void checkTreeIterList(AstNode* backp); - bool gateTreeIter() const; - static bool sameTreeIter(const AstNode* node1p, const AstNode* node2p, - bool ignNext, bool gateOnly); - void deleteTreeIter(); - void deleteNode(); - string locationStr() const; + AstNode* cloneTreeIter(); + AstNode* cloneTreeIterList(); + void checkTreeIter(AstNode* backp); + void checkTreeIterList(AstNode* backp); + bool gateTreeIter() const; + static bool sameTreeIter(const AstNode* node1p, const AstNode* node2p, bool ignNext, + bool gateOnly); + void deleteTreeIter(); + void deleteNode(); + string locationStr() const; + public: static void relinkOneLink(AstNode*& pointpr, AstNode* newp); // cppcheck-suppress functionConst - void debugTreeChange(const char* prefix, int lineno, bool next); + void debugTreeChange(const char* prefix, int lineno, bool next); protected: // CONSTRUCTORS AstNode(AstType t) - : m_type(t) { init(); } + : m_type(t) { + init(); + } AstNode(AstType t, FileLine* fl) - : m_type(t) { init(); m_fileline = fl; } + : m_type(t) { + init(); + m_fileline = fl; + } virtual AstNode* clone() = 0; // Generally, cloneTree is what you want instead virtual void cloneRelink() {} void cloneRelinkTree(); @@ -1334,23 +1416,31 @@ protected: void setOp3p(AstNode* newp); // Set non-list-type op3 to non-list element void setOp4p(AstNode* newp); // Set non-list-type op4 to non-list element - void setNOp1p(AstNode* newp) { if (newp) setOp1p(newp); } - void setNOp2p(AstNode* newp) { if (newp) setOp2p(newp); } - void setNOp3p(AstNode* newp) { if (newp) setOp3p(newp); } - void setNOp4p(AstNode* newp) { if (newp) setOp4p(newp); } - void addOp1p(AstNode* newp); // Append newp to end of op1 void addOp2p(AstNode* newp); // Append newp to end of op2 void addOp3p(AstNode* newp); // Append newp to end of op3 void addOp4p(AstNode* newp); // Append newp to end of op4 + // clang-format off + void setNOp1p(AstNode* newp) { if (newp) setOp1p(newp); } + void setNOp2p(AstNode* newp) { if (newp) setOp2p(newp); } + void setNOp3p(AstNode* newp) { if (newp) setOp3p(newp); } + void setNOp4p(AstNode* newp) { if (newp) setOp4p(newp); } + void addNOp1p(AstNode* newp) { if (newp) addOp1p(newp); } void addNOp2p(AstNode* newp) { if (newp) addOp2p(newp); } void addNOp3p(AstNode* newp) { if (newp) addOp3p(newp); } void addNOp4p(AstNode* newp) { if (newp) addOp4p(newp); } + // clang-format on - void clonep(AstNode* nodep) { m_clonep = nodep; m_cloneCnt = s_cloneCntGbl; } - static void cloneClearTree() { s_cloneCntGbl++; UASSERT_STATIC(s_cloneCntGbl, "Rollover"); } + void clonep(AstNode* nodep) { + m_clonep = nodep; + m_cloneCnt = s_cloneCntGbl; + } + static void cloneClearTree() { + s_cloneCntGbl++; + UASSERT_STATIC(s_cloneCntGbl, "Rollover"); + } public: // ACCESSORS @@ -1364,9 +1454,10 @@ public: AstNode* op3p() const { return m_op3p; } AstNode* op4p() const { return m_op4p; } AstNodeDType* dtypep() const { return m_dtypep; } - AstNode* clonep() const { return ((m_cloneCnt==s_cloneCntGbl)?m_clonep:NULL); } + AstNode* clonep() const { return ((m_cloneCnt == s_cloneCntGbl) ? m_clonep : NULL); } AstNode* firstAbovep() const { // Returns NULL when second or later in list - return ((backp() && backp()->nextp()!=this) ? backp() : NULL); } + return ((backp() && backp()->nextp() != this) ? backp() : NULL); + } bool brokeExists() const; bool brokeExistsAbove() const; @@ -1378,23 +1469,27 @@ public: #endif // CONSTANT ACCESSORS - static int instrCountBranch() { return 4; } ///< Instruction cycles to branch - static int instrCountDiv() { return 10; } ///< Instruction cycles to divide - static int instrCountDpi() { return 1000; } ///< Instruction cycles to call user function - static int instrCountLd() { return 2; } ///< Instruction cycles to load memory - static int instrCountMul() { return 3; } ///< Instruction cycles to multiply integers - static int instrCountPli() { return 20; } ///< Instruction cycles to call pli routines - static int instrCountDouble() { return 8; } ///< Instruction cycles to convert or do floats - static int instrCountDoubleDiv() { return 40; } ///< Instruction cycles to divide floats + static int instrCountBranch() { return 4; } ///< Instruction cycles to branch + static int instrCountDiv() { return 10; } ///< Instruction cycles to divide + static int instrCountDpi() { return 1000; } ///< Instruction cycles to call user function + static int instrCountLd() { return 2; } ///< Instruction cycles to load memory + static int instrCountMul() { return 3; } ///< Instruction cycles to multiply integers + static int instrCountPli() { return 20; } ///< Instruction cycles to call pli routines + static int instrCountDouble() { return 8; } ///< Instruction cycles to convert or do floats + static int instrCountDoubleDiv() { return 40; } ///< Instruction cycles to divide floats static int instrCountDoubleTrig() { return 200; } ///< Instruction cycles to do trigonomics - static int instrCountString() { return 100; } ///< Instruction cycles to do string ops - static int instrCountCall() { return instrCountBranch()+10; } ///< Instruction cycles to call subroutine - static int instrCountTime() { return instrCountCall()+5; } ///< Instruction cycles to determine simulation time + static int instrCountString() { return 100; } ///< Instruction cycles to do string ops + /// Instruction cycles to call subroutine + static int instrCountCall() { return instrCountBranch() + 10; } + /// Instruction cycles to determine simulation time + static int instrCountTime() { return instrCountCall() + 5; } // ACCESSORS virtual string name() const { return ""; } virtual string origName() const { return ""; } - virtual void name(const string& name) { this->v3fatalSrc("name() called on object without name() method"); } + virtual void name(const string& name) { + this->v3fatalSrc("name() called on object without name() method"); + } virtual void tag(const string& text) {} virtual string tag() const { return ""; } virtual string verilogKwd() const { return ""; } @@ -1404,30 +1499,38 @@ public: static string dedotName(const string& namein); // Name with dots removed static string prettyName(const string& namein); // Name for printing out to the user static string prettyNameQ(const string& namein) { // Quoted pretty name (for errors) - return string("'")+prettyName(namein)+"'"; } - static string encodeName(const string& namein); // Encode user name into internal C representation + return string("'") + prettyName(namein) + "'"; + } + static string + encodeName(const string& namein); // Encode user name into internal C representation static string encodeNumber(vlsint64_t num); // Encode number into internal C representation static string vcdName(const string& namein); // Name for printing out to vcd files string prettyName() const { return prettyName(name()); } string prettyNameQ() const { return prettyNameQ(name()); } string prettyTypeName() const; // "VARREF" for error messages (NOT dtype's pretty name) - virtual string prettyOperatorName() const { return "operator "+prettyTypeName(); } + virtual string prettyOperatorName() const { return "operator " + prettyTypeName(); } FileLine* fileline() const { return m_fileline; } void fileline(FileLine* fl) { m_fileline = fl; } bool width1() const; int widthInstrs() const; void didWidth(bool flag) { m_didWidth = flag; } bool didWidth() const { return m_didWidth; } - bool didWidthAndSet() { if (didWidth()) return true; didWidth(true); return false; } + bool didWidthAndSet() { + if (didWidth()) return true; + didWidth(true); + return false; + } bool doingWidth() const { return m_doingWidth; } void doingWidth(bool flag) { m_doingWidth = flag; } bool protect() const { return m_protect; } void protect(bool flag) { m_protect = flag; } - //TODO stomp these width functions out, and call via dtypep() instead + // TODO stomp these width functions out, and call via dtypep() instead int width() const; int widthMin() const; - int widthMinV() const { return v3Global.widthMinUsage()==VWidthMinUsage::VERILOG_WIDTH ? widthMin() : width(); } + int widthMinV() const { + return v3Global.widthMinUsage() == VWidthMinUsage::VERILOG_WIDTH ? widthMin() : width(); + } int widthWords() const { return VL_WORDS_I(width()); } bool isQuad() const { return (width() > VL_IDATASIZE && width() <= VL_QUADSIZE); } bool isWide() const { return (width() > VL_QUADSIZE); } @@ -1435,6 +1538,7 @@ public: bool isSigned() const; bool isString() const; + // clang-format off VNUser user1u() const { // Slows things down measurably, so disabled by default //UASSERT_STATIC(AstUser1InUse::s_userBusy, "userp set w/o busy"); @@ -1504,9 +1608,12 @@ public: int user5Inc(int val=1) { int v=user5(); user5(v+val); return v; } int user5SetOnce() { int v=user5(); if (!v) user5(1); return v; } // Better for cache than user5Inc() static void user5ClearTree() { AstUser5InUse::clear(); } // Clear userp()'s across the entire tree + // clang-format on vluint64_t editCount() const { return m_editCount; } - void editCountInc() { m_editCount = ++s_editCntGbl; } // Preincrement, so can "watch AstNode::s_editCntGbl=##" + void editCountInc() { + m_editCount = ++s_editCntGbl; // Preincrement, so can "watch AstNode::s_editCntGbl=##" + } static vluint64_t editCountLast() { return s_editCntLast; } static vluint64_t editCountGbl() { return s_editCntGbl; } static void editCountSetLast() { s_editCntLast = editCountGbl(); } @@ -1520,34 +1627,45 @@ public: bool isAllOnesV() const; // Verilog width rules apply // METHODS - data type changes especially for initial creation - void dtypep(AstNodeDType* nodep) { if (m_dtypep != nodep) { m_dtypep = nodep; editCountInc(); } } - void dtypeFrom(AstNode* fromp) { if (fromp) { dtypep(fromp->dtypep()); }} - void dtypeChgSigned(bool flag=true); + void dtypep(AstNodeDType* nodep) { + if (m_dtypep != nodep) { + m_dtypep = nodep; + editCountInc(); + } + } + void dtypeFrom(AstNode* fromp) { + if (fromp) { dtypep(fromp->dtypep()); } + } + void dtypeChgSigned(bool flag = true); void dtypeChgWidth(int width, int widthMin); void dtypeChgWidthSigned(int width, int widthMin, AstNumeric numeric); void dtypeSetBitUnsized(int width, int widthMin, AstNumeric numeric) { - dtypep(findBitDType(width, widthMin, numeric)); } + dtypep(findBitDType(width, widthMin, numeric)); + } void dtypeSetBitSized(int width, AstNumeric numeric) { - dtypep(findBitDType(width, width, numeric)); } // Since sized, widthMin is width + dtypep(findBitDType(width, width, numeric)); // Since sized, widthMin is width + } void dtypeSetLogicUnsized(int width, int widthMin, AstNumeric numeric) { - dtypep(findLogicDType(width, widthMin, numeric)); } + dtypep(findLogicDType(width, widthMin, numeric)); + } void dtypeSetLogicSized(int width, AstNumeric numeric) { - dtypep(findLogicDType(width, width, numeric)); } // Since sized, widthMin is width - void dtypeSetLogicBool() { dtypep(findLogicBoolDType()); } - void dtypeSetDouble() { dtypep(findDoubleDType()); } - void dtypeSetString() { dtypep(findStringDType()); } - void dtypeSetSigned32() { dtypep(findSigned32DType()); } - void dtypeSetUInt32() { dtypep(findUInt32DType()); } // Twostate - void dtypeSetUInt64() { dtypep(findUInt64DType()); } // Twostate + dtypep(findLogicDType(width, width, numeric)); // Since sized, widthMin is width + } + void dtypeSetLogicBool() { dtypep(findLogicBoolDType()); } + void dtypeSetDouble() { dtypep(findDoubleDType()); } + void dtypeSetString() { dtypep(findStringDType()); } + void dtypeSetSigned32() { dtypep(findSigned32DType()); } + void dtypeSetUInt32() { dtypep(findUInt32DType()); } // Twostate + void dtypeSetUInt64() { dtypep(findUInt64DType()); } // Twostate void dtypeSetVoid() { dtypep(findVoidDType()); } // Data type locators - AstNodeDType* findLogicBoolDType() { return findBasicDType(AstBasicDTypeKwd::LOGIC); } - AstNodeDType* findDoubleDType() { return findBasicDType(AstBasicDTypeKwd::DOUBLE); } - AstNodeDType* findStringDType() { return findBasicDType(AstBasicDTypeKwd::STRING); } - AstNodeDType* findSigned32DType() { return findBasicDType(AstBasicDTypeKwd::INTEGER); } - AstNodeDType* findUInt32DType() { return findBasicDType(AstBasicDTypeKwd::UINT32); } // Twostate - AstNodeDType* findUInt64DType() { return findBasicDType(AstBasicDTypeKwd::UINT64); } // Twostate + AstNodeDType* findLogicBoolDType() { return findBasicDType(AstBasicDTypeKwd::LOGIC); } + AstNodeDType* findDoubleDType() { return findBasicDType(AstBasicDTypeKwd::DOUBLE); } + AstNodeDType* findStringDType() { return findBasicDType(AstBasicDTypeKwd::STRING); } + AstNodeDType* findSigned32DType() { return findBasicDType(AstBasicDTypeKwd::INTEGER); } + AstNodeDType* findUInt32DType() { return findBasicDType(AstBasicDTypeKwd::UINT32); } + AstNodeDType* findUInt64DType() { return findBasicDType(AstBasicDTypeKwd::UINT64); } AstNodeDType* findVoidDType() const; AstNodeDType* findBitDType(int width, int widthMin, AstNumeric numeric) const; AstNodeDType* findLogicDType(int width, int widthMin, AstNumeric numeric) const; @@ -1566,66 +1684,89 @@ public: string warnMore() const { return fileline()->warnMore(); } string warnOther() const { return fileline()->warnOther(); } - virtual void dump(std::ostream& str=std::cout) const; + virtual void dump(std::ostream& str = std::cout) const; void dumpGdb(); // For GDB only void dumpGdbHeader() const; // METHODS - Tree modifications - static AstNode* addNext(AstNode* nodep, AstNode* newp); // Returns nodep, adds newp to end of nodep's list - static AstNode* addNextNull(AstNode* nodep, AstNode* newp); // Returns nodep, adds newp (maybe NULL) to end of nodep's list + // Returns nodep, adds newp to end of nodep's list + static AstNode* addNext(AstNode* nodep, AstNode* newp); + // Returns nodep, adds newp (maybe NULL) to end of nodep's list + static AstNode* addNextNull(AstNode* nodep, AstNode* newp); inline AstNode* addNext(AstNode* newp) { return addNext(this, newp); } inline AstNode* addNextNull(AstNode* newp) { return addNextNull(this, newp); } void addNextHere(AstNode* newp); // Insert newp at this->nextp - void addPrev(AstNode* newp) { replaceWith(newp); newp->addNext(this); } + void addPrev(AstNode* newp) { + replaceWith(newp); + newp->addNext(this); + } void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next void replaceWith(AstNode* newp); // Replace current node in tree with new node - AstNode* unlinkFrBack(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it. + AstNode* unlinkFrBack(AstNRelinker* linkerp = NULL); // Unlink this from whoever points to it. // Unlink this from whoever points to it, keep entire next list with unlinked node - AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp=NULL); + AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp = NULL); void swapWith(AstNode* bp); void relink(AstNRelinker* linkerp); // Generally use linker->relink() instead void cloneRelinkNode() { cloneRelink(); } // Iterate and insert - assumes tree format - virtual void addNextStmt(AstNode* newp, AstNode* belowp); // When calling, "this" is second argument - virtual void addBeforeStmt(AstNode* newp, AstNode* belowp); // When calling, "this" is second argument + virtual void addNextStmt(AstNode* newp, + AstNode* belowp); // When calling, "this" is second argument + virtual void addBeforeStmt(AstNode* newp, + AstNode* belowp); // When calling, "this" is second argument // METHODS - Iterate on a tree // Clone or return NULL if NULL static AstNode* cloneTreeNull(AstNode* nodep, bool cloneNextLink) { - return nodep ? nodep->cloneTree(cloneNextLink) : NULL; } + return nodep ? nodep->cloneTree(cloneNextLink) : NULL; + } AstNode* cloneTree(bool cloneNextLink); // Not const, as sets clonep() on original nodep bool gateTree() { return gateTreeIter(); } // Is tree isGateOptimizable? bool sameTree(const AstNode* node2p) const; // Does tree of this == node2p? - bool sameGateTree(const AstNode* node2p) const; // Does tree of this == node2p?, not allowing non-isGateOptimizable + // Does tree of this == node2p?, not allowing non-isGateOptimizable + bool sameGateTree(const AstNode* node2p) const; void deleteTree(); // Always deletes the next link void checkTree(); // User Interface version void checkIter() const; void clearIter() { m_iterpp = NULL; } - void dumpPtrs(std::ostream& os=std::cout) const; - void dumpTree(std::ostream& os=std::cout, const string& indent=" ", int maxDepth=0) const; - void dumpTree(const string& indent, int maxDepth=0) const { dumpTree(cout, indent, maxDepth); } + void dumpPtrs(std::ostream& os = std::cout) const; + void dumpTree(std::ostream& os = std::cout, const string& indent = " ", + int maxDepth = 0) const; + void dumpTree(const string& indent, int maxDepth = 0) const { + dumpTree(cout, indent, maxDepth); + } void dumpTreeGdb(); // For GDB only - void dumpTreeAndNext(std::ostream& os=std::cout, const string& indent=" ", int maxDepth=0) const; - void dumpTreeFile(const string& filename, bool append=false, bool doDump=true); - static void dumpTreeFileGdb(const char* filenamep=NULL); + void dumpTreeAndNext(std::ostream& os = std::cout, const string& indent = " ", + int maxDepth = 0) const; + void dumpTreeFile(const string& filename, bool append = false, bool doDump = true); + static void dumpTreeFileGdb(const char* filenamep = NULL); // METHODS - queries - virtual bool isPure() const { return true; } // Else a $display, etc, that must be ordered with other displays - virtual bool isBrancher() const { return false; } // Changes control flow, disable some optimizations - virtual bool isGateOptimizable() const { return true; } // Else a AstTime etc that can't be pushed out + // Else a $display, etc, that must be ordered with other displays + virtual bool isPure() const { return true; } + // Changes control flow, disable some optimizations + virtual bool isBrancher() const { return false; } + // Else a AstTime etc that can't be pushed out + virtual bool isGateOptimizable() const { return true; } // GateDedupable is a slightly larger superset of GateOptimzable (eg, AstNodeIf) virtual bool isGateDedupable() const { return isGateOptimizable(); } - virtual bool isSubstOptimizable() const { return true; } // Else a AstTime etc that can't be substituted out - virtual bool isPredictOptimizable() const { return true; } // Else a AstTime etc which output can't be predicted from input - virtual bool isOutputter() const { return false; } // Else creates output or exits, etc, not unconsumed + // Else a AstTime etc that can't be substituted out + virtual bool isSubstOptimizable() const { return true; } + // Else a AstTime etc which output can't be predicted from input + virtual bool isPredictOptimizable() const { return true; } + // Else creates output or exits, etc, not unconsumed + virtual bool isOutputter() const { return false; } // isUnlikely handles $stop or similar statement which means an above IF // statement is unlikely to be taken virtual bool isUnlikely() const { return false; } virtual int instrCount() const { return 0; } - virtual V3Hash sameHash() const { return V3Hash(V3Hash::Illegal()); } // Not a node that supports it + virtual V3Hash sameHash() const { + return V3Hash(V3Hash::Illegal()); // Not a node that supports it + } virtual bool same(const AstNode*) const { return true; } - virtual bool hasDType() const { return false; } // Iff has a data type; dtype() must be non null - virtual AstNodeDType* getChildDTypep() const { return NULL; } // Iff has a non-null childDTypep(), as generic node function + // Iff has a data type; dtype() must be non null + virtual bool hasDType() const { return false; } + // Iff has a non-null childDTypep(), as generic node function + virtual AstNodeDType* getChildDTypep() const { return NULL; } // Another AstNode* may have a pointer into this node, other then normal front/back/etc. virtual bool maybePointedTo() const { return false; } virtual const char* broken() const { return NULL; } @@ -1636,35 +1777,44 @@ public: protected: // All AstNVisitor related functions are called as methods off the visitor friend class AstNVisitor; - void iterateChildren(AstNVisitor& v); // Use instead AstNVisitor::iterateChildren - void iterateChildrenBackwards(AstNVisitor& v); // Use instead AstNVisitor::iterateChildrenBackwards - void iterateChildrenConst(AstNVisitor& v); // Use instead AstNVisitor::iterateChildrenConst - void iterateAndNext(AstNVisitor& v); // Use instead AstNVisitor::iterateAndNextNull - void iterateAndNextConst(AstNVisitor& v); // Use instead AstNVisitor::iterateAndNextConstNull - AstNode* iterateSubtreeReturnEdits(AstNVisitor& v); // Use instead AstNVisitor::iterateSubtreeReturnEdits + // Use instead AstNVisitor::iterateChildren + void iterateChildren(AstNVisitor& v); + // Use instead AstNVisitor::iterateChildrenBackwards + void iterateChildrenBackwards(AstNVisitor& v); + // Use instead AstNVisitor::iterateChildrenConst + void iterateChildrenConst(AstNVisitor& v); + // Use instead AstNVisitor::iterateAndNextNull + void iterateAndNext(AstNVisitor& v); + // Use instead AstNVisitor::iterateAndNextConstNull + void iterateAndNextConst(AstNVisitor& v); + // Use instead AstNVisitor::iterateSubtreeReturnEdits + AstNode* iterateSubtreeReturnEdits(AstNVisitor& v); + private: void iterateListBackwards(AstNVisitor& v); // CONVERSION public: // These for use by VN_IS macro only - template - static bool privateIs(const AstNode* nodep); + template static bool privateIs(const AstNode* nodep); // These for use by VN_CAST macro only - template - static T* privateCast(AstNode* nodep); + template static T* privateCast(AstNode* nodep); // These for use by VN_CAST_CONST macro only - template - static const T* privateConstCast(const AstNode* nodep); + template static const T* privateConstCast(const AstNode* nodep); }; // Specialisations of privateIs/privateCast #include "V3Ast__gen_impl.h" // From ./astgen inline std::ostream& operator<<(std::ostream& os, const AstNode* rhs) { - if (!rhs) os<<"NULL"; else rhs->dump(os); return os; + if (!rhs) { + os << "NULL"; + } else { + rhs->dump(os); + } + return os; } inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); } @@ -1672,12 +1822,15 @@ inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); } //###################################################################### //=== AstNode* : Derived generic node types -#define ASTNODE_BASE_FUNCS(name) \ - virtual ~Ast ##name() {} \ - static Ast ##name * cloneTreeNull(Ast ##name * nodep, bool cloneNextLink) { \ - return nodep ? nodep->cloneTree(cloneNextLink) : NULL; } \ - Ast ##name * cloneTree(bool cloneNext) { return static_cast(AstNode::cloneTree(cloneNext)); } \ - Ast ##name * clonep() const { return static_cast(AstNode::clonep()); } +#define ASTNODE_BASE_FUNCS(name) \ + virtual ~Ast##name() {} \ + static Ast##name* cloneTreeNull(Ast##name* nodep, bool cloneNextLink) { \ + return nodep ? nodep->cloneTree(cloneNextLink) : NULL; \ + } \ + Ast##name* cloneTree(bool cloneNext) { \ + return static_cast(AstNode::cloneTree(cloneNext)); \ + } \ + Ast##name* clonep() const { return static_cast(AstNode::clonep()); } class AstNodeMath : public AstNode { // Math -- anything that's part of an expression tree @@ -1706,7 +1859,7 @@ public: // Know no children, and hot function, so skip iterator for speed // See checkTreeIter also that asserts no children // cppcheck-suppress functionConst - void iterateChildren(AstNVisitor& v) { } + void iterateChildren(AstNVisitor& v) {} }; class AstNodeUniop : public AstNodeMath { @@ -1715,16 +1868,19 @@ public: AstNodeUniop(AstType t, FileLine* fl, AstNode* lhsp) : AstNodeMath(t, fl) { dtypeFrom(lhsp); - setOp1p(lhsp); } + setOp1p(lhsp); + } ASTNODE_BASE_FUNCS(NodeUniop) AstNode* lhsp() const { return op1p(); } void lhsp(AstNode* nodep) { return setOp1p(nodep); } // METHODS - virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs + // Set out to evaluation of a AstConst'ed lhs + virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; virtual bool cleanLhs() const = 0; virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors? - virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors? + // Signed flavor of nodes with both flavors? + virtual bool signedFlavor() const { return false; } virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors? virtual int instrCount() const { return widthInstrs(); } virtual V3Hash sameHash() const { return V3Hash(); } @@ -1736,22 +1892,27 @@ class AstNodeBiop : public AstNodeMath { public: AstNodeBiop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs) : AstNodeMath(t, fl) { - setOp1p(lhs); setOp2p(rhs); } + setOp1p(lhs); + setOp2p(rhs); + } ASTNODE_BASE_FUNCS(NodeBiop) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0; // Clone single node, just get same type back. + // Clone single node, just get same type back. + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0; // ACCESSORS AstNode* lhsp() const { return op1p(); } AstNode* rhsp() const { return op2p(); } void lhsp(AstNode* nodep) { return setOp1p(nodep); } void rhsp(AstNode* nodep) { return setOp2p(nodep); } // METHODS - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) = 0; // Set out to evaluation of a AstConst'ed + // Set out to evaluation of a AstConst'ed + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) = 0; virtual bool cleanLhs() const = 0; // True if LHS must have extra upper bits zero virtual bool cleanRhs() const = 0; // True if RHS must have extra upper bits zero virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors? - virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors? + // Signed flavor of nodes with both flavors? + virtual bool signedFlavor() const { return false; } virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors? virtual int instrCount() const { return widthInstrs(); } virtual V3Hash sameHash() const { return V3Hash(); } @@ -1763,7 +1924,10 @@ class AstNodeTriop : public AstNodeMath { public: AstNodeTriop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths) : AstNodeMath(t, fl) { - setOp1p(lhs); setOp2p(rhs); setOp3p(ths); } + setOp1p(lhs); + setOp2p(rhs); + setOp3p(ths); + } ASTNODE_BASE_FUNCS(NodeTriop) AstNode* lhsp() const { return op1p(); } AstNode* rhsp() const { return op2p(); } @@ -1773,8 +1937,9 @@ public: void thsp(AstNode* nodep) { return setOp3p(nodep); } // METHODS // Set out to evaluation of a AstConst'ed - virtual void numberOperate(V3Number& out, const V3Number& lhs, - const V3Number& rhs, const V3Number& ths) = 0; + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) + = 0; virtual bool cleanLhs() const = 0; // True if LHS must have extra upper bits zero virtual bool cleanRhs() const = 0; // True if RHS must have extra upper bits zero virtual bool cleanThs() const = 0; // True if THS must have extra upper bits zero @@ -1805,12 +1970,15 @@ class AstNodeCond : public AstNodeTriop { public: AstNodeCond(AstType t, FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) : AstNodeTriop(t, fl, condp, expr1p, expr2p) { - if (expr1p) dtypeFrom(expr1p); - else if (expr2p) dtypeFrom(expr2p); + if (expr1p) { + dtypeFrom(expr1p); + } else if (expr2p) { + dtypeFrom(expr2p); + } } ASTNODE_BASE_FUNCS(NodeCond) - virtual void numberOperate(V3Number& out, const V3Number& lhs, - const V3Number& rhs, const V3Number& ths); + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths); AstNode* condp() const { return op1p(); } // op1 = Condition AstNode* expr1p() const { return op2p(); } // op2 = If true... AstNode* expr2p() const { return op3p(); } // op3 = If false... @@ -1832,7 +2000,10 @@ class AstNodePreSel : public AstNode { public: AstNodePreSel(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths) : AstNode(t, fl) { - setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); } + setOp1p(lhs); + setOp2p(rhs); + setNOp3p(ths); + } ASTNODE_BASE_FUNCS(NodePreSel) AstNode* lhsp() const { return op1p(); } AstNode* fromp() const { return lhsp(); } @@ -1867,11 +2038,13 @@ class AstNodeAssign : public AstNodeStmt { public: AstNodeAssign(AstType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeStmt(t, fl) { - setOp1p(rhsp); setOp2p(lhsp); + setOp1p(rhsp); + setOp2p(lhsp); dtypeFrom(lhsp); } ASTNODE_BASE_FUNCS(NodeAssign) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0; // Clone single node, just get same type back. + // Clone single node, just get same type back. + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0; // So iteration hits the RHS which is "earlier" in execution order, it's op1, not op2 AstNode* rhsp() const { return op1p(); } // op1 = Assign from AstNode* lhsp() const { return op2p(); } // op2 = Assign to @@ -1888,10 +2061,13 @@ public: class AstNodeFor : public AstNodeStmt { public: - AstNodeFor(AstType t, FileLine* fl, AstNode* initsp, AstNode* condp, - AstNode* incsp, AstNode* bodysp) + AstNodeFor(AstType t, FileLine* fl, AstNode* initsp, AstNode* condp, AstNode* incsp, + AstNode* bodysp) : AstNodeStmt(t, fl) { - addNOp1p(initsp); setOp2p(condp); addNOp3p(incsp); addNOp4p(bodysp); + addNOp1p(initsp); + setOp2p(condp); + addNOp3p(incsp); + addNOp4p(bodysp); } ASTNODE_BASE_FUNCS(NodeFor) AstNode* initsp() const { return op1p(); } // op1 = initial statements @@ -1910,7 +2086,9 @@ private: public: AstNodeIf(AstType t, FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp) : AstNodeStmt(t, fl) { - setOp1p(condp); addNOp2p(ifsp); addNOp3p(elsesp); + setOp1p(condp); + addNOp2p(ifsp); + addNOp3p(elsesp); } ASTNODE_BASE_FUNCS(NodeIf) AstNode* condp() const { return op1p(); } // op1 = condition @@ -1932,12 +2110,15 @@ class AstNodeCase : public AstNodeStmt { public: AstNodeCase(AstType t, FileLine* fl, AstNode* exprp, AstNode* casesp) : AstNodeStmt(t, fl) { - setOp1p(exprp); addNOp2p(casesp); + setOp1p(exprp); + addNOp2p(casesp); } ASTNODE_BASE_FUNCS(NodeCase) virtual int instrCount() const { return instrCountBranch(); } AstNode* exprp() const { return op1p(); } // op1 = case condition - AstCaseItem* itemsp() const { return VN_CAST(op2p(), CaseItem); } // op2 = list of case expressions + AstCaseItem* itemsp() const { + return VN_CAST(op2p(), CaseItem); + } // op2 = list of case expressions AstNode* notParallelp() const { return op3p(); } // op3 = assertion code for non-full case's void addItemsp(AstNode* nodep) { addOp2p(nodep); } void addNotParallelp(AstNode* nodep) { setOp3p(nodep); } @@ -1959,23 +2140,34 @@ public: class AstNodeVarRef : public AstNodeMath { // An AstVarRef or AstVarXRef private: - bool m_lvalue; // Left hand side assignment - AstVar* m_varp; // [AfterLink] Pointer to variable itself - AstVarScope* m_varScopep; // Varscope for hierarchy + bool m_lvalue; // Left hand side assignment + AstVar* m_varp; // [AfterLink] Pointer to variable itself + AstVarScope* m_varScopep; // Varscope for hierarchy AstNodeModule* m_packagep; // Package hierarchy - string m_name; // Name of variable - string m_hiername; // Scope converted into name-> for emitting - bool m_hierThis; // Hiername points to "this" function + string m_name; // Name of variable + string m_hiername; // Scope converted into name-> for emitting + bool m_hierThis; // Hiername points to "this" function void init(); + public: AstNodeVarRef(AstType t, FileLine* fl, const string& name, bool lvalue) - : AstNodeMath(t, fl), m_lvalue(lvalue), m_varp(NULL), m_varScopep(NULL) - , m_packagep(NULL), m_name(name), m_hierThis(false) { + : AstNodeMath(t, fl) + , m_lvalue(lvalue) + , m_varp(NULL) + , m_varScopep(NULL) + , m_packagep(NULL) + , m_name(name) + , m_hierThis(false) { init(); } AstNodeVarRef(AstType t, FileLine* fl, const string& name, AstVar* varp, bool lvalue) - : AstNodeMath(t, fl), m_lvalue(lvalue), m_varp(varp), m_varScopep(NULL) - , m_packagep(NULL), m_name(name), m_hierThis(false) { + : AstNodeMath(t, fl) + , m_lvalue(lvalue) + , m_varp(varp) + , m_varScopep(NULL) + , m_packagep(NULL) + , m_name(name) + , m_hierThis(false) { // May have varp==NULL init(); } @@ -2002,12 +2194,13 @@ public: // Know no children, and hot function, so skip iterator for speed // See checkTreeIter also that asserts no children // cppcheck-suppress functionConst - void iterateChildren(AstNVisitor& v) { } + void iterateChildren(AstNVisitor& v) {} }; class AstNodeText : public AstNode { private: - string m_text; + string m_text; + public: // Node that simply puts text into the output stream AstNodeText(AstType t, FileLine* fl, const string& textp) @@ -2015,11 +2208,12 @@ public: m_text = textp; // Copy it } ASTNODE_BASE_FUNCS(NodeText) - virtual void dump(std::ostream& str=std::cout) const; + virtual void dump(std::ostream& str = std::cout) const; virtual V3Hash sameHash() const { return V3Hash(text()); } virtual bool same(const AstNode* samep) const { const AstNodeText* asamep = static_cast(samep); - return text() == asamep->text(); } + return text() == asamep->text(); + } const string& text() const { return m_text; } }; @@ -2028,17 +2222,21 @@ class AstNodeDType : public AstNode { // but it's currently so prevalent in the code we leave it here. // Note the below members are included in AstTypeTable::Key lookups private: - int m_width; // (also in AstTypeTable::Key) Bit width of operation - int m_widthMin; // (also in AstTypeTable::Key) If unsized, bitwidth of minimum implementation - AstNumeric m_numeric; // (also in AstTypeTable::Key) Node is signed + int m_width; // (also in AstTypeTable::Key) Bit width of operation + int m_widthMin; // (also in AstTypeTable::Key) If unsized, bitwidth of minimum implementation + AstNumeric m_numeric; // (also in AstTypeTable::Key) Node is signed // Other members - bool m_generic; // Simple globally referenced type, don't garbage collect - static int s_uniqueNum; // Unique number assigned to each dtype during creation for IEEE matching + bool m_generic; // Simple globally referenced type, don't garbage collect + // Unique number assigned to each dtype during creation for IEEE matching + static int s_uniqueNum; + public: // CONSTRUCTORS AstNodeDType(AstType t, FileLine* fl) : AstNode(t, fl) { - m_width = 0; m_widthMin = 0; m_generic = false; + m_width = 0; + m_widthMin = 0; + m_generic = false; } ASTNODE_BASE_FUNCS(NodeDType) // ACCESSORS @@ -2046,27 +2244,47 @@ public: virtual void dumpSmall(std::ostream& str) const; virtual bool hasDType() const { return true; } virtual AstBasicDType* basicp() const = 0; // (Slow) recurse down to find basic data type - virtual AstNodeDType* skipRefp() const = 0; // recurses over typedefs/const/enum to next non-typeref type - virtual AstNodeDType* skipRefToConstp() const = 0; // recurses over typedefs to next non-typeref-or-const type - virtual AstNodeDType* skipRefToEnump() const = 0; // recurses over typedefs/const to next non-typeref-or-enum/struct type - virtual int widthAlignBytes() const = 0; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) - virtual int widthTotalBytes() const = 0; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... + // recurses over typedefs/const/enum to next non-typeref type + virtual AstNodeDType* skipRefp() const = 0; + // recurses over typedefs to next non-typeref-or-const type + virtual AstNodeDType* skipRefToConstp() const = 0; + // recurses over typedefs/const to next non-typeref-or-enum/struct type + virtual AstNodeDType* skipRefToEnump() const = 0; + // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) + virtual int widthAlignBytes() const = 0; + virtual int + // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... + widthTotalBytes() const = 0; virtual bool maybePointedTo() const { return true; } - virtual AstNodeDType* virtRefDTypep() const { return NULL; } // Iff has a non-null refDTypep(), as generic node function - virtual void virtRefDTypep(AstNodeDType* nodep) { } // Iff has refDTypep(), set as generic node function - virtual AstNodeDType* virtRefDType2p() const { return NULL; } // Iff has a non-null second dtypep, as generic node function - virtual void virtRefDType2p(AstNodeDType* nodep) { } // Iff has second dtype, set as generic node function - virtual bool similarDType(AstNodeDType* samep) const = 0; // Assignable equivalence. Call skipRefp() on this and samep before calling - virtual AstNodeDType* subDTypep() const { return NULL; } // Iff has a non-null subDTypep(), as generic node function + // Iff has a non-null refDTypep(), as generic node function + virtual AstNodeDType* virtRefDTypep() const { return NULL; } + // Iff has refDTypep(), set as generic node function + virtual void virtRefDTypep(AstNodeDType* nodep) {} + // Iff has a non-null second dtypep, as generic node function + virtual AstNodeDType* virtRefDType2p() const { return NULL; } + // Iff has second dtype, set as generic node function + virtual void virtRefDType2p(AstNodeDType* nodep) {} + // Assignable equivalence. Call skipRefp() on this and samep before calling + virtual bool similarDType(AstNodeDType* samep) const = 0; + // Iff has a non-null subDTypep(), as generic node function + virtual AstNodeDType* subDTypep() const { return NULL; } virtual bool isFourstate() const; - virtual string prettyDTypeName() const { return prettyTypeName(); } // Ideally an IEEE $typename + // Ideally an IEEE $typename + virtual string prettyDTypeName() const { return prettyTypeName(); } string prettyDTypeNameQ() const { return "'" + prettyDTypeName() + "'"; } // // Changing the width may confuse the data type resolution, so must clear // TypeTable cache after use. - void widthForce(int width, int widthMin) { m_width = width; m_widthMin = widthMin; } + void widthForce(int width, int widthMin) { + m_width = width; + m_widthMin = widthMin; + } // For backward compatibility inherit width and signing from the subDType/base type - void widthFromSub(AstNodeDType* nodep) { m_width = nodep->m_width; m_widthMin = nodep->m_widthMin; m_numeric = nodep->m_numeric; } + void widthFromSub(AstNodeDType* nodep) { + m_width = nodep->m_width; + m_widthMin = nodep->m_widthMin; + m_numeric = nodep->m_numeric; + } // int width() const { return m_width; } void numeric(AstNumeric flag) { m_numeric = flag; } @@ -2075,29 +2293,33 @@ public: AstNumeric numeric() const { return m_numeric; } int widthWords() const { return VL_WORDS_I(width()); } int widthMin() const { // If sized, the size, if unsized the min digits to represent it - return m_widthMin?m_widthMin:m_width; } + return m_widthMin ? m_widthMin : m_width; + } int widthPow2() const; void widthMinFromWidth() { m_widthMin = m_width; } - bool widthSized() const { return !m_widthMin || m_widthMin==m_width; } + bool widthSized() const { return !m_widthMin || m_widthMin == m_width; } bool generic() const { return m_generic; } void generic(bool flag) { m_generic = flag; } AstNodeDType* dtypeDimensionp(int dimension); - std::pair dimensions(bool includeBasic); + std::pair dimensions(bool includeBasic); uint32_t arrayUnpackedElements(); // 1, or total multiplication of all dimensions static int uniqueNumInc() { return ++s_uniqueNum; } - const char* charIQWN() const { return (isString() ? "N" : isWide() ? "W" : isQuad() ? "Q" : "I"); } + const char* charIQWN() const { + return (isString() ? "N" : isWide() ? "W" : isQuad() ? "Q" : "I"); + } }; class AstNodeUOrStructDType : public AstNodeDType { // A struct or union; common handling private: // TYPES - typedef std::map MemberNameMap; + typedef std::map MemberNameMap; // MEMBERS string m_name; // Name from upper typedef, if any - bool m_packed; - bool m_isFourstate; - MemberNameMap m_members; + bool m_packed; + bool m_isFourstate; + MemberNameMap m_members; + public: AstNodeUOrStructDType(AstType t, FileLine* fl, AstNumeric numericUnpack) : AstNodeDType(t, fl) { @@ -2121,28 +2343,34 @@ public: virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) - virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... + virtual int widthAlignBytes() + const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) + virtual int + widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... // op1 = members virtual bool similarDType(AstNodeDType* samep) const { - return this==samep; // We don't compare members, require exact equivalence + return this == samep; // We don't compare members, require exact equivalence } virtual string name() const { return m_name; } void name(const string& flag) { m_name = flag; } - AstMemberDType* membersp() const { return VN_CAST(op1p(), MemberDType); } // op1 = AstMember list + AstMemberDType* membersp() const { + return VN_CAST(op1p(), MemberDType); + } // op1 = AstMember list void addMembersp(AstNode* nodep) { addNOp1p(nodep); } bool packed() const { return m_packed; } - bool packedUnsup() const { return true; } // packed() but as don't support unpacked, presently all structs + bool packedUnsup() const { + return true; + } // packed() but as don't support unpacked, presently all structs void isFourstate(bool flag) { m_isFourstate = flag; } virtual bool isFourstate() const { return m_isFourstate; } void clearCache() { m_members.clear(); } void repairMemberCache(); AstMemberDType* findMember(const string& name) const { MemberNameMap::const_iterator it = m_members.find(name); - return (it==m_members.end()) ? NULL : it->second; + return (it == m_members.end()) ? NULL : it->second; } int lsb() const { return 0; } - int msb() const { return dtypep()->width()-1; } // Packed classes look like arrays + int msb() const { return dtypep()->width() - 1; } // Packed classes look like arrays VNumRange declRange() const { return VNumRange(msb(), lsb(), false); } }; @@ -2163,26 +2391,30 @@ public: virtual void dumpSmall(std::ostream& str) const; virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) - || (!m_refDTypep && childDTypep()))); return NULL; } - virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) { - m_refDTypep = m_refDTypep->clonep(); - }} + || (!m_refDTypep && childDTypep()))); + return NULL; + } + virtual void cloneRelink() { + if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } + } virtual bool same(const AstNode* samep) const { const AstNodeArrayDType* asamep = static_cast(samep); - return (msb()==asamep->msb() - && subDTypep()==asamep->subDTypep() - && rangenp()->sameTree(asamep->rangenp())); } // HashedDT doesn't recurse, so need to check children + return (msb() == asamep->msb() && subDTypep() == asamep->subDTypep() + && rangenp()->sameTree(asamep->rangenp())); + } // HashedDT doesn't recurse, so need to check children virtual bool similarDType(AstNodeDType* samep) const { const AstNodeArrayDType* asamep = static_cast(samep); - return (asamep - && type() == samep->type() - && msb() == asamep->msb() + return (asamep && type() == samep->type() && msb() == asamep->msb() && rangenp()->sameTree(asamep->rangenp()) && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); } - virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_refDTypep), V3Hash(msb()), V3Hash(lsb())); } + virtual V3Hash sameHash() const { + return V3Hash(V3Hash(m_refDTypep), V3Hash(msb()), V3Hash(lsb())); + } AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable + AstNodeDType* childDTypep() const { + return VN_CAST(op1p(), NodeDType); + } // op1 = Range of variable void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } @@ -2191,12 +2423,16 @@ public: AstRange* rangep() const { return VN_CAST(op2p(), Range); } // op2 = Array(s) of variable void rangep(AstRange* nodep); // METHODS - virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type + virtual AstBasicDType* basicp() const { + return subDTypep()->basicp(); + } // (Slow) recurse down to find basic data type virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const { return elementsConst() * subDTypep()->widthTotalBytes(); } + virtual int widthTotalBytes() const { + return elementsConst() * subDTypep()->widthTotalBytes(); + } int msb() const; int lsb() const; int elementsConst() const; @@ -2222,9 +2458,7 @@ class AstNodeStream : public AstNodeBiop { public: AstNodeStream(AstType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(t, fl, lhsp, rhsp) { - if (lhsp->dtypep()) { - dtypeSetLogicSized(lhsp->dtypep()->width(), AstNumeric::UNSIGNED); - } + if (lhsp->dtypep()) { dtypeSetLogicSized(lhsp->dtypep()->width(), AstNumeric::UNSIGNED); } } ASTNODE_BASE_FUNCS(NodeStream) }; @@ -2238,6 +2472,7 @@ class AstNodeCCall : public AstNodeStmt { AstCFunc* m_funcp; string m_hiername; string m_argTypes; + public: AstNodeCCall(AstType t, FileLine* fl, AstCFunc* funcp, AstNode* argsp = NULL) : AstNodeStmt(t, fl, true) @@ -2255,7 +2490,7 @@ public: if (oldp->argsp()) addNOp2p(oldp->argsp()->unlinkFrBackWithNext()); } ASTNODE_BASE_FUNCS(NodeCCall) - virtual void dump(std::ostream& str=std::cout) const; + virtual void dump(std::ostream& str = std::cout) const; virtual void cloneRelink(); virtual const char* broken() const; virtual int instrCount() const { return instrCountCall(); } @@ -2282,33 +2517,41 @@ public: class AstNodeFTask : public AstNode { private: - string m_name; // Name of task - string m_cname; // Name of task if DPI import - uint64_t m_dpiOpenParent; // DPI import open array, if !=0, how many callees - bool m_taskPublic:1; // Public task - bool m_attrIsolateAssign:1;// User isolate_assignments attribute - bool m_classMethod:1; // Class method - bool m_prototype:1; // Just a prototype - bool m_dpiExport:1; // DPI exported - bool m_dpiImport:1; // DPI imported - bool m_dpiContext:1; // DPI import context - bool m_dpiOpenChild:1; // DPI import open array child wrapper - bool m_dpiTask:1; // DPI import task (vs. void function) - bool m_isConstructor:1; // Class constructor - bool m_pure:1; // DPI import pure (vs. virtual pure) + string m_name; // Name of task + string m_cname; // Name of task if DPI import + uint64_t m_dpiOpenParent; // DPI import open array, if !=0, how many callees + bool m_taskPublic : 1; // Public task + bool m_attrIsolateAssign : 1; // User isolate_assignments attribute + bool m_classMethod : 1; // Class method + bool m_prototype : 1; // Just a prototype + bool m_dpiExport : 1; // DPI exported + bool m_dpiImport : 1; // DPI imported + bool m_dpiContext : 1; // DPI import context + bool m_dpiOpenChild : 1; // DPI import open array child wrapper + bool m_dpiTask : 1; // DPI import task (vs. void function) + bool m_isConstructor : 1; // Class constructor + bool m_pure : 1; // DPI import pure (vs. virtual pure) public: AstNodeFTask(AstType t, FileLine* fl, const string& name, AstNode* stmtsp) : AstNode(t, fl) , m_name(name) - , m_dpiOpenParent(0), m_taskPublic(false) - , m_attrIsolateAssign(false), m_classMethod(false), m_prototype(false) - , m_dpiExport(false), m_dpiImport(false), m_dpiContext(false) - , m_dpiOpenChild(false), m_dpiTask(false), m_isConstructor(false), m_pure(false) { + , m_dpiOpenParent(0) + , m_taskPublic(false) + , m_attrIsolateAssign(false) + , m_classMethod(false) + , m_prototype(false) + , m_dpiExport(false) + , m_dpiImport(false) + , m_dpiContext(false) + , m_dpiOpenChild(false) + , m_dpiTask(false) + , m_isConstructor(false) + , m_pure(false) { addNOp3p(stmtsp); cname(name); // Might be overridden by dpi import/export } ASTNODE_BASE_FUNCS(NodeFTask) - virtual void dump(std::ostream& str=std::cout) const; + virtual void dump(std::ostream& str = std::cout) const; virtual string name() const { return m_name; } // * = Var name virtual bool maybePointedTo() const { return true; } virtual bool isGateOptimizable() const { return !((m_dpiExport || m_dpiImport) && !m_pure); } @@ -2319,7 +2562,7 @@ public: // op1 = Output variable (functions only, NULL for tasks) AstNode* fvarp() const { return op1p(); } void addFvarp(AstNode* nodep) { addNOp1p(nodep); } - bool isFunction() const { return fvarp()!=NULL; } + bool isFunction() const { return fvarp() != NULL; } // op3 = Statements/Ports/Vars AstNode* stmtsp() const { return op3p(); } // op3 = List of statements void addStmtsp(AstNode* nodep) { addNOp3p(nodep); } @@ -2358,28 +2601,35 @@ class AstNodeFTaskRef : public AstNodeStmt { // A reference to a task (or function) // Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal. private: - AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced - string m_name; // Name of variable - string m_dotted; // Dotted part of scope the name()ed task/func is under or "" - string m_inlinedDots; // Dotted hierarchy flattened out + AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced + string m_name; // Name of variable + string m_dotted; // Dotted part of scope the name()ed task/func is under or "" + string m_inlinedDots; // Dotted hierarchy flattened out AstNodeModule* m_packagep; // Package hierarchy public: AstNodeFTaskRef(AstType t, FileLine* fl, bool statement, AstNode* namep, AstNode* pinsp) : AstNodeStmt(t, fl, statement) - , m_taskp(NULL), m_packagep(NULL) { - setOp1p(namep); addNOp3p(pinsp); + , m_taskp(NULL) + , m_packagep(NULL) { + setOp1p(namep); + addNOp3p(pinsp); } AstNodeFTaskRef(AstType t, FileLine* fl, bool statement, const string& name, AstNode* pinsp) : AstNodeStmt(t, fl, statement) - , m_taskp(NULL), m_name(name), m_packagep(NULL) { + , m_taskp(NULL) + , m_name(name) + , m_packagep(NULL) { addNOp3p(pinsp); } ASTNODE_BASE_FUNCS(NodeFTaskRef) - virtual const char* broken() const { BROKEN_RTN(m_taskp && !m_taskp->brokeExists()); return NULL; } - virtual void cloneRelink() { if (m_taskp && m_taskp->clonep()) { - m_taskp = m_taskp->clonep(); - }} - virtual void dump(std::ostream& str=std::cout) const; + virtual const char* broken() const { + BROKEN_RTN(m_taskp && !m_taskp->brokeExists()); + return NULL; + } + virtual void cloneRelink() { + if (m_taskp && m_taskp->clonep()) { m_taskp = m_taskp->clonep(); } + } + virtual void dump(std::ostream& str = std::cout) const; virtual string name() const { return m_name; } // * = Var name virtual bool isGateOptimizable() const { return m_taskp && m_taskp->isGateOptimizable(); } string dotted() const { return m_dotted; } // * = Scope name or "" @@ -2408,27 +2658,35 @@ class AstNodeModule : public AstNode { // something that can live directly under the TOP, // excluding $unit package stuff private: - string m_name; // Name of the module - string m_origName; // Name of the module, ignoring name() changes, for dot lookup - string m_hierName; // Hierarchical name for errors, etc. - bool m_modPublic:1; // Module has public references - bool m_modTrace:1; // Tracing this module - bool m_inLibrary:1; // From a library, no error if not used, never top level - bool m_dead:1; // LinkDot believes is dead; will remove in Dead visitors - bool m_internal:1; // Internally created - bool m_recursive:1; // Recursive module - bool m_recursiveClone:1; // If recursive, what module it clones, otherwise NULL - int m_level; // 1=top module, 2=cell off top module, ... - int m_varNum; // Incrementing variable number - int m_typeNum; // Incrementing implicit type number + string m_name; // Name of the module + string m_origName; // Name of the module, ignoring name() changes, for dot lookup + string m_hierName; // Hierarchical name for errors, etc. + bool m_modPublic : 1; // Module has public references + bool m_modTrace : 1; // Tracing this module + bool m_inLibrary : 1; // From a library, no error if not used, never top level + bool m_dead : 1; // LinkDot believes is dead; will remove in Dead visitors + bool m_internal : 1; // Internally created + bool m_recursive : 1; // Recursive module + bool m_recursiveClone : 1; // If recursive, what module it clones, otherwise NULL + int m_level; // 1=top module, 2=cell off top module, ... + int m_varNum; // Incrementing variable number + int m_typeNum; // Incrementing implicit type number VOptionBool m_unconnectedDrive; // State of `unconnected_drive public: AstNodeModule(AstType t, FileLine* fl, const string& name) : AstNode(t, fl) - , m_name(name), m_origName(name) - , m_modPublic(false), m_modTrace(false), m_inLibrary(false), m_dead(false) - , m_internal(false), m_recursive(false), m_recursiveClone(false) - , m_level(0), m_varNum(0), m_typeNum(0) { } + , m_name(name) + , m_origName(name) + , m_modPublic(false) + , m_modTrace(false) + , m_inLibrary(false) + , m_dead(false) + , m_internal(false) + , m_recursive(false) + , m_recursiveClone(false) + , m_level(0) + , m_varNum(0) + , m_typeNum(0) {} ASTNODE_BASE_FUNCS(NodeModule) virtual void dump(std::ostream& str) const; virtual bool maybePointedTo() const { return true; } @@ -2442,13 +2700,13 @@ public: // ACCESSORS virtual void name(const string& name) { m_name = name; } virtual string origName() const { return m_origName; } - string hierName() const { return m_hierName; } + string hierName() const { return m_hierName; } void hierName(const string& hierName) { m_hierName = hierName; } bool inLibrary() const { return m_inLibrary; } void inLibrary(bool flag) { m_inLibrary = flag; } void level(int level) { m_level = level; } int level() const { return m_level; } - bool isTop() const { return level()==1; } + bool isTop() const { return level() == 1; } int varNumGetInc() { return ++m_varNum; } int typeNumGetInc() { return ++m_typeNum; } void modPublic(bool flag) { m_modPublic = flag; } @@ -2482,12 +2740,8 @@ public: //###################################################################### // Inline AstNVisitor METHODS -inline void AstNVisitor::iterate(AstNode* nodep) { - nodep->accept(*this); -} -inline void AstNVisitor::iterateChildren(AstNode* nodep) { - nodep->iterateChildren(*this); -} +inline void AstNVisitor::iterate(AstNode* nodep) { nodep->accept(*this); } +inline void AstNVisitor::iterateChildren(AstNode* nodep) { nodep->iterateChildren(*this); } inline void AstNVisitor::iterateChildrenBackwards(AstNode* nodep) { nodep->iterateChildrenBackwards(*this); } @@ -2510,27 +2764,44 @@ inline AstNode* AstNVisitor::iterateSubtreeReturnEdits(AstNode* nodep) { inline int AstNode::width() const { return dtypep() ? dtypep()->width() : 0; } inline int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() : 0; } inline bool AstNode::width1() const { // V3Const uses to know it can optimize - return dtypep() && dtypep()->width()==1; } + return dtypep() && dtypep()->width() == 1; +} inline int AstNode::widthInstrs() const { - return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1)); } + return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1)); +} inline bool AstNode::isDouble() const { - return dtypep() && VN_IS(dtypep(), BasicDType) && VN_CAST(dtypep(), BasicDType)->isDouble(); } + return dtypep() && VN_IS(dtypep(), BasicDType) && VN_CAST(dtypep(), BasicDType)->isDouble(); +} inline bool AstNode::isString() const { - return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString(); } -inline bool AstNode::isSigned() const { - return dtypep() && dtypep()->isSigned(); } + return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString(); +} +inline bool AstNode::isSigned() const { return dtypep() && dtypep()->isSigned(); } -inline bool AstNode::isZero() const { return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->num().isEqZero()); } -inline bool AstNode::isNeqZero() const { return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->num().isNeqZero()); } -inline bool AstNode::isOne() const { return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->num().isEqOne()); } -inline bool AstNode::isAllOnes() const { return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->isEqAllOnes()); } -inline bool AstNode::isAllOnesV() const { return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->isEqAllOnesV()); } +inline bool AstNode::isZero() const { + return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->num().isEqZero()); +} +inline bool AstNode::isNeqZero() const { + return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->num().isNeqZero()); +} +inline bool AstNode::isOne() const { + return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->num().isEqOne()); +} +inline bool AstNode::isAllOnes() const { + return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->isEqAllOnes()); +} +inline bool AstNode::isAllOnesV() const { + return (VN_IS(this, Const) && VN_CAST_CONST(this, Const)->isEqAllOnesV()); +} inline bool AstNode::sameTree(const AstNode* node2p) const { - return sameTreeIter(this, node2p, true, false); } + return sameTreeIter(this, node2p, true, false); +} inline bool AstNode::sameGateTree(const AstNode* node2p) const { - return sameTreeIter(this, node2p, true, true); } + return sameTreeIter(this, node2p, true, true); +} -inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); } +inline void AstNodeVarRef::init() { + if (m_varp) dtypep(m_varp->dtypep()); +} inline bool AstNodeDType::isFourstate() const { return basicp()->isFourstate(); } @@ -2538,11 +2809,14 @@ inline void AstNodeArrayDType::rangep(AstRange* nodep) { setOp2p(nodep); } inline int AstNodeArrayDType::msb() const { return rangep()->msbConst(); } inline int AstNodeArrayDType::lsb() const { return rangep()->lsbConst(); } inline int AstNodeArrayDType::elementsConst() const { return rangep()->elementsConst(); } -inline VNumRange AstNodeArrayDType::declRange() const { return VNumRange(msb(), lsb(), rangep()->littleEndian()); } +inline VNumRange AstNodeArrayDType::declRange() const { + return VNumRange(msb(), lsb(), rangep()->littleEndian()); +} inline void AstIfaceRefDType::cloneRelink() { if (m_cellp && m_cellp->clonep()) m_cellp = m_cellp->clonep(); if (m_ifacep && m_ifacep->clonep()) m_ifacep = m_ifacep->clonep(); - if (m_modportp && m_modportp->clonep()) m_modportp = m_modportp->clonep(); } + if (m_modportp && m_modportp->clonep()) m_modportp = m_modportp->clonep(); +} #endif // Guard diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index a46a7258d..4ca1f3646 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -64,21 +64,23 @@ int AstNodeSel::bitConst() const { void AstNodeUOrStructDType::repairMemberCache() { clearCache(); - for (AstMemberDType* itemp = membersp(); itemp; itemp=VN_CAST(itemp->nextp(), MemberDType)) { - if (m_members.find(itemp->name())!=m_members.end()) { - itemp->v3error("Duplicate declaration of member name: "<prettyNameQ()); } - else m_members.insert(make_pair(itemp->name(), itemp)); + for (AstMemberDType* itemp = membersp(); itemp; itemp = VN_CAST(itemp->nextp(), MemberDType)) { + if (m_members.find(itemp->name()) != m_members.end()) { + itemp->v3error("Duplicate declaration of member name: " << itemp->prettyNameQ()); + } else { + m_members.insert(make_pair(itemp->name(), itemp)); + } } } const char* AstNodeUOrStructDType::broken() const { vl_unordered_set exists; - for (AstMemberDType* itemp = membersp(); itemp; itemp=VN_CAST(itemp->nextp(), MemberDType)) { + for (AstMemberDType* itemp = membersp(); itemp; itemp = VN_CAST(itemp->nextp(), MemberDType)) { exists.insert(itemp); } - for (MemberNameMap::const_iterator it=m_members.begin(); it!=m_members.end(); ++it) { + for (MemberNameMap::const_iterator it = m_members.begin(); it != m_members.end(); ++it) { if (VL_UNCOVERABLE(exists.find(it->second) == exists.end())) { - this->v3error("Internal: Structure member broken: "<first); + this->v3error("Internal: Structure member broken: " << it->first); return "member broken"; } } @@ -106,39 +108,62 @@ string AstNodeCCall::hiernameProtect() const { return VIdProtect::protectWordsIf(hiername(), protect()); } -void AstNodeCond::numberOperate(V3Number& out, const V3Number& lhs, - const V3Number& rhs, const V3Number& ths) { - if (lhs.isNeqZero()) out.opAssign(rhs); else out.opAssign(ths); +void AstNodeCond::numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) { + if (lhs.isNeqZero()) + out.opAssign(rhs); + else + out.opAssign(ths); } int AstBasicDType::widthAlignBytes() const { - if (width()<=8) return 1; - else if (width()<=16) return 2; - else if (isQuad()) return 8; - else return 4; + if (width() <= 8) { + return 1; + } else if (width() <= 16) { + return 2; + } else if (isQuad()) { + return 8; + } else { + return 4; + } } int AstBasicDType::widthTotalBytes() const { - if (width()<=8) return 1; - else if (width()<=16) return 2; - else if (isQuad()) return 8; - else return widthWords() * (VL_EDATASIZE / 8); + if (width() <= 8) { + return 1; + } else if (width() <= 16) { + return 2; + } else if (isQuad()) { + return 8; + } else { + return widthWords() * (VL_EDATASIZE / 8); + } } int AstNodeUOrStructDType::widthTotalBytes() const { - if (width()<=8) return 1; - else if (width()<=16) return 2; - else if (isQuad()) return 8; - else return widthWords() * (VL_EDATASIZE / 8); + if (width() <= 8) { + return 1; + } else if (width() <= 16) { + return 2; + } else if (isQuad()) { + return 8; + } else { + return widthWords() * (VL_EDATASIZE / 8); + } } int AstNodeUOrStructDType::widthAlignBytes() const { // Could do max across members but that would be slow, // instead intuit based on total structure size - if (width()<=8) return 1; - else if (width()<=16) return 2; - else if (width()<=32) return 4; - else return 8; + if (width() <= 8) { + return 1; + } else if (width() <= 16) { + return 2; + } else if (width() <= 32) { + return 4; + } else { + return 8; + } } AstNodeBiop* AstEq::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) { @@ -189,9 +214,7 @@ AstExecGraph::AstExecGraph(FileLine* fileline) : AstNode(AstType::atExecGraph, fileline) { m_depGraphp = new V3Graph; } -AstExecGraph::~AstExecGraph() { - VL_DO_DANGLING(delete m_depGraphp, m_depGraphp); -} +AstExecGraph::~AstExecGraph() { VL_DO_DANGLING(delete m_depGraphp, m_depGraphp); } AstNode* AstInsideRange::newAndFromInside(AstNode* exprp, AstNode* lhsp, AstNode* rhsp) { AstNode* ap = new AstGte(fileline(), exprp->cloneTree(true), lhsp); @@ -205,19 +228,16 @@ AstNode* AstInsideRange::newAndFromInside(AstNode* exprp, AstNode* lhsp, AstNode bool AstVar::isSigPublic() const { return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar())); } -bool AstVar::isScQuad() const { - return (isSc() && isQuad() && !isScBv() && !isScBigUint()); -} +bool AstVar::isScQuad() const { return (isSc() && isQuad() && !isScBv() && !isScBigUint()); } bool AstVar::isScBv() const { return ((isSc() && width() >= v3Global.opt.pinsBv()) || m_attrScBv); } bool AstVar::isScUint() const { - return ((isSc() && v3Global.opt.pinsScUint() - && width() >= 2 && width() <= 64) && !isScBv()); + return ((isSc() && v3Global.opt.pinsScUint() && width() >= 2 && width() <= 64) && !isScBv()); } bool AstVar::isScBigUint() const { - return ((isSc() && v3Global.opt.pinsScBigUint() - && width() >= 65 && width() <= 512) && !isScBv()); + return ((isSc() && v3Global.opt.pinsScBigUint() && width() >= 65 && width() <= 512) + && !isScBv()); } void AstVar::combineType(AstVarType type) { @@ -226,15 +246,11 @@ void AstVar::combineType(AstVarType type) { // when we combine wires cross-hierarchy we need a union of all characteristics. m_varType = type; // These flags get combined with the existing settings of the flags. - if (type==AstVarType::TRIWIRE || type==AstVarType::TRI0 || type==AstVarType::TRI1) { + if (type == AstVarType::TRIWIRE || type == AstVarType::TRI0 || type == AstVarType::TRI1) { m_tristate = true; } - if (type==AstVarType::TRI0) { - m_isPulldown = true; - } - if (type==AstVarType::TRI1) { - m_isPullup = true; - } + if (type == AstVarType::TRI0) m_isPulldown = true; + if (type == AstVarType::TRI1) m_isPullup = true; } string AstVar::verilogKwd() const { @@ -242,11 +258,11 @@ string AstVar::verilogKwd() const { return direction().verilogKwd(); } else if (isTristate()) { return "tri"; - } else if (varType()==AstVarType::WIRE) { + } else if (varType() == AstVarType::WIRE) { return "wire"; - } else if (varType()==AstVarType::WREAL) { + } else if (varType() == AstVarType::WREAL) { return "wreal"; - } else if (varType()==AstVarType::IFACEREF) { + } else if (varType() == AstVarType::IFACEREF) { return "ifaceref"; } else { return dtypep()->name(); @@ -264,7 +280,7 @@ public: m_oprefix.clear(); } string refParen(const string& name) { - return m_oref.empty() ? name : "("+m_oref+" "+name+")"; + return m_oref.empty() ? name : "(" + m_oref + " " + name + ")"; } }; @@ -279,7 +295,7 @@ string AstVar::vlArgType(bool named, bool forReturn, bool forFunc, const string& string oname; if (named) { oname += " "; - if (!namespc.empty()) oname += namespc+"::"; + if (!namespc.empty()) oname += namespc + "::"; oname += VIdProtect::protectIf(name(), protect()); } return ostatic + info.m_oprefix + info.refParen(oname) + info.m_osuffix; @@ -344,11 +360,11 @@ AstVar::VlArgTypeRecursed AstVar::vlArgTypeRecurse(bool forFunc, const AstNodeDT if (!bdtypep->isOpaque() && !v3Global.opt.protectIds()) { // We don't print msb()/lsb() as multidim packed would require recursion, // and may confuse users as C++ data is stored always with bit 0 used - bitvec += "/*"+cvtToStr(dtypep->width()-1)+":0*/"; + bitvec += "/*" + cvtToStr(dtypep->width() - 1) + ":0*/"; } - if ((forFunc && isReadOnly()) - || bdtypep->keyword() == AstBasicDTypeKwd::CHARPTR - || bdtypep->keyword() == AstBasicDTypeKwd::SCOPEPTR) otype += "const "; + if ((forFunc && isReadOnly()) || bdtypep->keyword() == AstBasicDTypeKwd::CHARPTR + || bdtypep->keyword() == AstBasicDTypeKwd::SCOPEPTR) + otype += "const "; if (bdtypep->keyword() == AstBasicDTypeKwd::CHARPTR) { otype += "char*"; } else if (bdtypep->keyword() == AstBasicDTypeKwd::SCOPEPTR) { @@ -360,28 +376,27 @@ AstVar::VlArgTypeRecursed AstVar::vlArgTypeRecurse(bool forFunc, const AstNodeDT } else if (strtype) { otype += "std::string"; } else if (dtypep->widthMin() <= 8) { // Handle unpacked arrays; not bdtypep->width - otype += "CData"+bitvec; + otype += "CData" + bitvec; } else if (dtypep->widthMin() <= 16) { - otype += "SData"+bitvec; + otype += "SData" + bitvec; } else if (dtypep->widthMin() <= VL_IDATASIZE) { - otype += "IData"+bitvec; + otype += "IData" + bitvec; } else if (dtypep->isQuad()) { - otype += "QData"+bitvec; + otype += "QData" + bitvec; } else if (dtypep->isWide()) { if (arrayed) { - otype += "VlWide<"+cvtToStr(dtypep->widthWords())+"> "; + otype += "VlWide<" + cvtToStr(dtypep->widthWords()) + "> "; } else { - otype += "WData"+bitvec; // []'s added later - oarray += "["+cvtToStr(dtypep->widthWords())+"]"; + otype += "WData" + bitvec; // []'s added later + oarray += "[" + cvtToStr(dtypep->widthWords()) + "]"; } } string oref; if (isDpiOpenArray() - || (forFunc && (isWritable() - || direction() == VDirection::REF - || direction() == VDirection::CONSTREF - || (strtype && isNonOutput())))) { + || (forFunc + && (isWritable() || direction() == VDirection::REF + || direction() == VDirection::CONSTREF || (strtype && isNonOutput())))) { oref = "&"; } @@ -389,21 +404,21 @@ AstVar::VlArgTypeRecursed AstVar::vlArgTypeRecurse(bool forFunc, const AstNodeDT info.m_oprefix = otype; info.m_osuffix = oarray; info.m_oref = oref; - //UINFO(9, "vlArgRec "<<"oprefix="<prettyName()); + v3fatalSrc("Unknown data type in var type emitter: " << dtypep->prettyName()); } } string AstVar::vlEnumType() const { string arg; AstBasicDType* bdtypep = basicp(); - bool strtype = bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::STRING; - if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::CHARPTR) { + bool strtype = bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::STRING; + if (bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::CHARPTR) { return "VLVT_PTR"; - } else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) { + } else if (bdtypep && bdtypep->keyword() == AstBasicDTypeKwd::SCOPEPTR) { return "VLVT_PTR"; } else if (strtype) { arg += "VLVT_STRING"; @@ -434,8 +449,11 @@ string AstVar::vlEnumDir() const { out = "VLVD_NODIR"; } // - if (isSigUserRWPublic()) out += "|VLVF_PUB_RW"; - else if (isSigUserRdPublic()) out += "|VLVF_PUB_RD"; + if (isSigUserRWPublic()) { + out += "|VLVF_PUB_RW"; + } else if (isSigUserRdPublic()) { + out += "|VLVF_PUB_RD"; + } // if (AstBasicDType* bdtypep = basicp()) { if (bdtypep->keyword().isDpiCLayout()) out += "|VLVF_DPI_CLAY"; @@ -446,23 +464,25 @@ string AstVar::vlEnumDir() const { string AstVar::vlPropInit() const { string out; out = vlEnumType(); // VLVT_UINT32 etc - out += ", "+vlEnumDir(); // VLVD_IN etc + out += ", " + vlEnumDir(); // VLVD_IN etc if (AstBasicDType* bdtypep = basicp()) { out += ", VerilatedVarProps::Packed()"; - out += ", "+cvtToStr(bdtypep->left())+", "+cvtToStr(bdtypep->right()); + out += ", " + cvtToStr(bdtypep->left()) + ", " + cvtToStr(bdtypep->right()); } bool first = true; - for (AstNodeDType* dtp=dtypep(); dtp; ) { + for (AstNodeDType* dtp = dtypep(); dtp;) { dtp = dtp->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node if (AstNodeArrayDType* adtypep = VN_CAST(dtp, NodeArrayDType)) { if (first) { out += ", VerilatedVarProps::Unpacked()"; first = false; } - out += ", "+cvtToStr(adtypep->declRange().left())+", "+cvtToStr(adtypep->declRange().right()); + out += ", " + cvtToStr(adtypep->declRange().left()) + ", " + + cvtToStr(adtypep->declRange().right()); dtp = adtypep->subDTypep(); + } else { + break; // AstBasicDType - nothing below } - else break; // AstBasicDType - nothing below } return out; } @@ -481,13 +501,15 @@ string AstVar::cPubArgType(bool named, bool forReturn) const { arg += "uint32_t"; // []'s added later } if (isWide()) { - if (forReturn) v3error("Unsupported: Public functions with >64 bit outputs; make an output of a public task instead"); - arg += " (& "+name(); - arg += ")["+cvtToStr(widthWords())+"]"; + if (forReturn) { + v3error("Unsupported: Public functions with >64 bit outputs; " + "make an output of a public task instead"); + } + arg += " (& " + name(); + arg += ")[" + cvtToStr(widthWords()) + "]"; } else { - if (!forReturn && (isWritable() - || direction().isRefOrConstRef())) arg += "&"; - if (named) arg += " "+name(); + if (!forReturn && (isWritable() || direction().isRefOrConstRef())) arg += "&"; + if (named) arg += " " + name(); } return arg; } @@ -518,21 +540,23 @@ string AstVar::dpiArgType(bool named, bool forReturn) const { } else { arg = basicp()->keyword().dpiType(); if (basicp()->keyword().isDpiUnsignable() && !basicp()->isSigned()) { - arg = "unsigned "+arg; + arg = "unsigned " + arg; } if (!forReturn && isWritable()) arg += "*"; } - if (named) arg += " "+name(); + if (named) arg += " " + name(); return arg; } string AstVar::scType() const { if (isScBigUint()) { - return (string("sc_biguint<")+cvtToStr(widthMin())+"> "); // Keep the space so don't get >> + return (string("sc_biguint<") + cvtToStr(widthMin()) + + "> "); // Keep the space so don't get >> } else if (isScUint()) { - return (string("sc_uint<")+cvtToStr(widthMin())+"> "); // Keep the space so don't get >> + return (string("sc_uint<") + cvtToStr(widthMin()) + + "> "); // Keep the space so don't get >> } else if (isScBv()) { - return (string("sc_bv<")+cvtToStr(widthMin())+"> "); // Keep the space so don't get >> + return (string("sc_bv<") + cvtToStr(widthMin()) + "> "); // Keep the space so don't get >> } else if (widthMin() == 1) { return "bool"; } else if (widthMin() <= VL_IDATASIZE) { @@ -553,28 +577,39 @@ AstVar* AstVar::scVarRecurse(AstNode* nodep) { // Historically sc variables are identified by a variable // attribute. TODO it would better be a data type attribute. if (AstVar* anodep = VN_CAST(nodep, Var)) { - if (anodep->isSc()) return anodep; - else return NULL; - } - else if (VN_IS(nodep, VarRef)) { - if (VN_CAST(nodep, VarRef)->varp()->isSc()) return VN_CAST(nodep, VarRef)->varp(); - else return NULL; - } - else if (VN_IS(nodep, ArraySel)) { - if (nodep->op1p()) if (AstVar* p = scVarRecurse(nodep->op1p())) return p; - if (nodep->op2p()) if (AstVar* p = scVarRecurse(nodep->op2p())) return p; - if (nodep->op3p()) if (AstVar* p = scVarRecurse(nodep->op3p())) return p; - if (nodep->op4p()) if (AstVar* p = scVarRecurse(nodep->op4p())) return p; + if (anodep->isSc()) { + return anodep; + } else { + return NULL; + } + } else if (VN_IS(nodep, VarRef)) { + if (VN_CAST(nodep, VarRef)->varp()->isSc()) { + return VN_CAST(nodep, VarRef)->varp(); + } else { + return NULL; + } + } else if (VN_IS(nodep, ArraySel)) { + if (nodep->op1p()) { + if (AstVar* p = scVarRecurse(nodep->op1p())) return p; + } + if (nodep->op2p()) { + if (AstVar* p = scVarRecurse(nodep->op2p())) return p; + } + if (nodep->op3p()) { + if (AstVar* p = scVarRecurse(nodep->op3p())) return p; + } + if (nodep->op4p()) { + if (AstVar* p = scVarRecurse(nodep->op4p())) return p; + } } return NULL; } string AstVar::mtasksString() const { std::ostringstream os; - os<<"all: "; - for (MTaskIdSet::const_iterator it = m_mtaskIds.begin(); - it != m_mtaskIds.end(); ++it) { - os<<*it<<" "; + os << "all: "; + for (MTaskIdSet::const_iterator it = m_mtaskIds.begin(); it != m_mtaskIds.end(); ++it) { + os << *it << " "; } return os.str(); } @@ -594,29 +629,21 @@ AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) { // TODO this function should be removed in favor of recursing the dtype(), // as that allows for more complicated data types. int dim = 0; - for (AstNodeDType* dtypep=this; dtypep; ) { + for (AstNodeDType* dtypep = this; dtypep;) { dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node if (AstNodeArrayDType* adtypep = VN_CAST(dtypep, NodeArrayDType)) { - if ((dim++)==dimension) { - return dtypep; - } + if ((dim++) == dimension) return dtypep; dtypep = adtypep->subDTypep(); continue; - } - else if (AstBasicDType* adtypep = VN_CAST(dtypep, BasicDType)) { + } else if (AstBasicDType* adtypep = VN_CAST(dtypep, BasicDType)) { // AstBasicDType - nothing below, return null if (adtypep->isRanged()) { - if ((dim++) == dimension) { - return adtypep; - } + if ((dim++) == dimension) return adtypep; } return NULL; - } - else if (AstNodeUOrStructDType* adtypep = VN_CAST(dtypep, NodeUOrStructDType)) { + } else if (AstNodeUOrStructDType* adtypep = VN_CAST(dtypep, NodeUOrStructDType)) { if (adtypep->packed()) { - if ((dim++) == dimension) { - return adtypep; - } + if ((dim++) == dimension) return adtypep; } return NULL; } @@ -628,13 +655,12 @@ AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) { uint32_t AstNodeDType::arrayUnpackedElements() { uint32_t entries = 1; - for (AstNodeDType* dtypep=this; dtypep; ) { + for (AstNodeDType* dtypep = this; dtypep;) { dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) { entries *= adtypep->elementsConst(); dtypep = adtypep->subDTypep(); - } - else { + } else { // AstBasicDType - nothing below, 1 break; } @@ -642,27 +668,27 @@ uint32_t AstNodeDType::arrayUnpackedElements() { return entries; } -std::pair AstNodeDType::dimensions(bool includeBasic) { +std::pair AstNodeDType::dimensions(bool includeBasic) { // How many array dimensions (packed,unpacked) does this Var have? uint32_t packed = 0; uint32_t unpacked = 0; - for (AstNodeDType* dtypep=this; dtypep; ) { + for (AstNodeDType* dtypep = this; dtypep;) { dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node if (const AstNodeArrayDType* adtypep = VN_CAST(dtypep, NodeArrayDType)) { - if (VN_IS(adtypep, PackArrayDType)) packed++; - else unpacked++; + if (VN_IS(adtypep, PackArrayDType)) { + ++packed; + } else { + ++unpacked; + } dtypep = adtypep->subDTypep(); continue; - } - else if (const AstQueueDType* qdtypep = VN_CAST(dtypep, QueueDType)) { + } else if (const AstQueueDType* qdtypep = VN_CAST(dtypep, QueueDType)) { unpacked++; dtypep = qdtypep->subDTypep(); continue; - } - else if (const AstBasicDType* adtypep = VN_CAST(dtypep, BasicDType)) { + } else if (const AstBasicDType* adtypep = VN_CAST(dtypep, BasicDType)) { if (includeBasic && (adtypep->isRanged() || adtypep->isString())) packed++; - } - else if (VN_IS(dtypep, StructDType)) { + } else if (VN_IS(dtypep, StructDType)) { packed++; } break; @@ -673,29 +699,38 @@ std::pair AstNodeDType::dimensions(bool includeBasic) { int AstNodeDType::widthPow2() const { // I.e. width 30 returns 32, width 32 returns 32. uint32_t width = this->width(); - for (int p2=30; p2>=0; p2--) { - if (width > (1UL<= 0; p2--) { + if (width > (1UL << p2)) return (1UL << (p2 + 1)); } return 1; } -AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variable (or const) this dereferences? +/// What is the base variable (or const) this dereferences? +AstNode* AstArraySel::baseFromp(AstNode* nodep) { // Else AstArraySel etc; search for the base while (nodep) { - if (VN_IS(nodep, ArraySel)) { nodep = VN_CAST(nodep, ArraySel)->fromp(); continue; } - else if (VN_IS(nodep, Sel)) { nodep = VN_CAST(nodep, Sel)->fromp(); continue; } + if (VN_IS(nodep, ArraySel)) { + nodep = VN_CAST(nodep, ArraySel)->fromp(); + continue; + } else if (VN_IS(nodep, Sel)) { + nodep = VN_CAST(nodep, Sel)->fromp(); + continue; + } // AstNodeSelPre stashes the associated variable under an ATTROF // of AstAttrType::VAR_BASE/MEMBER_BASE so it isn't constified - else if (VN_IS(nodep, AttrOf)) { nodep = VN_CAST(nodep, AttrOf)->fromp(); continue; } - else if (VN_IS(nodep, NodePreSel)) { + else if (VN_IS(nodep, AttrOf)) { + nodep = VN_CAST(nodep, AttrOf)->fromp(); + continue; + } else if (VN_IS(nodep, NodePreSel)) { if (VN_CAST(nodep, NodePreSel)->attrp()) { nodep = VN_CAST(nodep, NodePreSel)->attrp(); } else { nodep = VN_CAST(nodep, NodePreSel)->lhsp(); } continue; + } else { + break; } - else break; } return nodep; } @@ -719,15 +754,13 @@ void AstScope::cloneRelink() { string AstScope::nameDotless() const { string out = shortName(); string::size_type pos; - while ((pos = out.find('.')) != string::npos) { - out.replace(pos, 1, "__"); - } + while ((pos = out.find('.')) != string::npos) out.replace(pos, 1, "__"); return out; } string AstScopeName::scopePrettyNameFormatter(AstText* scopeTextp) const { string out; - for (AstText* textp=scopeTextp; textp; textp=VN_CAST(textp->nextp(), Text)) { + for (AstText* textp = scopeTextp; textp; textp = VN_CAST(textp->nextp(), Text)) { out += textp->text(); } // TOP will be replaced by top->name() @@ -739,46 +772,42 @@ string AstScopeName::scopePrettyNameFormatter(AstText* scopeTextp) const { string AstScopeName::scopeNameFormatter(AstText* scopeTextp) const { string out; - for (AstText* textp=scopeTextp; textp; textp=VN_CAST(textp->nextp(), Text)) { + for (AstText* textp = scopeTextp; textp; textp = VN_CAST(textp->nextp(), Text)) { out += textp->text(); } if (out.substr(0, 10) == "__DOT__TOP") out.replace(0, 10, ""); if (out.substr(0, 7) == "__DOT__") out.replace(0, 7, ""); if (out.substr(0, 1) == ".") out.replace(0, 1, ""); string::size_type pos; - while ((pos = out.find('.')) != string::npos) { - out.replace(pos, 1, "__"); - } - while ((pos = out.find("__DOT__")) != string::npos) { - out.replace(pos, 7, "__"); - } + while ((pos = out.find('.')) != string::npos) out.replace(pos, 1, "__"); + while ((pos = out.find("__DOT__")) != string::npos) out.replace(pos, 7, "__"); return out; } bool AstSenTree::hasClocked() const { UASSERT_OBJ(sensesp(), this, "SENTREE without any SENITEMs under it"); - for (AstNodeSenItem* senp = sensesp(); senp; senp=VN_CAST(senp->nextp(), NodeSenItem)) { + for (AstNodeSenItem* senp = sensesp(); senp; senp = VN_CAST(senp->nextp(), NodeSenItem)) { if (senp->isClocked()) return true; } return false; } bool AstSenTree::hasSettle() const { UASSERT_OBJ(sensesp(), this, "SENTREE without any SENITEMs under it"); - for (AstNodeSenItem* senp = sensesp(); senp; senp=VN_CAST(senp->nextp(), NodeSenItem)) { + for (AstNodeSenItem* senp = sensesp(); senp; senp = VN_CAST(senp->nextp(), NodeSenItem)) { if (senp->isSettle()) return true; } return false; } bool AstSenTree::hasInitial() const { UASSERT_OBJ(sensesp(), this, "SENTREE without any SENITEMs under it"); - for (AstNodeSenItem* senp = sensesp(); senp; senp=VN_CAST(senp->nextp(), NodeSenItem)) { + for (AstNodeSenItem* senp = sensesp(); senp; senp = VN_CAST(senp->nextp(), NodeSenItem)) { if (senp->isInitial()) return true; } return false; } bool AstSenTree::hasCombo() const { UASSERT_OBJ(sensesp(), this, "SENTREE without any SENITEMs under it"); - for (AstNodeSenItem* senp = sensesp(); senp; senp=VN_CAST(senp->nextp(), NodeSenItem)) { + for (AstNodeSenItem* senp = sensesp(); senp; senp = VN_CAST(senp->nextp(), NodeSenItem)) { if (senp->isCombo()) return true; } return false; @@ -787,22 +816,20 @@ bool AstSenTree::hasCombo() const { void AstTypeTable::clearCache() { // When we mass-change widthMin in V3WidthCommit, we need to correct the table. // Just clear out the maps; the search functions will be used to rebuild the map - for (int i=0; i < static_cast(AstBasicDTypeKwd::_ENUM_MAX); ++i) { + for (int i = 0; i < static_cast(AstBasicDTypeKwd::_ENUM_MAX); ++i) { m_basicps[i] = NULL; } m_detailedMap.clear(); // Clear generic()'s so dead detection will work - for (AstNode* nodep = typesp(); nodep; nodep=nodep->nextp()) { - if (AstBasicDType* bdtypep = VN_CAST(nodep, BasicDType)) { - bdtypep->generic(false); - } + for (AstNode* nodep = typesp(); nodep; nodep = nodep->nextp()) { + if (AstBasicDType* bdtypep = VN_CAST(nodep, BasicDType)) bdtypep->generic(false); } } void AstTypeTable::repairCache() { // After we mass-change widthMin in V3WidthCommit, we need to correct the table. clearCache(); - for (AstNode* nodep = typesp(); nodep; nodep=nodep->nextp()) { + for (AstNode* nodep = typesp(); nodep; nodep = nodep->nextp()) { if (AstBasicDType* bdtypep = VN_CAST(nodep, BasicDType)) { (void)findInsertSameDType(bdtypep); } @@ -826,34 +853,43 @@ AstBasicDType* AstTypeTable::findBasicDType(FileLine* fl, AstBasicDTypeKwd kwd) // check the detailed map for this same node // Also adds this new node to the detailed map AstBasicDType* newp = findInsertSameDType(new1p); - if (newp != new1p) VL_DO_DANGLING(new1p->deleteTree(), new1p); - else addTypesp(newp); + if (newp != new1p) { + VL_DO_DANGLING(new1p->deleteTree(), new1p); + } else { + addTypesp(newp); + } // m_basicps[kwd] = newp; return newp; } -AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd, - int width, int widthMin, AstNumeric numeric) { +AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd, int width, + int widthMin, AstNumeric numeric) { AstBasicDType* new1p = new AstBasicDType(fl, kwd, numeric, width, widthMin); AstBasicDType* newp = findInsertSameDType(new1p); - if (newp != new1p) VL_DO_DANGLING(new1p->deleteTree(), new1p); - else addTypesp(newp); + if (newp != new1p) { + VL_DO_DANGLING(new1p->deleteTree(), new1p); + } else { + addTypesp(newp); + } return newp; } -AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd, - VNumRange range, int widthMin, AstNumeric numeric) { +AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd, VNumRange range, + int widthMin, AstNumeric numeric) { AstBasicDType* new1p = new AstBasicDType(fl, kwd, numeric, range, widthMin); AstBasicDType* newp = findInsertSameDType(new1p); - if (newp != new1p) VL_DO_DANGLING(new1p->deleteTree(), new1p); - else addTypesp(newp); + if (newp != new1p) { + VL_DO_DANGLING(new1p->deleteTree(), new1p); + } else { + addTypesp(newp); + } return newp; } AstBasicDType* AstTypeTable::findInsertSameDType(AstBasicDType* nodep) { - VBasicTypeKey key (nodep->width(), nodep->widthMin(), nodep->numeric(), - nodep->keyword(), nodep->nrange()); + VBasicTypeKey key(nodep->width(), nodep->widthMin(), nodep->numeric(), nodep->keyword(), + nodep->nrange()); DetailedMap& mapr = m_detailedMap; DetailedMap::const_iterator it = mapr.find(key); if (it != mapr.end()) return it->second; @@ -931,45 +967,49 @@ void AstWhile::addNextStmt(AstNode* newp, AstNode* belowp) { // Per-type Debugging void AstNode::dump(std::ostream& str) const { - str<m_backp - <<" =editCountLast())?"#>":">") - <<" {"<filenameLetters()<lastLineno()<<"}"; - if (user1p()) str<<" u1="<= editCountLast()) ? "#>" : ">") + << " {" << fileline()->filenameLetters() << std::dec << fileline()->lastLineno() << "}"; + 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 (hasDType()) { // Final @ so less likely to by accident read it as a nodep - if (dtypep()==this) str<<" @dt="<<"this@"; - else str<<" @dt="<dumpSmall(str); + if (dtypep() == this) { + str << " @dt=this@"; + } else { + str << " @dt=" << cvtToHex(dtypep()) << "@"; } + if (AstNodeDType* dtp = dtypep()) { dtp->dumpSmall(str); } } else { // V3Broken will throw an error - if (dtypep()) str<<" %Error-dtype-exp=null,got="<AstNode::dump(str); - if (keyword() != VAlwaysKwd::ALWAYS) str<<" ["<AstNode::dump(str); - str<<" ["<AstNodeDType::dump(str); - str<<" kwd="<AstNode::dump(str); - str<<" sz"<AstNode::dump(str); - if (recursive()) str<<" [RECURSIVE]"; - if (modp()) { str<<" -> "; modp()->dump(str); } - else { str<<" ->UNLINKED:"< "; + modp()->dump(str); + } else { + str << " ->UNLINKED:" << modName(); + } } void AstCellInline::dump(std::ostream& str) const { this->AstNode::dump(str); - str<<" -> "< " << origModName(); } const char* AstClassPackage::broken() const { BROKEN_BASE_RTN(AstNodeModule::broken()); @@ -1009,13 +1053,9 @@ void AstClass::insertCache(AstNode* nodep) { } void AstClass::repairCache() { clearCache(); - for (AstNode* itemp = membersp(); itemp; itemp = itemp->nextp()) { - insertCache(itemp); - } -} -void AstClass::dump(std::ostream& str) const { - this->AstNode::dump(str); + for (AstNode* itemp = membersp(); itemp; itemp = itemp->nextp()) { insertCache(itemp); } } +void AstClass::dump(std::ostream& str) const { this->AstNode::dump(str); } AstClass* AstClassExtends::classp() const { AstClassRefDType* refp = VN_CAST(dtypep(), ClassRefDType); UASSERT_OBJ(refp, this, "class extends non-ref"); @@ -1023,60 +1063,82 @@ AstClass* AstClassExtends::classp() const { } void AstClassRefDType::dump(std::ostream& str) const { this->AstNode::dump(str); - if (classp()) { str<<" -> "; classp()->dump(str); } - else { str<<" -> UNLINKED"; } + if (classp()) { + str << " -> "; + classp()->dump(str); + } else { + str << " -> UNLINKED"; + } } void AstClassRefDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); - str<<"class:"<AstNode::dump(str); - if (immediate()) str<<" [IMMEDIATE]"; + if (immediate()) str << " [IMMEDIATE]"; } void AstDisplay::dump(std::ostream& str) const { this->AstNode::dump(str); - //str<<" "<AstNode::dump(str); - str<<" -> "; - if (itemp()) { itemp()->dump(str); } - else { str<<"UNLINKED"; } + str << " -> "; + if (itemp()) { + itemp()->dump(str); + } else { + str << "UNLINKED"; + } } void AstIfaceRefDType::dump(std::ostream& str) const { this->AstNode::dump(str); - if (cellName()!="") { str<<" cell="< "; cellp()->dump(str); } - else if (ifacep()) { str<<" -> "; ifacep()->dump(str); } - else { str<<" -> UNLINKED"; } + if (cellName() != "") { str << " cell=" << cellName(); } + if (ifaceName() != "") { str << " if=" << ifaceName(); } + if (modportName() != "") { str << " mp=" << modportName(); } + if (cellp()) { + str << " -> "; + cellp()->dump(str); + } else if (ifacep()) { + str << " -> "; + ifacep()->dump(str); + } else { + str << " -> UNLINKED"; + } } void AstIfaceRefDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); - str<<"iface"; + str << "iface"; } void AstInitArray::dump(std::ostream& str) const { this->AstNode::dump(str); int n = 0; const AstInitArray::KeyItemMap& mapr = map(); for (AstInitArray::KeyItemMap::const_iterator it = mapr.begin(); it != mapr.end(); ++it) { - if (n++ > 5) { str<<" ..."; break; } - str<<" ["<first<<"]="<<(void*)it->second; + if (n++ > 5) { + str << " ..."; + break; + } + str << " [" << it->first << "]=" << (void*)it->second; } } void AstJumpGo::dump(std::ostream& str) const { this->AstNode::dump(str); - str<<" -> "; - if (labelp()) { labelp()->dump(str); } - else { str<<"%Error:UNLINKED"; } + str << " -> "; + if (labelp()) { + labelp()->dump(str); + } else { + str << "%Error:UNLINKED"; + } } void AstMemberSel::dump(std::ostream& str) const { this->AstNode::dump(str); str << " -> "; - if (varp()) { varp()->dump(str); } - else { str << "%Error:UNLINKED"; } + if (varp()) { + varp()->dump(str); + } else { + str << "%Error:UNLINKED"; + } } void AstMethodCall::dump(std::ostream& str) const { this->AstNode::dump(str); @@ -1090,30 +1152,42 @@ void AstMethodCall::dump(std::ostream& str) const { } void AstModportFTaskRef::dump(std::ostream& str) const { this->AstNode::dump(str); - if (isExport()) str<<" EXPORT"; - if (isImport()) str<<" IMPORT"; - if (ftaskp()) { str<<" -> "; ftaskp()->dump(str); } - else { str<<" -> UNLINKED"; } + if (isExport()) str << " EXPORT"; + if (isImport()) str << " IMPORT"; + if (ftaskp()) { + str << " -> "; + ftaskp()->dump(str); + } else { + str << " -> UNLINKED"; + } } void AstModportVarRef::dump(std::ostream& str) const { this->AstNode::dump(str); - if (direction().isAny()) str<<" "< "; varp()->dump(str); } - else { str<<" -> UNLINKED"; } + if (direction().isAny()) str << " " << direction(); + if (varp()) { + str << " -> "; + varp()->dump(str); + } else { + str << " -> UNLINKED"; + } } void AstPin::dump(std::ostream& str) const { this->AstNode::dump(str); - if (modVarp()) { str<<" -> "; modVarp()->dump(str); } - else { str<<" ->UNLINKED"; } - if (svImplicit()) str<<" [.SV]"; + if (modVarp()) { + str << " -> "; + modVarp()->dump(str); + } else { + str << " ->UNLINKED"; + } + if (svImplicit()) str << " [.SV]"; } void AstTypedef::dump(std::ostream& str) const { this->AstNode::dump(str); - if (attrPublic()) str<<" [PUBLIC]"; + if (attrPublic()) str << " [PUBLIC]"; } void AstRange::dump(std::ostream& str) const { this->AstNode::dump(str); - if (littleEndian()) str<<" [LITTLE]"; + if (littleEndian()) str << " [LITTLE]"; } void AstRefDType::dump(std::ostream& str) const { this->AstNodeDType::dump(str); @@ -1121,46 +1195,46 @@ void AstRefDType::dump(std::ostream& str) const { static bool s_recursing = false; if (!s_recursing) { // Prevent infinite dump if circular typedefs s_recursing = true; - str<<" -> "; defp()->dump(str); + str << " -> "; + defp()->dump(str); s_recursing = false; } + } else { + str << " -> UNLINKED"; } - else { str<<" -> UNLINKED"; } } void AstNodeUOrStructDType::dump(std::ostream& str) const { this->AstNode::dump(str); - if (packed()) str<<" [PACKED]"; - if (isFourstate()) str<<" [4STATE]"; + if (packed()) str << " [PACKED]"; + if (isFourstate()) str << " [4STATE]"; } void AstNodeDType::dump(std::ostream& str) const { this->AstNode::dump(str); - if (generic()) str<<" [GENERIC]"; + if (generic()) str << " [GENERIC]"; if (AstNodeDType* dtp = virtRefDTypep()) { - str<<" refdt="<AstNodeDType::dumpSmall(str); - if (VN_IS(this, PackArrayDType)) str<<"p"; else str<<"u"; - str<AstNodeDType::dump(str); - str<<" "<AstNode::dump(str); - str<<" L"<AstNode::dump(str); - str<<" -> "< " << packagep(); } void AstPackageImport::dump(std::ostream& str) const { this->AstNode::dump(str); - str<<" -> "< " << packagep(); } void AstSel::dump(std::ostream& str) const { this->AstNode::dump(str); if (declRange().ranged()) { - str<<" decl"<AstNode::dump(str); - if (declRange().ranged()) { - str<<" decl"<AstNode::dump(str); - str<<" "; + str << " "; m_execMTaskp->dump(str); } void AstTypeTable::dump(std::ostream& str) const { this->AstNode::dump(str); - for (int i=0; i < static_cast(AstBasicDTypeKwd::_ENUM_MAX); ++i) { + for (int i = 0; i < static_cast(AstBasicDTypeKwd::_ENUM_MAX); ++i) { if (AstBasicDType* subnodep = m_basicps[i]) { - str< "; + str << endl; // Newline from caller, so newline first + str << "\t\t" << std::setw(8) << AstBasicDTypeKwd(i).ascii(); + str << " -> "; subnodep->dump(str); } } @@ -1229,8 +1304,8 @@ void AstTypeTable::dump(std::ostream& str) const { const DetailedMap& mapr = m_detailedMap; for (DetailedMap::const_iterator it = mapr.begin(); it != mapr.end(); ++it) { AstBasicDType* dtypep = it->second; - str< "; + str << endl; // Newline from caller, so newline first + str << "\t\tdetailed -> "; dtypep->dump(str); } } @@ -1238,21 +1313,19 @@ void AstTypeTable::dump(std::ostream& str) const { } void AstAssocArrayDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); - str<<"[assoc-"<<(void*)keyDTypep()<<"]"; + str << "[assoc-" << (void*)keyDTypep() << "]"; } string AstAssocArrayDType::prettyDTypeName() const { return subDTypep()->prettyDTypeName() + "[" + keyDTypep()->prettyDTypeName() + "]"; } void AstDynArrayDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); - str<<"[]"; -} -string AstDynArrayDType::prettyDTypeName() const { - return subDTypep()->prettyDTypeName() + "[]"; + str << "[]"; } +string AstDynArrayDType::prettyDTypeName() const { return subDTypep()->prettyDTypeName() + "[]"; } void AstQueueDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); - str<<"[queue]"; + str << "[queue]"; } string AstQueueDType::prettyDTypeName() const { string str = subDTypep()->prettyDTypeName() + "[$"; @@ -1261,165 +1334,200 @@ string AstQueueDType::prettyDTypeName() const { } void AstUnsizedArrayDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); - str<<"[]"; + str << "[]"; } void AstVoidDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); - str<<"void"; + str << "void"; } void AstVarScope::dump(std::ostream& str) const { this->AstNode::dump(str); - if (isCircular()) str<<" [CIRC]"; - if (varp()) { str<<" -> "; varp()->dump(str); } - else { str<<" ->UNLINKED"; } + if (isCircular()) str << " [CIRC]"; + if (varp()) { + str << " -> "; + varp()->dump(str); + } else { + str << " ->UNLINKED"; + } } void AstVarXRef::dump(std::ostream& str) const { this->AstNode::dump(str); - if (packagep()) { str<<" pkg="< "; - else str<<" [RV] <- "; - str<<".="<dump(str); } - else if (varp()) { varp()->dump(str); } - else { str<<"UNLINKED"; } + if (packagep()) { str << " pkg=" << cvtToHex(packagep()); } + if (lvalue()) { + str << " [LV] => "; + } else { + str << " [RV] <- "; + } + str << ".=" << dotted() << " "; + if (inlinedDots() != "") str << " inline.=" << inlinedDots() << " - "; + if (varScopep()) { + varScopep()->dump(str); + } else if (varp()) { + varp()->dump(str); + } else { + str << "UNLINKED"; + } } void AstVarRef::dump(std::ostream& str) const { this->AstNode::dump(str); - if (packagep()) { str<<" pkg="< "; - else str<<" [RV] <- "; - if (varScopep()) { varScopep()->dump(str); } - else if (varp()) { varp()->dump(str); } - else { str<<"UNLINKED"; } + if (packagep()) { str << " pkg=" << cvtToHex(packagep()); } + if (lvalue()) { + str << " [LV] => "; + } else { + str << " [RV] <- "; + } + if (varScopep()) { + varScopep()->dump(str); + } else if (varp()) { + varp()->dump(str); + } else { + str << "UNLINKED"; + } } void AstVar::dump(std::ostream& str) const { this->AstNode::dump(str); - if (isSc()) str<<" [SC]"; - if (isPrimaryIO()) str<<(isInoutish()?" [PIO]":(isWritable()?" [PO]":" [PI]")); - if (isIO()) str<<" "<AstNode::dump(str); - if (isMulti()) str<<" [MULTI]"; + if (isMulti()) str << " [MULTI]"; } void AstSenItem::dump(std::ostream& str) const { this->AstNode::dump(str); - str<<" ["<AstNode::dump(str); - str<<" ["<AstNode::dump(str); - if (packagep()) { str<<" pkg="< "; - if (packagep()) { packagep()->dump(str); } - else { str<<"UNLINKED"; } -} -void AstDot::dump(std::ostream& str) const { - this->AstNode::dump(str); + if (packagep()) { str << " pkg=" << cvtToHex(packagep()); } + str << " -> "; + if (packagep()) { + packagep()->dump(str); + } else { + str << "UNLINKED"; + } } +void AstDot::dump(std::ostream& str) const { this->AstNode::dump(str); } void AstActive::dump(std::ostream& str) const { this->AstNode::dump(str); - str<<" => "; - if (sensesp()) { sensesp()->dump(str); } - else { str<<"UNLINKED"; } + str << " => "; + if (sensesp()) { + sensesp()->dump(str); + } else { + str << "UNLINKED"; + } } void AstNodeFTaskRef::dump(std::ostream& str) const { this->AstNode::dump(str); - if (packagep()) { str<<" pkg="< "; - if (dotted()!="") { str<<".="<dump(str); } - else { str<<"UNLINKED"; } + if (packagep()) { str << " pkg=" << cvtToHex(packagep()); } + str << " -> "; + if (dotted() != "") { str << ".=" << dotted() << " "; } + if (taskp()) { + taskp()->dump(str); + } else { + str << "UNLINKED"; + } } void AstNodeFTask::dump(std::ostream& str) const { this->AstNode::dump(str); - if (classMethod()) str<<" [METHOD]"; - if (taskPublic()) str<<" [PUBLIC]"; - if (prototype()) str<<" [PROTOTYPE]"; - if (dpiImport()) str<<" [DPII]"; - if (dpiExport()) str<<" [DPIX]"; - if (dpiOpenChild()) str<<" [DPIOPENCHILD]"; - if (dpiOpenParent()) str<<" [DPIOPENPARENT]"; - if ((dpiImport() || dpiExport()) && cname()!=name()) str<<" [c="<AstNode::dump(str); - if (unnamed()) str<<" [UNNAMED]"; - if (generate()) str<<" [GEN]"; - if (genforp()) str<<" [GENFOR]"; - if (implied()) str<<" [IMPLIED]"; + if (unnamed()) str << " [UNNAMED]"; + if (generate()) str << " [GEN]"; + if (genforp()) str << " [GENFOR]"; + if (implied()) str << " [IMPLIED]"; } void AstCoverDecl::dump(std::ostream& str) const { this->AstNode::dump(str); if (this->dataDeclNullp()) { - str<<" -> "; + str << " -> "; this->dataDeclNullp()->dump(str); } else { - if (binNum()) { str<<" bin"<AstNode::dump(str); - str<<" -> "; - if (declp()) { declp()->dump(str); } - else { str<<"%Error:UNLINKED"; } + str << " -> "; + if (declp()) { + declp()->dump(str); + } else { + str << "%Error:UNLINKED"; + } } void AstTraceInc::dump(std::ostream& str) const { this->AstNode::dump(str); - str<<" -> "; - if (declp()) { declp()->dump(str); } - else { str<<"%Error:UNLINKED"; } + str << " -> "; + if (declp()) { + declp()->dump(str); + } else { + str << "%Error:UNLINKED"; + } } void AstNodeText::dump(std::ostream& str) const { this->AstNode::dump(str); string out = text(); string::size_type pos; if ((pos = out.find('\n')) != string::npos) { - out.erase(pos, out.length()-pos); + out.erase(pos, out.length() - pos); out += "..."; } - str<<" \""<AstNode::dump(str); -} +void AstVFile::dump(std::ostream& str) const { this->AstNode::dump(str); } void AstCFile::dump(std::ostream& str) const { this->AstNode::dump(str); - if (source()) str<<" [SRC]"; - if (slow()) str<<" [SLOW]"; + if (source()) str << " [SRC]"; + if (slow()) str << " [SLOW]"; } void AstCFunc::dump(std::ostream& str) const { this->AstNode::dump(str); - if (slow()) str<<" [SLOW]"; - if (pure()) str<<" [PURE]"; - if (isStatic().unknown()) str<<" [STATICU]"; - else if (isStatic().trueUnknown()) str<<" [STATIC]"; - if (dpiImport()) str<<" [DPII]"; - if (dpiExport()) str<<" [DPIX]"; - if (dpiExportWrapper()) str<<" [DPIXWR]"; - if (isConstructor()) str<<" [CTOR]"; - if (isDestructor()) str<<" [DTOR]"; - if (isVirtual()) str<<" [VIRT]"; + if (slow()) str << " [SLOW]"; + if (pure()) str << " [PURE]"; + if (isStatic().unknown()) { + str << " [STATICU]"; + } else if (isStatic().trueUnknown()) { + str << " [STATIC]"; + } + if (dpiImport()) str << " [DPII]"; + if (dpiExport()) str << " [DPIX]"; + if (dpiExportWrapper()) str << " [DPIXWR]"; + if (isConstructor()) str << " [CTOR]"; + if (isDestructor()) str << " [DTOR]"; + if (isVirtual()) str << " [VIRT]"; } void AstCUse::dump(std::ostream& str) const { this->AstNode::dump(str); diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 4eb5676f7..aa05bd09c 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -26,20 +26,23 @@ #define ASTNODE_NODE_FUNCS_NO_DTOR(name) \ virtual void accept(AstNVisitor& v) { v.visit(this); } \ - virtual AstNode* clone() { return new Ast ##name (*this); } \ - static Ast ##name * cloneTreeNull(Ast ##name * nodep, bool cloneNextLink) { \ - return nodep ? nodep->cloneTree(cloneNextLink) : NULL; } \ - Ast ##name * cloneTree(bool cloneNext) { return static_cast(AstNode::cloneTree(cloneNext)); } \ - Ast ##name * clonep() const { return static_cast(AstNode::clonep()); } + virtual AstNode* clone() { return new Ast##name(*this); } \ + static Ast##name* cloneTreeNull(Ast##name* nodep, bool cloneNextLink) { \ + return nodep ? nodep->cloneTree(cloneNextLink) : NULL; \ + } \ + Ast##name* cloneTree(bool cloneNext) { \ + return static_cast(AstNode::cloneTree(cloneNext)); \ + } \ + Ast##name* clonep() const { return static_cast(AstNode::clonep()); } #define ASTNODE_NODE_FUNCS(name) \ - virtual ~Ast ##name() {} \ + virtual ~Ast##name() {} \ ASTNODE_NODE_FUNCS_NO_DTOR(name) //###################################################################### // Macros replaced by 'astgen' -#define ASTGEN_SUPER(...) // Roughly: (AstType::at, ...) +#define ASTGEN_SUPER(...) // Roughly: (AstType::at, ...) //###################################################################### //=== Ast* : Specific types @@ -60,6 +63,7 @@ private: } m_num.nodep(this); } + public: AstConst(FileLine* fl, const V3Number& num) : ASTGEN_SUPER(fl) @@ -72,7 +76,7 @@ public: , m_num(this, width, value) { initWithNumber(); } - class DtypedValue{}; // for creator type-overload selection + class DtypedValue {}; // for creator type-overload selection AstConst(FileLine* fl, DtypedValue, AstNodeDType* nodedtypep, uint32_t value) : ASTGEN_SUPER(fl) , m_num(this, nodedtypep->width(), value, nodedtypep->widthSized()) { @@ -119,19 +123,28 @@ public: class RealDouble {}; // for creator type-overload selection AstConst(FileLine* fl, RealDouble, double num) : ASTGEN_SUPER(fl) - , m_num(this, 64) { m_num.setDouble(num); dtypeSetDouble(); } + , m_num(this, 64) { + m_num.setDouble(num); + dtypeSetDouble(); + } class String {}; // for creator type-overload selection AstConst(FileLine* fl, String, const string& num) : ASTGEN_SUPER(fl) - , m_num(V3Number::String(), this, num) { dtypeSetString(); } + , m_num(V3Number::String(), this, num) { + dtypeSetString(); + } class LogicFalse {}; AstConst(FileLine* fl, LogicFalse) // Shorthand const 0, dtype should be a logic of size 1 : ASTGEN_SUPER(fl) - , m_num(this, 1, 0) { dtypeSetLogicBool(); } + , m_num(this, 1, 0) { + dtypeSetLogicBool(); + } class LogicTrue {}; AstConst(FileLine* fl, LogicTrue) // Shorthand const 1, dtype should be a logic of size 1 : ASTGEN_SUPER(fl) - , m_num(this, 1, 1) { dtypeSetLogicBool(); } + , m_num(this, 1, 1) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(Const) virtual string name() const { return num().ascii(); } // * = Value const V3Number& num() const { return m_num; } // * = Value @@ -145,7 +158,8 @@ public: virtual V3Hash sameHash() const { return V3Hash(num().toHash()); } virtual bool same(const AstNode* samep) const { const AstConst* sp = static_cast(samep); - return num().isCaseEq(sp->num()); } + return num().isCaseEq(sp->num()); + } virtual int instrCount() const { return widthInstrs(); } bool isEqAllOnes() const { return num().isEqAllOnes(width()); } bool isEqAllOnesV() const { return num().isEqAllOnes(widthMinV()); } @@ -154,12 +168,14 @@ public: class AstRange : public AstNodeRange { // Range specification, for use under variables and cells private: - bool m_littleEndian:1; // Bit vector is little endian + bool m_littleEndian : 1; // Bit vector is little endian public: AstRange(FileLine* fl, AstNode* msbp, AstNode* lsbp) : ASTGEN_SUPER(fl) { m_littleEndian = false; - setOp2p(msbp); setOp3p(lsbp); } + setOp2p(msbp); + setOp3p(lsbp); + } AstRange(FileLine* fl, int msb, int lsb) : ASTGEN_SUPER(fl) { m_littleEndian = false; @@ -175,14 +191,31 @@ public: ASTNODE_NODE_FUNCS(Range) AstNode* msbp() const { return op2p(); } // op2 = Msb expression AstNode* lsbp() const { return op3p(); } // op3 = Lsb expression - AstNode* leftp() const { return littleEndian()?lsbp():msbp(); } // How to show a declaration - AstNode* rightp() const { return littleEndian()?msbp():lsbp(); } - int msbConst() const { AstConst* constp = VN_CAST(msbp(), Const); return (constp?constp->toSInt():0); } - int lsbConst() const { AstConst* constp = VN_CAST(lsbp(), Const); return (constp?constp->toSInt():0); } - int elementsConst() const { return (msbConst()>lsbConst()) ? msbConst()-lsbConst()+1 : lsbConst()-msbConst()+1; } - int leftConst() const { AstConst* constp = VN_CAST(leftp(), Const); return (constp?constp->toSInt():0); } - int rightConst() const { AstConst* constp = VN_CAST(rightp(), Const); return (constp?constp->toSInt():0); } - int leftToRightInc() const { return littleEndian()?1:-1; } + AstNode* leftp() const { + return littleEndian() ? lsbp() : msbp(); + } // How to show a declaration + AstNode* rightp() const { return littleEndian() ? msbp() : lsbp(); } + int msbConst() const { + AstConst* constp = VN_CAST(msbp(), Const); + return (constp ? constp->toSInt() : 0); + } + int lsbConst() const { + AstConst* constp = VN_CAST(lsbp(), Const); + return (constp ? constp->toSInt() : 0); + } + int elementsConst() const { + return (msbConst() > lsbConst()) ? msbConst() - lsbConst() + 1 + : lsbConst() - msbConst() + 1; + } + int leftConst() const { + AstConst* constp = VN_CAST(leftp(), Const); + return (constp ? constp->toSInt() : 0); + } + int rightConst() const { + AstConst* constp = VN_CAST(rightp(), Const); + return (constp ? constp->toSInt() : 0); + } + int leftToRightInc() const { return littleEndian() ? 1 : -1; } bool littleEndian() const { return m_littleEndian; } void littleEndian(bool flag) { m_littleEndian = flag; } virtual void dump(std::ostream& str) const; @@ -237,7 +270,8 @@ class AstGatePin : public AstNodeMath { public: AstGatePin(FileLine* fl, AstNode* lhsp, AstRange* rangep) : ASTGEN_SUPER(fl) { - setOp1p(lhsp); setOp2p(rangep); + setOp1p(lhsp); + setOp2p(rangep); } ASTNODE_NODE_FUNCS(GatePin) virtual string emitVerilog() { return "%l"; } @@ -271,6 +305,7 @@ class AstClass : public AstNodeModule { MemberNameMap m_members; // Members or method children AstClassPackage* m_packagep; // Class package this is under void insertCache(AstNode* nodep); + public: AstClass(FileLine* fl, const string& name) : ASTGEN_SUPER(fl, name) @@ -326,20 +361,24 @@ class AstParamTypeDType : public AstNodeDType { // Parents: MODULE // A parameter type statement; much like a var or typedef private: - AstVarType m_varType; // Type of variable (for localparam vs. param) - string m_name; // Name of variable + AstVarType m_varType; // Type of variable (for localparam vs. param) + string m_name; // Name of variable public: - AstParamTypeDType(FileLine* fl, AstVarType type, const string& name, VFlagChildDType, AstNodeDType* dtp) - : ASTGEN_SUPER(fl), m_varType(type), m_name(name) { + AstParamTypeDType(FileLine* fl, AstVarType type, const string& name, VFlagChildDType, + AstNodeDType* dtp) + : ASTGEN_SUPER(fl) + , m_varType(type) + , m_name(name) { childDTypep(dtp); // Only for parser dtypep(NULL); // V3Width will resolve } ASTNODE_NODE_FUNCS(ParamTypeDType) AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Type assigning to + // op1 = Type assigning to + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } - virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type + virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); } virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); } virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); } @@ -356,17 +395,19 @@ public: void name(const string& flag) { m_name = flag; } AstVarType varType() const { return m_varType; } // * = Type of variable bool isParam() const { return true; } - bool isGParam() const { return (varType()==AstVarType::GPARAM); } + bool isGParam() const { return (varType() == AstVarType::GPARAM); } }; class AstTypedef : public AstNode { private: - string m_name; - bool m_attrPublic; - string m_tag; // Holds the string of the verilator tag -- used in XML output. + string m_name; + bool m_attrPublic; + string m_tag; // Holds the string of the verilator tag -- used in XML output. public: - AstTypedef(FileLine* fl, const string& name, AstNode* attrsp, VFlagChildDType, AstNodeDType* dtp) - : ASTGEN_SUPER(fl), m_name(name) { + AstTypedef(FileLine* fl, const string& name, AstNode* attrsp, VFlagChildDType, + AstNodeDType* dtp) + : ASTGEN_SUPER(fl) + , m_name(name) { childDTypep(dtp); // Only for parser addAttrsp(attrsp); dtypep(NULL); // V3Width will resolve @@ -375,7 +416,8 @@ public: ASTNODE_NODE_FUNCS(Typedef) virtual void dump(std::ostream& str) const; AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Type assigning to + // op1 = Type assigning to + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } void addAttrsp(AstNode* nodep) { addNOp4p(nodep); } @@ -387,17 +429,19 @@ public: void name(const string& flag) { m_name = flag; } bool attrPublic() const { return m_attrPublic; } void attrPublic(bool flag) { m_attrPublic = flag; } - virtual void tag(const string& text) { m_tag = text;} + virtual void tag(const string& text) { m_tag = text; } virtual string tag() const { return m_tag; } }; class AstTypedefFwd : public AstNode { // Forward declaration of a type; stripped after netlist parsing is complete private: - string m_name; + string m_name; + public: AstTypedefFwd(FileLine* fl, const string& name) - : ASTGEN_SUPER(fl), m_name(name) {} + : ASTGEN_SUPER(fl) + , m_name(name) {} ASTNODE_NODE_FUNCS(TypedefFwd) // METHODS virtual string name() const { return m_name; } @@ -408,13 +452,17 @@ class AstDefImplicitDType : public AstNodeDType { // This allows "var enum {...} a,b" to share the enum definition for both variables // After link, these become typedefs private: - string m_name; - void* m_containerp; // In what scope is the name unique, so we can know what are duplicate definitions (arbitrary value) - int m_uniqueNum; + string m_name; + void* m_containerp; // In what scope is the name unique, so we can know what are duplicate + // definitions (arbitrary value) + int m_uniqueNum; + public: - AstDefImplicitDType(FileLine* fl, const string& name, void* containerp, - VFlagChildDType, AstNodeDType* dtp) - : ASTGEN_SUPER(fl), m_name(name), m_containerp(containerp) { + AstDefImplicitDType(FileLine* fl, const string& name, void* containerp, VFlagChildDType, + AstNodeDType* dtp) + : ASTGEN_SUPER(fl) + , m_name(name) + , m_containerp(containerp) { childDTypep(dtp); // Only for parser dtypep(NULL); // V3Width will resolve m_uniqueNum = uniqueNumInc(); @@ -422,18 +470,22 @@ public: ASTNODE_NODE_FUNCS(DefImplicitDType) virtual bool same(const AstNode* samep) const { const AstDefImplicitDType* sp = static_cast(samep); - return m_uniqueNum == sp->m_uniqueNum; } + return m_uniqueNum == sp->m_uniqueNum; + } virtual bool similarDType(AstNodeDType* samep) const { - return type()==samep->type() && same(samep); } + return type() == samep->type() && same(samep); + } virtual V3Hash sameHash() const { return V3Hash(m_uniqueNum); } AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } void* containerp() const { return m_containerp; } // METHODS - AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); } // op1 = Range of variable - virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type + // op1 = Range of variable + AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); } + virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } @@ -465,14 +517,16 @@ public: || (!m_refDTypep && childDTypep()))); BROKEN_RTN(!((m_keyDTypep && !childDTypep() && m_keyDTypep->brokeExists()) || (!m_keyDTypep && childDTypep()))); - return NULL; } + return NULL; + } virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } - if (m_keyDTypep && m_keyDTypep->clonep()) { m_keyDTypep = m_keyDTypep->clonep(); } } + if (m_keyDTypep && m_keyDTypep->clonep()) { m_keyDTypep = m_keyDTypep->clonep(); } + } virtual bool same(const AstNode* samep) const { const AstAssocArrayDType* asamep = static_cast(samep); - return (subDTypep() == asamep->subDTypep() - && keyDTypep() == asamep->keyDTypep()); } + return (subDTypep() == asamep->subDTypep() && keyDTypep() == asamep->keyDTypep()); + } virtual bool similarDType(AstNodeDType* samep) const { const AstAssocArrayDType* asamep = static_cast(samep); return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); @@ -481,7 +535,8 @@ public: virtual void dumpSmall(std::ostream& str) const; virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); } AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } @@ -492,10 +547,11 @@ public: // AstNodeDType* keyDTypep() const { return m_keyDTypep ? m_keyDTypep : keyChildDTypep(); } void keyDTypep(AstNodeDType* nodep) { m_keyDTypep = nodep; } - AstNodeDType* keyChildDTypep() const { return VN_CAST(op2p(), NodeDType); } // op1 = Range of variable + // op1 = Range of variable + AstNodeDType* keyChildDTypep() const { return VN_CAST(op2p(), NodeDType); } void keyChildDTypep(AstNodeDType* nodep) { setOp2p(nodep); } // METHODS - virtual AstBasicDType* basicp() const { return NULL; } // (Slow) recurse down to find basic data type + virtual AstBasicDType* basicp() const { return NULL; } virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } @@ -524,12 +580,15 @@ public: virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); - return NULL; } + return NULL; + } virtual void cloneRelink() { - if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } } + if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } + } virtual bool same(const AstNode* samep) const { const AstAssocArrayDType* asamep = static_cast(samep); - return subDTypep() == asamep->subDTypep(); } + return subDTypep() == asamep->subDTypep(); + } virtual bool similarDType(AstNodeDType* samep) const { const AstAssocArrayDType* asamep = static_cast(samep); return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); @@ -538,14 +597,15 @@ public: virtual void dumpSmall(std::ostream& str) const; virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); } AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; } virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } // METHODS - virtual AstBasicDType* basicp() const { return NULL; } // (Slow) recurse down to find basic data type + virtual AstBasicDType* basicp() const { return NULL; } virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } @@ -620,14 +680,18 @@ public: dtypep(NULL); // V3Width will resolve } ASTNODE_NODE_FUNCS(UnsizedArrayDType) - virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) - || (!m_refDTypep && childDTypep()))); return NULL; } - virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) { - m_refDTypep = m_refDTypep->clonep(); - }} + virtual const char* broken() const { + BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) + || (!m_refDTypep && childDTypep()))); + return NULL; + } + virtual void cloneRelink() { + if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } + } virtual bool same(const AstNode* samep) const { const AstNodeArrayDType* asamep = static_cast(samep); - return (subDTypep()==asamep->subDTypep()); } + return (subDTypep() == asamep->subDTypep()); + } virtual bool similarDType(AstNodeDType* samep) const { const AstNodeArrayDType* asamep = static_cast(samep); return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); @@ -635,14 +699,15 @@ public: virtual void dumpSmall(std::ostream& str) const; virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); } AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; } virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } // METHODS - virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type + virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } @@ -658,12 +723,12 @@ private: AstBasicDTypeKwd m_keyword; // (also in VBasicTypeKey) What keyword created basic type VNumRange m_nrange; // (also in VBasicTypeKey) Numeric msb/lsb (if non-opaque keyword) bool operator==(const Members& rhs) const { - return rhs.m_keyword == m_keyword - && rhs.m_nrange == m_nrange; } + return rhs.m_keyword == m_keyword && rhs.m_nrange == m_nrange; + } } m; // See also in AstNodeDType: m_width, m_widthMin, m_numeric(issigned) public: - AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, VSignedState signst=signedst_NOSIGN) + AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, VSignedState signst = signedst_NOSIGN) : ASTGEN_SUPER(fl) { init(kwd, AstNumeric(signst), 0, -1, NULL); } @@ -675,77 +740,98 @@ public: : ASTGEN_SUPER(fl) { init(AstBasicDTypeKwd::BIT, AstNumeric::NOSIGN, wantwidth, -1, NULL); } - AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, AstNumeric numer, int wantwidth, int widthmin) + AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, AstNumeric numer, int wantwidth, + int widthmin) : ASTGEN_SUPER(fl) { init(kwd, numer, wantwidth, widthmin, NULL); } - AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, AstNumeric numer, VNumRange range, int widthmin) + AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, AstNumeric numer, VNumRange range, + int widthmin) : ASTGEN_SUPER(fl) { init(kwd, numer, range.elements(), widthmin, NULL); m.m_nrange = range; // as init() presumes lsb==0, but range.lsb() might not be } // See also addRange in verilog.y private: - void init(AstBasicDTypeKwd kwd, AstNumeric numer, - int wantwidth, int wantwidthmin, AstRange* rangep) { + void init(AstBasicDTypeKwd kwd, AstNumeric numer, int wantwidth, int wantwidthmin, + AstRange* rangep) { // wantwidth=0 means figure it out, but if a widthmin is >=0 // we allow width 0 so that {{0{x}},y} works properly // wantwidthmin=-1: default, use wantwidth if it is non zero m.m_keyword = kwd; // Implicitness: // "parameter X" is implicit and sized from initial // value, "parameter reg x" not - if (keyword()==AstBasicDTypeKwd::LOGIC_IMPLICIT) { + if (keyword() == AstBasicDTypeKwd::LOGIC_IMPLICIT) { if (rangep || wantwidth) m.m_keyword = AstBasicDTypeKwd::LOGIC; } if (numer == AstNumeric::NOSIGN) { - if (keyword().isSigned()) numer = AstNumeric::SIGNED; - else if (keyword().isUnsigned()) numer = AstNumeric::UNSIGNED; + if (keyword().isSigned()) { + numer = AstNumeric::SIGNED; + } else if (keyword().isUnsigned()) { + numer = AstNumeric::UNSIGNED; + } } numeric(numer); - if (!rangep && (wantwidth || wantwidthmin>=0)) { // Constant width - if (wantwidth>1) m.m_nrange.init(wantwidth-1, 0, false); - int wmin = wantwidthmin>=0 ? wantwidthmin : wantwidth; + if (!rangep && (wantwidth || wantwidthmin >= 0)) { // Constant width + if (wantwidth > 1) m.m_nrange.init(wantwidth - 1, 0, false); + int wmin = wantwidthmin >= 0 ? wantwidthmin : wantwidth; widthForce(wantwidth, wmin); } else if (!rangep) { // Set based on keyword properties // V3Width will pull from this width if (keyword().width() > 1 && !isOpaque()) { - m.m_nrange.init(keyword().width()-1, 0, false); + m.m_nrange.init(keyword().width() - 1, 0, false); } widthForce(keyword().width(), keyword().width()); } else { - widthForce(rangep->elementsConst(), rangep->elementsConst()); // Maybe unknown if parameters underneath it + widthForce(rangep->elementsConst(), + rangep->elementsConst()); // Maybe unknown if parameters underneath it } setNOp1p(rangep); dtypep(this); } + public: ASTNODE_NODE_FUNCS(BasicDType) virtual void dump(std::ostream& str) const; - virtual V3Hash sameHash() const { return V3Hash(V3Hash(m.m_keyword), V3Hash(m.m_nrange.hi())); } + virtual V3Hash sameHash() const { + return V3Hash(V3Hash(m.m_keyword), V3Hash(m.m_nrange.hi())); + } virtual bool same(const AstNode* samep) const { // width/widthMin/numeric compared elsewhere const AstBasicDType* sp = static_cast(samep); - return m == sp->m; } + return m == sp->m; + } virtual bool similarDType(AstNodeDType* samep) const { - return type()==samep->type() && same(samep); } + return type() == samep->type() && same(samep); + } virtual string name() const { return m.m_keyword.ascii(); } virtual string prettyDTypeName() const; - virtual const char* broken() const { BROKEN_RTN(dtypep()!=this); return NULL; } + virtual const char* broken() const { + BROKEN_RTN(dtypep() != this); + return NULL; + } AstRange* rangep() const { return VN_CAST(op1p(), Range); } // op1 = Range of variable void rangep(AstRange* nodep) { setNOp1p(nodep); } void setSignedState(VSignedState signst) { // Note NOSIGN does NOT change the state; this is required by the parser - if (signst==signedst_UNSIGNED) numeric(signst); - else if (signst==signedst_SIGNED) numeric(signst); + if (signst == signedst_UNSIGNED) { + numeric(signst); + } else if (signst == signedst_SIGNED) { + numeric(signst); + } } // METHODS - virtual AstBasicDType* basicp() const { return (AstBasicDType*)this; } // (Slow) recurse down to find basic data type + virtual AstBasicDType* basicp() const { return (AstBasicDType*)this; } virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) - virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... + // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) + virtual int widthAlignBytes() const; + virtual int + widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... virtual bool isFourstate() const { return keyword().isFourstate(); } - AstBasicDTypeKwd keyword() const { return m.m_keyword; } // Avoid using - use isSomething accessors instead + AstBasicDTypeKwd keyword() const { // Avoid using - use isSomething accessors instead + return m.m_keyword; + } bool isBitLogic() const { return keyword().isBitLogic(); } bool isDouble() const { return keyword().isDouble(); } bool isOpaque() const { return keyword().isOpaque(); } @@ -762,18 +848,23 @@ public: bool isDpiPrimitive() const { // DPI uses a primitive type return !isDpiBitVec() && !isDpiLogicVec(); } - const VNumRange& nrange() const { return m.m_nrange; } // Generally the msb/lsb/etc funcs should be used instead + const VNumRange& nrange() const { + return m.m_nrange; + } // Generally the msb/lsb/etc funcs should be used instead int msb() const { return (rangep() ? rangep()->msbConst() : m.m_nrange.hi()); } int lsb() const { return (rangep() ? rangep()->lsbConst() : m.m_nrange.lo()); } - int left() const { return littleEndian()?lsb():msb(); } // How to show a declaration - int right() const { return littleEndian()?msb():lsb(); } - bool littleEndian() const { return (rangep() ? rangep()->littleEndian() : m.m_nrange.littleEndian()); } + int left() const { return littleEndian() ? lsb() : msb(); } // How to show a declaration + int right() const { return littleEndian() ? msb() : lsb(); } + bool littleEndian() const { + return (rangep() ? rangep()->littleEndian() : m.m_nrange.littleEndian()); + } bool implicit() const { return keyword() == AstBasicDTypeKwd::LOGIC_IMPLICIT; } - VNumRange declRange() const { return isRanged() ? VNumRange(msb(), lsb(), littleEndian()) : VNumRange(); } + VNumRange declRange() const { + return isRanged() ? VNumRange(msb(), lsb(), littleEndian()) : VNumRange(); + } void cvtRangeConst() { // Convert to smaller representation if (rangep() && VN_IS(rangep()->msbp(), Const) && VN_IS(rangep()->lsbp(), Const)) { - m.m_nrange.init(rangep()->msbConst(), rangep()->lsbConst(), - rangep()->littleEndian()); + m.m_nrange.init(rangep()->msbConst(), rangep()->lsbConst(), rangep()->littleEndian()); rangep()->unlinkFrBackWithNext()->deleteTree(); rangep(NULL); } @@ -785,7 +876,7 @@ class AstConstDType : public AstNodeDType { // ConstDType are removed in V3LinkLValue and become AstVar::isConst. // When more generic types are supported AstConstDType will be propagated further. private: - AstNodeDType* m_refDTypep; // Inherit from this base data type + AstNodeDType* m_refDTypep; // Inherit from this base data type public: AstConstDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp) : ASTGEN_SUPER(fl) { @@ -795,26 +886,34 @@ public: widthFromSub(subDTypep()); } ASTNODE_NODE_FUNCS(ConstDType) - virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) - || (!m_refDTypep && childDTypep()))); return NULL; } - virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) { - m_refDTypep = m_refDTypep->clonep(); - }} + virtual const char* broken() const { + BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) + || (!m_refDTypep && childDTypep()))); + return NULL; + } + virtual void cloneRelink() { + if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } + } virtual bool same(const AstNode* samep) const { const AstConstDType* sp = static_cast(samep); - return (m_refDTypep == sp->m_refDTypep); } + return (m_refDTypep == sp->m_refDTypep); + } virtual bool similarDType(AstNodeDType* samep) const { - return skipRefp()->similarDType(samep->skipRefp()); } - virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); } // node's type() included elsewhere + return skipRefp()->similarDType(samep->skipRefp()); + } + virtual V3Hash sameHash() const { + return V3Hash(m_refDTypep); + } // node's type() included elsewhere AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } // op1 = Range of variable + virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; } virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } // METHODS - virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type + virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); } @@ -829,24 +928,27 @@ private: AstNodeModule* m_packagep; // Package hierarchy public: AstClassRefDType(FileLine* fl, AstClass* classp) - : ASTGEN_SUPER(fl), m_classp(classp), m_packagep(NULL) { + : ASTGEN_SUPER(fl) + , m_classp(classp) + , m_packagep(NULL) { dtypep(this); } ASTNODE_NODE_FUNCS(ClassRefDType) // METHODS virtual const char* broken() const { - BROKEN_RTN(m_classp && !m_classp->brokeExists()); return NULL; } + BROKEN_RTN(m_classp && !m_classp->brokeExists()); + return NULL; + } virtual void cloneRelink() { if (m_classp && m_classp->clonep()) m_classp = m_classp->clonep(); } virtual bool same(const AstNode* samep) const { const AstClassRefDType* asamep = static_cast(samep); - return (m_classp == asamep->m_classp - && m_packagep == asamep->m_packagep); } - virtual bool similarDType(AstNodeDType* samep) const { - return this == samep || same(samep); } + return (m_classp == asamep->m_classp && m_packagep == asamep->m_packagep); + } + virtual bool similarDType(AstNodeDType* samep) const { return this == samep || same(samep); } virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_classp), V3Hash(m_packagep)); } - virtual void dump(std::ostream& str=std::cout) const; + virtual void dump(std::ostream& str = std::cout) const; virtual void dumpSmall(std::ostream& str) const; virtual string name() const { return classp() ? classp()->name() : ""; } virtual AstBasicDType* basicp() const { return NULL; } @@ -867,35 +969,44 @@ public: class AstIfaceRefDType : public AstNodeDType { // Reference to an interface, either for a port, or inside parent cell private: - FileLine* m_modportFileline; // Where modport token was - string m_cellName; // "" = no cell, such as when connects to 'input' iface - string m_ifaceName; // Interface name - string m_modportName; // "" = no modport - AstIface* m_ifacep; // Pointer to interface; note cellp() should override - AstCell* m_cellp; // When exact parent cell known; not a guess - AstModport* m_modportp; // NULL = unlinked or no modport + FileLine* m_modportFileline; // Where modport token was + string m_cellName; // "" = no cell, such as when connects to 'input' iface + string m_ifaceName; // Interface name + string m_modportName; // "" = no modport + AstIface* m_ifacep; // Pointer to interface; note cellp() should override + AstCell* m_cellp; // When exact parent cell known; not a guess + AstModport* m_modportp; // NULL = unlinked or no modport public: - AstIfaceRefDType(FileLine* fl, - const string& cellName, const string& ifaceName) - : ASTGEN_SUPER(fl), m_modportFileline(NULL) - , m_cellName(cellName), m_ifaceName(ifaceName), m_modportName("") - , m_ifacep(NULL), m_cellp(NULL), m_modportp(NULL) { } - AstIfaceRefDType(FileLine* fl, FileLine* modportFl, - const string& cellName, const string& ifaceName, const string& modport) - : ASTGEN_SUPER(fl), m_modportFileline(modportFl) - , m_cellName(cellName), m_ifaceName(ifaceName), m_modportName(modport) - , m_ifacep(NULL), m_cellp(NULL), m_modportp(NULL) { } + AstIfaceRefDType(FileLine* fl, const string& cellName, const string& ifaceName) + : ASTGEN_SUPER(fl) + , m_modportFileline(NULL) + , m_cellName(cellName) + , m_ifaceName(ifaceName) + , m_modportName("") + , m_ifacep(NULL) + , m_cellp(NULL) + , m_modportp(NULL) {} + AstIfaceRefDType(FileLine* fl, FileLine* modportFl, const string& cellName, + const string& ifaceName, const string& modport) + : ASTGEN_SUPER(fl) + , m_modportFileline(modportFl) + , m_cellName(cellName) + , m_ifaceName(ifaceName) + , m_modportName(modport) + , m_ifacep(NULL) + , m_cellp(NULL) + , m_modportp(NULL) {} ASTNODE_NODE_FUNCS(IfaceRefDType) // METHODS virtual const char* broken() const; - virtual void dump(std::ostream& str=std::cout) const; + virtual void dump(std::ostream& str = std::cout) const; virtual void dumpSmall(std::ostream& str) const; virtual void cloneRelink(); virtual AstBasicDType* basicp() const { return NULL; } virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } - virtual bool similarDType(AstNodeDType* samep) const { return this==samep; } + virtual bool similarDType(AstNodeDType* samep) const { return this == samep; } virtual V3Hash sameHash() const { return V3Hash(m_cellp); } virtual int widthAlignBytes() const { return 1; } virtual int widthTotalBytes() const { return 1; } @@ -933,12 +1044,15 @@ public: virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); - return NULL; } + return NULL; + } virtual void cloneRelink() { - if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } } + if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } + } virtual bool same(const AstNode* samep) const { const AstQueueDType* asamep = static_cast(samep); - return (subDTypep() == asamep->subDTypep()); } + return (subDTypep() == asamep->subDTypep()); + } virtual bool similarDType(AstNodeDType* samep) const { const AstQueueDType* asamep = static_cast(samep); return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); @@ -947,13 +1061,17 @@ public: virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); } virtual string prettyDTypeName() const; AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } AstNode* boundp() const { return op2p(); } // op2 = Bound, NULL = none void boundp(AstNode* nodep) { setNOp2p(nodep); } - int boundConst() const { AstConst* constp = VN_CAST(boundp(), Const); return (constp?constp->toSInt() : 0); } + int boundConst() const { + AstConst* constp = VN_CAST(boundp(), Const); + return (constp ? constp->toSInt() : 0); + } virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; } virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } // METHODS @@ -971,58 +1089,85 @@ public: class AstRefDType : public AstNodeDType { private: AstNodeDType* m_refDTypep; // data type pointed to, BELOW the AstTypedef - string m_name; // Name of an AstTypedef + string m_name; // Name of an AstTypedef AstNodeModule* m_packagep; // Package hierarchy public: AstRefDType(FileLine* fl, const string& name) - : ASTGEN_SUPER(fl), m_refDTypep(NULL), m_name(name), m_packagep(NULL) {} + : ASTGEN_SUPER(fl) + , m_refDTypep(NULL) + , m_name(name) + , m_packagep(NULL) {} AstRefDType(FileLine* fl, AstNodeDType* defp) - : ASTGEN_SUPER(fl), m_refDTypep(defp), m_packagep(NULL) { + : ASTGEN_SUPER(fl) + , m_refDTypep(defp) + , m_packagep(NULL) { dtypeFrom(defp->dtypep()); widthFromSub(subDTypep()); } class FlagTypeOfExpr {}; // type(expr) for parser only AstRefDType(FileLine* fl, FlagTypeOfExpr, AstNode* typeofp) - : ASTGEN_SUPER(fl), m_refDTypep(NULL), m_packagep(NULL) { + : ASTGEN_SUPER(fl) + , m_refDTypep(NULL) + , m_packagep(NULL) { setOp2p(typeofp); } ASTNODE_NODE_FUNCS(RefDType) // METHODS - virtual const char* broken() const { BROKEN_RTN(m_refDTypep && !m_refDTypep->brokeExists()); return NULL; } - virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) { - m_refDTypep = m_refDTypep->clonep(); - }} + virtual const char* broken() const { + BROKEN_RTN(m_refDTypep && !m_refDTypep->brokeExists()); + return NULL; + } + virtual void cloneRelink() { + if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } + } virtual bool same(const AstNode* samep) const { const AstRefDType* asamep = static_cast(samep); - return (m_refDTypep == asamep->m_refDTypep - && m_name == asamep->m_name - && m_packagep == asamep->m_packagep); } + return (m_refDTypep == asamep->m_refDTypep && m_name == asamep->m_name + && m_packagep == asamep->m_packagep); + } virtual bool similarDType(AstNodeDType* samep) const { - return skipRefp()->similarDType(samep->skipRefp()); } + return skipRefp()->similarDType(samep->skipRefp()); + } virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_refDTypep), V3Hash(m_packagep)); } - virtual void dump(std::ostream& str=std::cout) const; + virtual void dump(std::ostream& str = std::cout) const; virtual string name() const { return m_name; } virtual string prettyDTypeName() const { - return subDTypep() ? subDTypep()->name() : prettyName(); } + return subDTypep() ? subDTypep()->name() : prettyName(); + } virtual AstBasicDType* basicp() const { return subDTypep() ? subDTypep()->basicp() : NULL; } virtual AstNodeDType* skipRefp() const { // Skip past both the Ref and the Typedef - if (defp()) return defp()->skipRefp(); - else { v3fatalSrc("Typedef not linked"); return NULL; } + if (defp()) { + return defp()->skipRefp(); + } else { + v3fatalSrc("Typedef not linked"); + return NULL; + } } virtual AstNodeDType* skipRefToConstp() const { - if (defp()) return defp()->skipRefToConstp(); - else { v3fatalSrc("Typedef not linked"); return NULL; } + if (defp()) { + return defp()->skipRefToConstp(); + } else { + v3fatalSrc("Typedef not linked"); + return NULL; + } } virtual AstNodeDType* skipRefToEnump() const { - if (defp()) return defp()->skipRefToEnump(); - else { v3fatalSrc("Typedef not linked"); return NULL; } + if (defp()) { + return defp()->skipRefToEnump(); + } else { + v3fatalSrc("Typedef not linked"); + return NULL; + } } virtual int widthAlignBytes() const { return dtypeSkipRefp()->widthAlignBytes(); } virtual int widthTotalBytes() const { return dtypeSkipRefp()->widthTotalBytes(); } void name(const string& flag) { m_name = flag; } - AstNodeDType* dtypeSkipRefp() const { return defp()->skipRefp(); } // op1 = Range of variable - AstNodeDType* defp() const { return m_refDTypep; } // Code backward compatibility name for refDTypep + // op1 = Range of variable + AstNodeDType* dtypeSkipRefp() const { return defp()->skipRefp(); } + AstNodeDType* defp() const { + return m_refDTypep; + } // Code backward compatibility name for refDTypep AstNodeDType* refDTypep() const { return m_refDTypep; } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } virtual AstNodeDType* virtRefDTypep() const { return refDTypep(); } @@ -1044,7 +1189,7 @@ public: class AstUnionDType : public AstNodeUOrStructDType { public: - //UNSUP: bool isTagged; + // UNSUP: bool isTagged; // AstNumeric below is mispurposed to indicate if packed or not AstUnionDType(FileLine* fl, AstNumeric numericUnpack) : ASTGEN_SUPER(fl, numericUnpack) {} @@ -1057,21 +1202,23 @@ class AstMemberDType : public AstNodeDType { // PARENT: AstNodeUOrStructDType private: AstNodeDType* m_refDTypep; // Elements of this type (after widthing) - string m_name; // Name of variable - string m_tag; // Holds the string of the verilator tag -- used in XML output. - int m_lsb; // Within this level's packed struct, the LSB of the first bit of the member - //UNSUP: int m_randType; // Randomization type (IEEE) + string m_name; // Name of variable + string m_tag; // Holds the string of the verilator tag -- used in XML output. + int m_lsb; // Within this level's packed struct, the LSB of the first bit of the member + // UNSUP: int m_randType; // Randomization type (IEEE) public: AstMemberDType(FileLine* fl, const string& name, VFlagChildDType, AstNodeDType* dtp) : ASTGEN_SUPER(fl) - , m_name(name), m_lsb(-1) { + , m_name(name) + , m_lsb(-1) { childDTypep(dtp); // Only for parser dtypep(NULL); // V3Width will resolve refDTypep(NULL); } AstMemberDType(FileLine* fl, const string& name, AstNodeDType* dtp) : ASTGEN_SUPER(fl) - , m_name(name), m_lsb(-1) { + , m_name(name) + , m_lsb(-1) { UASSERT(dtp, "AstMember created with no dtype"); refDTypep(dtp); dtypep(this); @@ -1082,13 +1229,14 @@ public: virtual bool hasDType() const { return true; } virtual bool maybePointedTo() const { return true; } AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; } virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } - virtual bool similarDType(AstNodeDType* samep) const { return this==samep; } + virtual bool similarDType(AstNodeDType* samep) const { return this == samep; } // // (Slow) recurse down to find basic data type (Note don't need virtual - // AstVar isn't a NodeDType) @@ -1104,7 +1252,7 @@ public: virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } // METHODS virtual void name(const string& name) { m_name = name; } - virtual void tag(const string& text) { m_tag = text;} + virtual void tag(const string& text) { m_tag = text; } virtual string tag() const { return m_tag; } int lsb() const { return m_lsb; } void lsb(int lsb) { m_lsb = lsb; } @@ -1114,15 +1262,17 @@ class AstVoidDType : public AstNodeDType { // For e.g. a function returning void public: explicit AstVoidDType(FileLine* fl) - : ASTGEN_SUPER(fl) { dtypep(this); } + : ASTGEN_SUPER(fl) { + dtypep(this); + } ASTNODE_NODE_FUNCS(VoidDType) virtual void dumpSmall(std::ostream& str) const; virtual bool hasDType() const { return true; } virtual bool maybePointedTo() const { return true; } virtual AstNodeDType* subDTypep() const { return NULL; } virtual AstNodeDType* virtRefDTypep() const { return NULL; } - virtual void virtRefDTypep(AstNodeDType* nodep) { } - virtual bool similarDType(AstNodeDType* samep) const { return this==samep; } + virtual void virtRefDTypep(AstNodeDType* nodep) {} + virtual bool similarDType(AstNodeDType* samep) const { return this == samep; } virtual AstBasicDType* basicp() const { return NULL; } // cppcheck-suppress csyleCast virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } @@ -1137,12 +1287,16 @@ public: class AstEnumItem : public AstNode { private: - string m_name; + string m_name; + public: // Parents: ENUM AstEnumItem(FileLine* fl, const string& name, AstNode* rangep, AstNode* initp) - : ASTGEN_SUPER(fl), m_name(name) - { addNOp1p(rangep); addNOp2p(initp); } + : ASTGEN_SUPER(fl) + , m_name(name) { + addNOp1p(rangep); + addNOp2p(initp); + } ASTNODE_NODE_FUNCS(EnumItem) virtual string name() const { return m_name; } virtual bool maybePointedTo() const { return true; } @@ -1160,18 +1314,26 @@ private: AstNodeModule* m_packagep; // Package hierarchy public: AstEnumItemRef(FileLine* fl, AstEnumItem* itemp, AstNodeModule* packagep) - : ASTGEN_SUPER(fl), m_itemp(itemp), m_packagep(packagep) { + : ASTGEN_SUPER(fl) + , m_itemp(itemp) + , m_packagep(packagep) { dtypeFrom(m_itemp); } ASTNODE_NODE_FUNCS(EnumItemRef) virtual void dump(std::ostream& str) const; virtual string name() const { return itemp()->name(); } - virtual const char* broken() const { BROKEN_RTN(!VN_IS(itemp(), EnumItem)); return NULL; } + virtual const char* broken() const { + BROKEN_RTN(!VN_IS(itemp(), EnumItem)); + return NULL; + } virtual int instrCount() const { return 0; } - virtual void cloneRelink() { if (m_itemp->clonep()) m_itemp = VN_CAST(m_itemp->clonep(), EnumItem); } + virtual void cloneRelink() { + if (m_itemp->clonep()) m_itemp = VN_CAST(m_itemp->clonep(), EnumItem); + } virtual bool same(const AstNode* samep) const { const AstEnumItemRef* sp = static_cast(samep); - return itemp() == sp->itemp(); } + return itemp() == sp->itemp(); + } AstEnumItem* itemp() const { return m_itemp; } virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } virtual string emitC() { V3ERROR_NA_RETURN(""); } @@ -1187,6 +1349,7 @@ private: string m_name; // Name from upper typedef, if any AstNodeDType* m_refDTypep; // Elements are of this type after V3Width int m_uniqueNum; + public: AstEnumDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* itemsp) : ASTGEN_SUPER(fl) { @@ -1198,20 +1361,25 @@ public: m_uniqueNum = uniqueNumInc(); } ASTNODE_NODE_FUNCS(EnumDType) - virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) - || (!m_refDTypep && childDTypep()))); return NULL; } - virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) { - m_refDTypep = m_refDTypep->clonep(); - }} + virtual const char* broken() const { + BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) + || (!m_refDTypep && childDTypep()))); + return NULL; + } + virtual void cloneRelink() { + if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } + } virtual bool same(const AstNode* samep) const { const AstEnumDType* sp = static_cast(samep); - return m_uniqueNum == sp->m_uniqueNum; } - virtual bool similarDType(AstNodeDType* samep) const { return this==samep; } + return m_uniqueNum == sp->m_uniqueNum; + } + virtual bool similarDType(AstNodeDType* samep) const { return this == samep; } virtual V3Hash sameHash() const { return V3Hash(m_uniqueNum); } AstNodeDType* getChildDTypep() const { return childDTypep(); } AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Data type void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } // op1 = Range of variable + // op1 = Range of variable + virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; } virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } @@ -1220,7 +1388,7 @@ public: AstEnumItem* itemsp() const { return VN_CAST(op2p(), EnumItem); } // op2 = AstEnumItem's void addValuesp(AstNode* nodep) { addOp2p(nodep); } // METHODS - virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type + virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); } virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); } // cppcheck-suppress csyleCast @@ -1239,7 +1407,7 @@ public: ASTNODE_NODE_FUNCS(ParseTypeDType) AstNodeDType* dtypep() const { return NULL; } // METHODS - virtual bool similarDType(AstNodeDType* samep) const { return this==samep; } + virtual bool similarDType(AstNodeDType* samep) const { return this == samep; } virtual AstBasicDType* basicp() const { return NULL; } virtual AstNodeDType* skipRefp() const { return NULL; } // cppcheck-suppress csyleCast @@ -1262,6 +1430,7 @@ private: dtypeFrom(VN_CAST(fromp->dtypep()->skipRefp(), NodeArrayDType)->subDTypep()); } } + public: AstArraySel(FileLine* fl, AstNode* fromp, AstNode* bitp) : ASTGEN_SUPER(fl, fromp, bitp) { @@ -1272,9 +1441,12 @@ public: init(fromp); } ASTNODE_NODE_FUNCS(ArraySel) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstArraySel(this->fileline(), lhsp, rhsp); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstArraySel(this->fileline(), lhsp, rhsp); + } virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { - V3ERROR_NA; /* How can from be a const? */ } + V3ERROR_NA; /* How can from be a const? */ + } virtual string emitVerilog() { return "%k(%l%f[%r])"; } virtual string emitC() { return "%li%k[%ri]"; } virtual bool cleanOut() const { return true; } @@ -1288,7 +1460,8 @@ public: virtual bool same(const AstNode* samep) const { return true; } virtual int instrCount() const { return widthInstrs(); } // Special operators - static AstNode* baseFromp(AstNode* nodep); ///< What is the base variable (or const) this dereferences? + static AstNode* + baseFromp(AstNode* nodep); ///< What is the base variable (or const) this dereferences? }; class AstAssocSel : public AstNodeSel { @@ -1301,6 +1474,7 @@ private: dtypeFrom(VN_CAST(fromp->dtypep()->skipRefp(), AssocArrayDType)->subDTypep()); } } + public: AstAssocSel(FileLine* fl, AstNode* fromp, AstNode* bitp) : ASTGEN_SUPER(fl, fromp, bitp) { @@ -1308,9 +1482,11 @@ public: } ASTNODE_NODE_FUNCS(AssocSel) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { - return new AstAssocSel(this->fileline(), lhsp, rhsp); } + return new AstAssocSel(this->fileline(), lhsp, rhsp); + } virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { - V3ERROR_NA; } + V3ERROR_NA; + } virtual string emitVerilog() { return "%k(%l%f[%r])"; } virtual string emitC() { return "%li%k[%ri]"; } virtual bool cleanOut() const { return true; } @@ -1333,8 +1509,12 @@ public: dtypeSetUInt32(); // Always used on WData arrays so returns edata size } ASTNODE_NODE_FUNCS(WordSel) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstWordSel(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit) { V3ERROR_NA; } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstWordSel(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit) { + V3ERROR_NA; + } virtual string emitVerilog() { return "%k(%l%f[%r])"; } virtual string emitC() { return "%li[%ri]"; } // Not %k, as usually it's a small constant rhsp virtual bool cleanOut() const { return true; } @@ -1363,7 +1543,8 @@ public: AstSelBit(FileLine* fl, AstNode* fromp, AstNode* bitp) : ASTGEN_SUPER(fl, fromp, bitp, NULL) { UASSERT_OBJ(!v3Global.assertDTypesResolved(), this, - "not coded to create after dtypes resolved"); } + "not coded to create after dtypes resolved"); + } ASTNODE_NODE_FUNCS(SelBit) AstNode* bitp() const { return rhsp(); } }; @@ -1397,32 +1578,32 @@ class AstSel : public AstNodeTriop { // Tempting to have an lvalue() style method here as LHS selects are quite // different, but that doesn't play well with V3Inst and bidirects which don't know direction private: - VNumRange m_declRange; // Range of the 'from' array if isRanged() is set, else invalid - int m_declElWidth; // If a packed array, the number of bits per element + VNumRange m_declRange; // Range of the 'from' array if isRanged() is set, else invalid + int m_declElWidth; // If a packed array, the number of bits per element public: AstSel(FileLine* fl, AstNode* fromp, AstNode* lsbp, AstNode* widthp) : ASTGEN_SUPER(fl, fromp, lsbp, widthp) { m_declElWidth = 1; if (VN_IS(widthp, Const)) { - dtypeSetLogicSized(VN_CAST(widthp, Const)->toUInt(), - AstNumeric::UNSIGNED); + dtypeSetLogicSized(VN_CAST(widthp, Const)->toUInt(), AstNumeric::UNSIGNED); } } AstSel(FileLine* fl, AstNode* fromp, int lsb, int bitwidth) - : ASTGEN_SUPER(fl, fromp, - new AstConst(fl, lsb), new AstConst(fl, bitwidth)) { + : ASTGEN_SUPER(fl, fromp, new AstConst(fl, lsb), new AstConst(fl, bitwidth)) { m_declElWidth = 1; dtypeSetLogicSized(bitwidth, AstNumeric::UNSIGNED); } ASTNODE_NODE_FUNCS(Sel) virtual void dump(std::ostream& str) const; - virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit, const V3Number& width) { - out.opSel(from, bit.toUInt()+width.toUInt()-1, bit.toUInt()); } + virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit, + const V3Number& width) { + out.opSel(from, bit.toUInt() + width.toUInt() - 1, bit.toUInt()); + } virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } virtual string emitC() { - return this->widthp()->isOne() - ? "VL_BITSEL_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri)" - : "VL_SEL_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri, %ti)"; } + return this->widthp()->isOne() ? "VL_BITSEL_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri)" + : "VL_SEL_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri, %ti)"; + } virtual bool cleanOut() const { return false; } virtual bool cleanLhs() const { return true; } virtual bool cleanRhs() const { return true; } @@ -1432,13 +1613,13 @@ public: virtual bool sizeMattersThs() const { return false; } virtual V3Hash sameHash() const { return V3Hash(); } virtual bool same(const AstNode*) const { return true; } - virtual int instrCount() const { return widthInstrs()*(VN_CAST(lsbp(), Const)?3:10); } + virtual int instrCount() const { return widthInstrs() * (VN_CAST(lsbp(), Const) ? 3 : 10); } AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing) AstNode* lsbp() const { return op2p(); } // op2 = Msb selection expression AstNode* widthp() const { return op3p(); } // op3 = Width int widthConst() const { return VN_CAST(widthp(), Const)->toSInt(); } int lsbConst() const { return VN_CAST(lsbp(), Const)->toSInt(); } - int msbConst() const { return lsbConst()+widthConst()-1; } + int msbConst() const { return lsbConst() + widthConst() - 1; } VNumRange& declRange() { return m_declRange; } const VNumRange& declRange() const { return m_declRange; } void declRange(const VNumRange& flag) { m_declRange = flag; } @@ -1454,14 +1635,15 @@ private: VNumRange m_declRange; // Range of the 'from' array if isRanged() is set, else invalid public: AstSliceSel(FileLine* fl, AstNode* fromp, const VNumRange& declRange) - : ASTGEN_SUPER(fl, fromp, - new AstConst(fl, declRange.lo()), + : ASTGEN_SUPER(fl, fromp, new AstConst(fl, declRange.lo()), new AstConst(fl, declRange.elements())) - , m_declRange(declRange) { } + , m_declRange(declRange) {} ASTNODE_NODE_FUNCS(SliceSel) virtual void dump(std::ostream& str) const; - virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& lo, const V3Number& width) { - V3ERROR_NA; } + virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& lo, + const V3Number& width) { + V3ERROR_NA; + } virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } virtual string emitC() { V3ERROR_NA_RETURN(""); } // Removed before EmitC virtual bool cleanOut() const { return false; } @@ -1505,7 +1687,10 @@ public: } virtual void dump(std::ostream& str) const; virtual bool hasDType() const { return true; } - void makeStatement() { statement(true); dtypeSetVoid(); } + void makeStatement() { + statement(true); + dtypeSetVoid(); + } AstNode* fromp() const { return op2p(); } // op2 = Extracting what (NULL=TBD during parsing) void fromp(AstNode* nodep) { setOp2p(nodep); } }; @@ -1541,10 +1726,14 @@ public: virtual V3Hash sameHash() const { return V3Hash(m_name); } virtual bool same(const AstNode* samep) const { const AstCMethodHard* asamep = static_cast(samep); - return (m_name == asamep->m_name); } + return (m_name == asamep->m_name); + } virtual bool isPure() const { return m_pure; } void pure(bool flag) { m_pure = flag; } - void makeStatement() { statement(true); dtypeSetVoid(); } + void makeStatement() { + statement(true); + dtypeSetVoid(); + } AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing) void fromp(AstNode* nodep) { setOp1p(nodep); } AstNode* pinsp() const { return op2p(); } // op2 = Pin interconnection list @@ -1554,87 +1743,115 @@ public: class AstVar : public AstNode { // A variable (in/out/wire/reg/param) inside a module private: - string m_name; // Name of variable - string m_origName; // Original name before dot addition - string m_tag; // Holds the string of the verilator tag -- used in XML output. - AstVarType m_varType; // Type of variable - VDirection m_direction; // Direction input/output etc - VDirection m_declDirection; // Declared direction input/output etc + string m_name; // Name of variable + string m_origName; // Original name before dot addition + string m_tag; // Holds the string of the verilator tag -- used in XML output. + AstVarType m_varType; // Type of variable + VDirection m_direction; // Direction input/output etc + VDirection m_declDirection; // Declared direction input/output etc AstBasicDTypeKwd m_declKwd; // Keyword at declaration time - bool m_ansi:1; // ANSI port list variable (for dedup check) - bool m_declTyped:1; // Declared as type (for dedup check) - bool m_tristate:1; // Inout or triwire or trireg - bool m_primaryIO:1; // In/out to top level (or directly assigned from same) - bool m_sc:1; // SystemC variable - bool m_scClocked:1; // SystemC sc_clk<> needed - bool m_scSensitive:1;// SystemC sensitive() needed - bool m_sigPublic:1; // User C code accesses this signal or is top signal - bool m_sigModPublic:1;// User C code accesses this signal and module - bool m_sigUserRdPublic:1; // User C code accesses this signal, read only - bool m_sigUserRWPublic:1; // User C code accesses this signal, read-write - bool m_usedClock:1; // Signal used as a clock - bool m_usedParam:1; // Parameter is referenced (on link; later signals not setup) - bool m_usedLoopIdx:1; // Variable subject of for unrolling - bool m_funcLocal:1; // Local variable for a function - bool m_funcReturn:1; // Return variable for a function - bool m_attrClockEn:1;// User clock enable attribute - bool m_attrScBv:1; // User force bit vector attribute - bool m_attrIsolateAssign:1;// User isolate_assignments attribute - bool m_attrSFormat:1;// User sformat attribute - bool m_attrSplitVar:1; // declared with split_var metacomment - bool m_fileDescr:1; // File descriptor - bool m_isConst:1; // Table contains constant data - bool m_isStatic:1; // Static variable - bool m_isPulldown:1; // Tri0 - bool m_isPullup:1; // Tri1 - bool m_isIfaceParent:1; // dtype is reference to interface present in this module - bool m_isDpiOpenArray:1; // DPI import open array - bool m_noReset:1; // Do not do automated reset/randomization - bool m_noSubst:1; // Do not substitute out references - bool m_trace:1; // Trace this variable + bool m_ansi : 1; // ANSI port list variable (for dedup check) + bool m_declTyped : 1; // Declared as type (for dedup check) + bool m_tristate : 1; // Inout or triwire or trireg + bool m_primaryIO : 1; // In/out to top level (or directly assigned from same) + bool m_sc : 1; // SystemC variable + bool m_scClocked : 1; // SystemC sc_clk<> needed + bool m_scSensitive : 1; // SystemC sensitive() needed + bool m_sigPublic : 1; // User C code accesses this signal or is top signal + bool m_sigModPublic : 1; // User C code accesses this signal and module + bool m_sigUserRdPublic : 1; // User C code accesses this signal, read only + bool m_sigUserRWPublic : 1; // User C code accesses this signal, read-write + bool m_usedClock : 1; // Signal used as a clock + bool m_usedParam : 1; // Parameter is referenced (on link; later signals not setup) + bool m_usedLoopIdx : 1; // Variable subject of for unrolling + bool m_funcLocal : 1; // Local variable for a function + bool m_funcReturn : 1; // Return variable for a function + bool m_attrClockEn : 1; // User clock enable attribute + bool m_attrScBv : 1; // User force bit vector attribute + bool m_attrIsolateAssign : 1; // User isolate_assignments attribute + bool m_attrSFormat : 1; // User sformat attribute + bool m_attrSplitVar : 1; // declared with split_var metacomment + bool m_fileDescr : 1; // File descriptor + bool m_isConst : 1; // Table contains constant data + bool m_isStatic : 1; // Static variable + bool m_isPulldown : 1; // Tri0 + bool m_isPullup : 1; // Tri1 + bool m_isIfaceParent : 1; // dtype is reference to interface present in this module + bool m_isDpiOpenArray : 1; // DPI import open array + bool m_noReset : 1; // Do not do automated reset/randomization + bool m_noSubst : 1; // Do not substitute out references + bool m_trace : 1; // Trace this variable VVarAttrClocker m_attrClocker; - MTaskIdSet m_mtaskIds; // MTaskID's that read or write this var + MTaskIdSet m_mtaskIds; // MTaskID's that read or write this var void init() { - m_ansi = false; m_declTyped = false; - m_tristate = false; m_primaryIO = false; - m_sc = false; m_scClocked = false; m_scSensitive = false; - m_usedClock = false; m_usedParam = false; m_usedLoopIdx = false; - m_sigPublic = false; m_sigModPublic = false; - m_sigUserRdPublic = false; m_sigUserRWPublic = false; - m_funcLocal = false; m_funcReturn = false; - m_attrClockEn = false; m_attrScBv = false; - m_attrIsolateAssign = false; m_attrSFormat = false; m_attrSplitVar = false; - m_fileDescr = false; m_isConst = false; - m_isStatic = false; m_isPulldown = false; m_isPullup = false; - m_isIfaceParent = false; m_isDpiOpenArray = false; - m_noReset = false; m_noSubst = false; m_trace = false; + m_ansi = false; + m_declTyped = false; + m_tristate = false; + m_primaryIO = false; + m_sc = false; + m_scClocked = false; + m_scSensitive = false; + m_usedClock = false; + m_usedParam = false; + m_usedLoopIdx = false; + m_sigPublic = false; + m_sigModPublic = false; + m_sigUserRdPublic = false; + m_sigUserRWPublic = false; + m_funcLocal = false; + m_funcReturn = false; + m_attrClockEn = false; + m_attrScBv = false; + m_attrIsolateAssign = false; + m_attrSFormat = false; + m_attrSplitVar = false; + m_fileDescr = false; + m_isConst = false; + m_isStatic = false; + m_isPulldown = false; + m_isPullup = false; + m_isIfaceParent = false; + m_isDpiOpenArray = false; + m_noReset = false; + m_noSubst = false; + m_trace = false; m_attrClocker = VVarAttrClocker::CLOCKER_UNKNOWN; } + public: AstVar(FileLine* fl, AstVarType type, const string& name, VFlagChildDType, AstNodeDType* dtp) : ASTGEN_SUPER(fl) - , m_name(name), m_origName(name) { + , m_name(name) + , m_origName(name) { init(); combineType(type); childDTypep(dtp); // Only for parser dtypep(NULL); // V3Width will resolve - if (dtp->basicp()) m_declKwd = dtp->basicp()->keyword(); - else m_declKwd = AstBasicDTypeKwd::LOGIC; + if (dtp->basicp()) { + m_declKwd = dtp->basicp()->keyword(); + } else { + m_declKwd = AstBasicDTypeKwd::LOGIC; + } } AstVar(FileLine* fl, AstVarType type, const string& name, AstNodeDType* dtp) : ASTGEN_SUPER(fl) - , m_name(name), m_origName(name) { + , m_name(name) + , m_origName(name) { init(); combineType(type); UASSERT(dtp, "AstVar created with no dtype"); dtypep(dtp); - if (dtp->basicp()) m_declKwd = dtp->basicp()->keyword(); - else m_declKwd = AstBasicDTypeKwd::LOGIC; + if (dtp->basicp()) { + m_declKwd = dtp->basicp()->keyword(); + } else { + m_declKwd = AstBasicDTypeKwd::LOGIC; + } } AstVar(FileLine* fl, AstVarType type, const string& name, VFlagLogicPacked, int wantwidth) : ASTGEN_SUPER(fl) - , m_name(name), m_origName(name) { + , m_name(name) + , m_origName(name) { init(); combineType(type); dtypeSetLogicSized(wantwidth, AstNumeric::UNSIGNED); @@ -1642,7 +1859,8 @@ public: } AstVar(FileLine* fl, AstVarType type, const string& name, VFlagBitPacked, int wantwidth) : ASTGEN_SUPER(fl) - , m_name(name), m_origName(name) { + , m_name(name) + , m_origName(name) { init(); combineType(type); dtypeSetBitSized(wantwidth, AstNumeric::UNSIGNED); @@ -1650,12 +1868,11 @@ public: } AstVar(FileLine* fl, AstVarType type, const string& name, AstVar* examplep) : ASTGEN_SUPER(fl) - , m_name(name), m_origName(name) { + , m_name(name) + , m_origName(name) { init(); combineType(type); - if (examplep->childDTypep()) { - childDTypep(examplep->childDTypep()->cloneTree(true)); - } + if (examplep->childDTypep()) { childDTypep(examplep->childDTypep()->cloneTree(true)); } dtypeFrom(examplep); m_declKwd = examplep->declKwd(); } @@ -1669,32 +1886,43 @@ public: AstVarType varType() const { return m_varType; } // * = Type of variable void direction(const VDirection& flag) { m_direction = flag; - if (m_direction == VDirection::INOUT) m_tristate = true; } + if (m_direction == VDirection::INOUT) m_tristate = true; + } VDirection direction() const { return m_direction; } bool isIO() const { return m_direction != VDirection::NONE; } void declDirection(const VDirection& flag) { m_declDirection = flag; } VDirection declDirection() const { return m_declDirection; } void varType(AstVarType type) { m_varType = type; } - void varType2Out() { m_tristate = 0; m_direction = VDirection::OUTPUT; } - void varType2In() { m_tristate = 0; m_direction = VDirection::INPUT; } + void varType2Out() { + m_tristate = 0; + m_direction = VDirection::OUTPUT; + } + void varType2In() { + m_tristate = 0; + m_direction = VDirection::INPUT; + } AstBasicDTypeKwd declKwd() const { return m_declKwd; } string scType() const; // Return SysC type: bool, uint32_t, uint64_t, sc_bv - string cPubArgType(bool named, bool forReturn) const; // Return C /*public*/ type for argument: bool, uint32_t, uint64_t, etc. + // Return C /*public*/ type for argument: bool, uint32_t, uint64_t, etc. + string cPubArgType(bool named, bool forReturn) const; string dpiArgType(bool named, bool forReturn) const; // Return DPI-C type for argument // Return Verilator internal type for argument: CData, SData, IData, WData - string vlArgType(bool named, bool forReturn, bool forFunc, const string& namespc="") const; + string vlArgType(bool named, bool forReturn, bool forFunc, const string& namespc = "") const; string vlEnumType() const; // Return VerilatorVarType: VLVT_UINT32, etc string vlEnumDir() const; // Return VerilatorVarDir: VLVD_INOUT, etc string vlPropInit() const; // Return VerilatorVarProps initializer void combineType(AstVarType type); AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Range of variable + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - // AstVar isn't a NodeDType) AstBasicDType* basicp() const { return subDTypep()->basicp(); } - AstNode* valuep() const { return op3p(); } // op3 = Initial value that never changes (static const) - void valuep(AstNode* nodep) { setOp3p(nodep); } // It's valuep, not constp, as may be more complicated than an AstConst + // op3 = Initial value that never changes (static const) + AstNode* valuep() const { return op3p(); } + // It's valuep(), not constp(), as may be more complicated than an AstConst + void valuep(AstNode* nodep) { setOp3p(nodep); } void addAttrsp(AstNode* nodep) { addNOp4p(nodep); } AstNode* attrsp() const { return op4p(); } // op4 = Attributes during early parse void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } @@ -1714,8 +1942,14 @@ public: void usedLoopIdx(bool flag) { m_usedLoopIdx = flag; } void sigPublic(bool flag) { m_sigPublic = flag; } void sigModPublic(bool flag) { m_sigModPublic = flag; } - void sigUserRdPublic(bool flag) { m_sigUserRdPublic = flag; if (flag) sigPublic(true); } - void sigUserRWPublic(bool flag) { m_sigUserRWPublic = flag; if (flag) sigUserRdPublic(true); } + void sigUserRdPublic(bool flag) { + m_sigUserRdPublic = flag; + if (flag) sigPublic(true); + } + void sigUserRWPublic(bool flag) { + m_sigUserRWPublic = flag; + if (flag) sigUserRdPublic(true); + } void sc(bool flag) { m_sc = flag; } void scSensitive(bool flag) { m_scSensitive = flag; } void primaryIO(bool flag) { m_primaryIO = flag; } @@ -1733,7 +1967,7 @@ public: void trace(bool flag) { m_trace = flag; } // METHODS virtual void name(const string& name) { m_name = name; } - virtual void tag(const string& text) { m_tag = text;} + virtual void tag(const string& text) { m_tag = text; } virtual string tag() const { return m_tag; } bool isAnsi() const { return m_ansi; } bool isDeclTyped() const { return m_declTyped; } @@ -1744,7 +1978,7 @@ public: bool isTristate() const { return m_tristate; } bool isPrimaryIO() const { return m_primaryIO; } bool isPrimaryInish() const { return isPrimaryIO() && isNonOutput(); } - bool isIfaceRef() const { return (varType()==AstVarType::IFACEREF); } + bool isIfaceRef() const { return (varType() == AstVarType::IFACEREF); } bool isIfaceParent() const { return m_isIfaceParent; } bool isSignal() const { return varType().isSignal(); } bool isTemp() const { return varType().isTemp(); } @@ -1752,15 +1986,21 @@ public: return ((isIO() || isSignal()) && (isIO() || isBitLogic()) // Wrapper would otherwise duplicate wrapped module's coverage - && !isSc() && !isPrimaryIO() && !isConst()); } + && !isSc() && !isPrimaryIO() && !isConst()); + } bool isClassMember() const { return varType() == AstVarType::MEMBER; } - bool isStatementTemp() const { return (varType()==AstVarType::STMTTEMP); } - bool isMovableToBlock() const { return (varType()==AstVarType::BLOCKTEMP || isFuncLocal()); } - bool isXTemp() const { return (varType()==AstVarType::XTEMP); } - bool isParam() const { return (varType()==AstVarType::LPARAM || varType()==AstVarType::GPARAM); } - bool isGParam() const { return (varType()==AstVarType::GPARAM); } - bool isGenVar() const { return (varType()==AstVarType::GENVAR); } - bool isBitLogic() const { AstBasicDType* bdtypep = basicp(); return bdtypep && bdtypep->isBitLogic(); } + bool isStatementTemp() const { return (varType() == AstVarType::STMTTEMP); } + bool isMovableToBlock() const { return (varType() == AstVarType::BLOCKTEMP || isFuncLocal()); } + bool isXTemp() const { return (varType() == AstVarType::XTEMP); } + bool isParam() const { + return (varType() == AstVarType::LPARAM || varType() == AstVarType::GPARAM); + } + bool isGParam() const { return (varType() == AstVarType::GPARAM); } + bool isGenVar() const { return (varType() == AstVarType::GENVAR); } + bool isBitLogic() const { + AstBasicDType* bdtypep = basicp(); + return bdtypep && bdtypep->isBitLogic(); + } bool isUsedClock() const { return m_usedClock; } bool isUsedParam() const { return m_usedParam; } bool isUsedLoopIdx() const { return m_usedLoopIdx; } @@ -1813,7 +2053,7 @@ public: if (typevarp->attrScClocked()) attrScClocked(true); } void inlineAttrReset(const string& name) { - if (direction()==VDirection::INOUT && varType()==AstVarType::WIRE) { + if (direction() == VDirection::INOUT && varType() == AstVarType::WIRE) { m_varType = AstVarType::TRIWIRE; } m_direction = VDirection::NONE; @@ -1824,6 +2064,7 @@ public: void addConsumingMTaskId(int id) { m_mtaskIds.insert(id); } const MTaskIdSet& mtaskIds() const { return m_mtaskIds; } string mtasksString() const; + private: class VlArgTypeRecursed; VlArgTypeRecursed vlArgTypeRecurse(bool forFunc, const AstNodeDType* dtypep, @@ -1835,8 +2076,8 @@ class AstDefParam : public AstNode { // Parents: MODULE // Children: math private: - string m_name; // Name of variable getting set - string m_path; // Dotted cellname to set parameter of + string m_name; // Name of variable getting set + string m_path; // Dotted cellname to set parameter of public: AstDefParam(FileLine* fl, const string& path, const string& name, AstNode* rhsp) : ASTGEN_SUPER(fl) { @@ -1871,15 +2112,18 @@ class AstScope : public AstNode { // Children: NODEBLOCK private: // An AstScope->name() is special: . indicates an uninlined scope, __DOT__ an inlined scope - string m_name; // Name - AstScope* m_aboveScopep; // Scope above this one in the hierarchy (NULL if top) - AstCell* m_aboveCellp; // Cell above this in the hierarchy (NULL if top) - AstNodeModule* m_modp; // Module scope corresponds to + string m_name; // Name + AstScope* m_aboveScopep; // Scope above this one in the hierarchy (NULL if top) + AstCell* m_aboveCellp; // Cell above this in the hierarchy (NULL if top) + AstNodeModule* m_modp; // Module scope corresponds to public: - AstScope(FileLine* fl, AstNodeModule* modp, const string& name, - AstScope* aboveScopep, AstCell* aboveCellp) + AstScope(FileLine* fl, AstNodeModule* modp, const string& name, AstScope* aboveScopep, + AstCell* aboveCellp) : ASTGEN_SUPER(fl) - , m_name(name), m_aboveScopep(aboveScopep), m_aboveCellp(aboveCellp), m_modp(modp) {} + , m_name(name) + , m_aboveScopep(aboveScopep) + , m_aboveCellp(aboveCellp) + , m_modp(modp) {} ASTNODE_NODE_FUNCS(Scope) virtual void cloneRelink(); virtual const char* broken() const; @@ -1897,7 +2141,7 @@ public: AstNode* finalClksp() const { return op3p(); } // op3 = Final assigns for clock correction AstScope* aboveScopep() const { return m_aboveScopep; } AstCell* aboveCellp() const { return m_aboveCellp; } - bool isTop() const { return aboveScopep()==NULL; } // At top of hierarchy + bool isTop() const { return aboveScopep() == NULL; } // At top of hierarchy }; class AstTopScope : public AstNode { @@ -1907,8 +2151,9 @@ class AstTopScope : public AstNode { // Children: SCOPEs public: AstTopScope(FileLine* fl, AstScope* ascopep) - : ASTGEN_SUPER(fl) - {addNOp2p(ascopep);} + : ASTGEN_SUPER(fl) { + addNOp2p(ascopep); + } ASTNODE_NODE_FUNCS(TopScope) AstNode* stmtsp() const { return op1p(); } void addStmtsp(AstNode* nodep) { addOp1p(nodep); } @@ -1922,33 +2167,40 @@ class AstVarScope : public AstNode { // Parents: MODULE // Children: none private: - AstScope* m_scopep; // Scope variable is underneath - AstVar* m_varp; // [AfterLink] Pointer to variable itself - bool m_circular:1; // Used in circular ordering dependency, need change detect - bool m_trace:1; // Tracing is turned on for this scope + AstScope* m_scopep; // Scope variable is underneath + AstVar* m_varp; // [AfterLink] Pointer to variable itself + bool m_circular : 1; // Used in circular ordering dependency, need change detect + bool m_trace : 1; // Tracing is turned on for this scope public: AstVarScope(FileLine* fl, AstScope* scopep, AstVar* varp) : ASTGEN_SUPER(fl) - , m_scopep(scopep), m_varp(varp) { + , m_scopep(scopep) + , m_varp(varp) { m_circular = false; m_trace = true; dtypeFrom(varp); } ASTNODE_NODE_FUNCS(VarScope) - virtual void cloneRelink() { if (m_varp && m_varp->clonep()) { - m_varp = m_varp->clonep(); - UASSERT(m_scopep->clonep(), "No clone cross link: "<clonep(); - }} - virtual const char* broken() const { BROKEN_RTN(m_varp && !m_varp->brokeExists()); - BROKEN_RTN(m_scopep && !m_scopep->brokeExists()); return NULL; } + virtual void cloneRelink() { + if (m_varp && m_varp->clonep()) { + m_varp = m_varp->clonep(); + UASSERT(m_scopep->clonep(), "No clone cross link: " << this); + m_scopep = m_scopep->clonep(); + } + } + virtual const char* broken() const { + BROKEN_RTN(m_varp && !m_varp->brokeExists()); + BROKEN_RTN(m_scopep && !m_scopep->brokeExists()); + return NULL; + } virtual bool maybePointedTo() const { return true; } - virtual string name() const {return scopep()->name()+"->"+varp()->name();} // * = Var name + virtual string name() const { return scopep()->name() + "->" + varp()->name(); } virtual void dump(std::ostream& str) const; virtual bool hasDType() const { return true; } AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable AstScope* scopep() const { return m_scopep; } // Pointer to scope it's under - AstNode* valuep() const { return op1p(); } // op1 = Calculation of value of variable, NULL=complicated + // op1 = Calculation of value of variable, NULL=complicated + AstNode* valuep() const { return op1p(); } void valuep(AstNode* valuep) { addOp1p(valuep); } bool isCircular() const { return m_circular; } void circular(bool flag) { m_circular = flag; } @@ -1974,18 +2226,24 @@ public: virtual void dump(std::ostream& str) const; virtual V3Hash sameHash() const { return V3Hash(V3Hash(varp()->name()), V3Hash(hiername())); } virtual bool same(const AstNode* samep) const { - return same(static_cast(samep)); } + return same(static_cast(samep)); + } inline bool same(const AstVarRef* samep) const { - if (varScopep()) return (varScopep()==samep->varScopep() - && lvalue()==samep->lvalue()); - else return (hiername()==samep->hiername() - && varp()->name()==samep->varp()->name() - && lvalue()==samep->lvalue()); } + if (varScopep()) { + return (varScopep() == samep->varScopep() && lvalue() == samep->lvalue()); + } else { + return (hiername() == samep->hiername() && varp()->name() == samep->varp()->name() + && lvalue() == samep->lvalue()); + } + } inline bool sameNoLvalue(AstVarRef* samep) const { - if (varScopep()) return (varScopep()==samep->varScopep()); - else return (hiername()==samep->hiername() - && varp()->name()==samep->varp()->name()); } - virtual int instrCount() const { return widthInstrs()*(lvalue()?1:instrCountLd()); } + if (varScopep()) { + return (varScopep() == samep->varScopep()); + } else { + return (hiername() == samep->hiername() && varp()->name() == samep->varp()->name()); + } + } + virtual int instrCount() const { return widthInstrs() * (lvalue() ? 1 : instrCountLd()); } virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const { return true; } @@ -1995,12 +2253,12 @@ class AstVarXRef : public AstNodeVarRef { // A VarRef to something in another module before AstScope. // Includes pin on a cell, as part of a ASSIGN statement to connect I/Os until AstScope private: - string m_dotted; // Dotted part of scope the name()'ed reference is under or "" - string m_inlinedDots; // Dotted hierarchy flattened out + string m_dotted; // Dotted part of scope the name()'ed reference is under or "" + string m_inlinedDots; // Dotted hierarchy flattened out public: AstVarXRef(FileLine* fl, const string& name, const string& dotted, bool lvalue) : ASTGEN_SUPER(fl, name, NULL, lvalue) - , m_dotted(dotted) { } + , m_dotted(dotted) {} AstVarXRef(FileLine* fl, AstVar* varp, const string& dotted, bool lvalue) : ASTGEN_SUPER(fl, varp->name(), varp, lvalue) , m_dotted(dotted) { @@ -2020,32 +2278,35 @@ public: virtual V3Hash sameHash() const { return V3Hash(V3Hash(varp()), V3Hash(dotted())); } virtual bool same(const AstNode* samep) const { const AstVarXRef* asamep = static_cast(samep); - return (hiername() == asamep->hiername() - && varp() == asamep->varp() - && name() == asamep->name() - && dotted() == asamep->dotted()); } + return (hiername() == asamep->hiername() && varp() == asamep->varp() + && name() == asamep->name() && dotted() == asamep->dotted()); + } }; class AstPin : public AstNode { // A pin on a cell private: - int m_pinNum; // Pin number - string m_name; // Pin name, or "" for number based interconnect - AstVar* m_modVarp; // Input/output this pin connects to on submodule. - AstParamTypeDType* m_modPTypep; // Param type this pin connects to on submodule. - bool m_param; // Pin connects to parameter - bool m_svImplicit; // Pin is SystemVerilog .name'ed + int m_pinNum; // Pin number + string m_name; // Pin name, or "" for number based interconnect + AstVar* m_modVarp; // Input/output this pin connects to on submodule. + AstParamTypeDType* m_modPTypep; // Param type this pin connects to on submodule. + bool m_param; // Pin connects to parameter + bool m_svImplicit; // Pin is SystemVerilog .name'ed public: AstPin(FileLine* fl, int pinNum, const string& name, AstNode* exprp) : ASTGEN_SUPER(fl) - , m_name(name), m_param(false), m_svImplicit(false) { + , m_name(name) + , m_param(false) + , m_svImplicit(false) { m_pinNum = pinNum; m_modVarp = NULL; m_modPTypep = NULL; setNOp1p(exprp); } AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp) - : ASTGEN_SUPER(fl), m_param(false), m_svImplicit(false) { + : ASTGEN_SUPER(fl) + , m_param(false) + , m_svImplicit(false) { m_name = varname->name(); m_pinNum = pinNum; m_modVarp = NULL; @@ -2057,22 +2318,26 @@ public: virtual const char* broken() const { BROKEN_RTN(m_modVarp && !m_modVarp->brokeExists()); BROKEN_RTN(m_modPTypep && !m_modPTypep->brokeExists()); - return NULL; } + return NULL; + } virtual string name() const { return m_name; } // * = Pin name, ""=go by number virtual void name(const string& name) { m_name = name; } virtual string prettyOperatorName() const { - return modVarp() ? ((modVarp()->direction().isAny() - ? modVarp()->direction().prettyName()+" " - : "") - +"port connection "+modVarp()->prettyNameQ()) - : "port connection"; } + return modVarp() + ? ((modVarp()->direction().isAny() ? modVarp()->direction().prettyName() + " " + : "") + + "port connection " + modVarp()->prettyNameQ()) + : "port connection"; + } bool dotStar() const { return name() == ".*"; } // Fake name for .* connections until linked int pinNum() const { return m_pinNum; } void exprp(AstNode* nodep) { addOp1p(nodep); } - AstNode* exprp() const { return op1p(); } // op1 = Expression connected to pin, NULL if unconnected + // op1 = Expression connected to pin, NULL if unconnected + AstNode* exprp() const { return op1p(); } AstVar* modVarp() const { return m_modVarp; } // [After Link] Pointer to variable void modVarp(AstVar* nodep) { m_modVarp = nodep; } - AstParamTypeDType* modPTypep() const { return m_modPTypep; } // [After Link] Pointer to variable + // [After Link] Pointer to variable + AstParamTypeDType* modPTypep() const { return m_modPTypep; } void modPTypep(AstParamTypeDType* nodep) { m_modPTypep = nodep; } bool param() const { return m_param; } void param(bool flag) { m_param = flag; } @@ -2083,7 +2348,7 @@ public: class AstArg : public AstNode { // An argument to a function/task private: - string m_name; // Pin name, or "" for number based interconnect + string m_name; // Pin name, or "" for number based interconnect public: AstArg(FileLine* fl, const string& name, AstNode* exprp) : ASTGEN_SUPER(fl) @@ -2095,8 +2360,9 @@ public: virtual void name(const string& name) { m_name = name; } virtual V3Hash sameHash() const { return V3Hash(); } void exprp(AstNode* nodep) { addOp1p(nodep); } - AstNode* exprp() const { return op1p(); } // op1 = Expression connected to pin, NULL if unconnected - bool emptyConnectNoNext() const { return !exprp() && name()=="" && !nextp(); } + // op1 = Expression connected to pin, NULL if unconnected + AstNode* exprp() const { return op1p(); } + bool emptyConnectNoNext() const { return !exprp() && name() == "" && !nextp(); } }; class AstModule : public AstNodeModule { @@ -2149,14 +2415,21 @@ public: class AstPackageExport : public AstNode { private: // A package export declaration - string m_name; - AstPackage* m_packagep; // Package hierarchy + string m_name; + AstPackage* m_packagep; // Package hierarchy public: AstPackageExport(FileLine* fl, AstPackage* packagep, const string& name) - : ASTGEN_SUPER(fl), m_name(name), m_packagep(packagep) {} + : ASTGEN_SUPER(fl) + , m_name(name) + , m_packagep(packagep) {} ASTNODE_NODE_FUNCS(PackageExport) - virtual const char* broken() const { BROKEN_RTN(!m_packagep || !m_packagep->brokeExists()); return NULL; } - virtual void cloneRelink() { if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep(); } + virtual const char* broken() const { + BROKEN_RTN(!m_packagep || !m_packagep->brokeExists()); + return NULL; + } + virtual void cloneRelink() { + if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep(); + } virtual void dump(std::ostream& str) const; virtual string name() const { return m_name; } AstPackage* packagep() const { return m_packagep; } @@ -2166,14 +2439,21 @@ public: class AstPackageImport : public AstNode { private: // A package import declaration - string m_name; - AstPackage* m_packagep; // Package hierarchy + string m_name; + AstPackage* m_packagep; // Package hierarchy public: AstPackageImport(FileLine* fl, AstPackage* packagep, const string& name) - : ASTGEN_SUPER(fl), m_name(name), m_packagep(packagep) {} + : ASTGEN_SUPER(fl) + , m_name(name) + , m_packagep(packagep) {} ASTNODE_NODE_FUNCS(PackageImport) - virtual const char* broken() const { BROKEN_RTN(!m_packagep || !m_packagep->brokeExists()); return NULL; } - virtual void cloneRelink() { if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep(); } + virtual const char* broken() const { + BROKEN_RTN(!m_packagep || !m_packagep->brokeExists()); + return NULL; + } + virtual void cloneRelink() { + if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep(); + } virtual void dump(std::ostream& str) const; virtual string name() const { return m_name; } AstPackage* packagep() const { return m_packagep; } @@ -2184,7 +2464,7 @@ class AstIface : public AstNodeModule { // A module declaration public: AstIface(FileLine* fl, const string& name) - : ASTGEN_SUPER(fl, name) { } + : ASTGEN_SUPER(fl, name) {} ASTNODE_NODE_FUNCS(Iface) }; @@ -2211,14 +2491,19 @@ public: dtypep(dtp); } ASTNODE_NODE_FUNCS(MemberSel) - virtual void cloneRelink() { if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep(); } } + virtual void cloneRelink() { + if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep(); } + } virtual const char* broken() const { - BROKEN_RTN(m_varp && !m_varp->brokeExists()); return NULL; } + BROKEN_RTN(m_varp && !m_varp->brokeExists()); + return NULL; + } virtual void dump(std::ostream& str) const; virtual string name() const { return m_name; } virtual V3Hash sameHash() const { return V3Hash(m_name); } virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { - V3ERROR_NA; /* How can from be a const? */ } + V3ERROR_NA; /* How can from be a const? */ + } virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const { return false; } @@ -2236,17 +2521,25 @@ class AstModportFTaskRef : public AstNode { // interface/instantiator, thus this is a reference // PARENT: AstModport private: - string m_name; // Name of the variable referenced - bool m_export; // Type of the function (import/export) - AstNodeFTask* m_ftaskp; // Link to the function + string m_name; // Name of the variable referenced + bool m_export; // Type of the function (import/export) + AstNodeFTask* m_ftaskp; // Link to the function public: AstModportFTaskRef(FileLine* fl, const string& name, bool isExport) - : ASTGEN_SUPER(fl), m_name(name), m_export(isExport), m_ftaskp(NULL) { } + : ASTGEN_SUPER(fl) + , m_name(name) + , m_export(isExport) + , m_ftaskp(NULL) {} ASTNODE_NODE_FUNCS(ModportFTaskRef) - virtual const char* broken() const { BROKEN_RTN(m_ftaskp && !m_ftaskp->brokeExists()); return NULL; } + virtual const char* broken() const { + BROKEN_RTN(m_ftaskp && !m_ftaskp->brokeExists()); + return NULL; + } virtual void dump(std::ostream& str) const; virtual string name() const { return m_name; } - virtual void cloneRelink() { if (m_ftaskp && m_ftaskp->clonep()) m_ftaskp = m_ftaskp->clonep(); } + virtual void cloneRelink() { + if (m_ftaskp && m_ftaskp->clonep()) m_ftaskp = m_ftaskp->clonep(); + } bool isImport() const { return !m_export; } bool isExport() const { return m_export; } AstNodeFTask* ftaskp() const { return m_ftaskp; } // [After Link] Pointer to variable @@ -2258,16 +2551,24 @@ class AstModportVarRef : public AstNode { // The storage for the variable itself is inside the interface, thus this is a reference // PARENT: AstModport private: - string m_name; // Name of the variable referenced - VDirection m_direction; // Direction of the variable (in/out) - AstVar* m_varp; // Link to the actual Var + string m_name; // Name of the variable referenced + VDirection m_direction; // Direction of the variable (in/out) + AstVar* m_varp; // Link to the actual Var public: AstModportVarRef(FileLine* fl, const string& name, VDirection::en direction) - : ASTGEN_SUPER(fl), m_name(name), m_direction(direction), m_varp(NULL) { } + : ASTGEN_SUPER(fl) + , m_name(name) + , m_direction(direction) + , m_varp(NULL) {} ASTNODE_NODE_FUNCS(ModportVarRef) - virtual const char* broken() const { BROKEN_RTN(m_varp && !m_varp->brokeExists()); return NULL; } + virtual const char* broken() const { + BROKEN_RTN(m_varp && !m_varp->brokeExists()); + return NULL; + } virtual void dump(std::ostream& str) const; - virtual void cloneRelink() { if (m_varp && m_varp->clonep()) m_varp = m_varp->clonep(); } + virtual void cloneRelink() { + if (m_varp && m_varp->clonep()) m_varp = m_varp->clonep(); + } virtual string name() const { return m_name; } void direction(const VDirection& flag) { m_direction = flag; } VDirection direction() const { return m_direction; } @@ -2278,11 +2579,13 @@ public: class AstModport : public AstNode { // A modport in an interface private: - string m_name; // Name of the modport + string m_name; // Name of the modport public: AstModport(FileLine* fl, const string& name, AstNode* varsp) - : ASTGEN_SUPER(fl), m_name(name) { - addNOp1p(varsp); } + : ASTGEN_SUPER(fl) + , m_name(name) { + addNOp1p(varsp); + } virtual string name() const { return m_name; } virtual bool maybePointedTo() const { return true; } ASTNODE_NODE_FUNCS(Modport) @@ -2295,7 +2598,8 @@ private: string m_name; // Name of the reference public: AstIntfRef(FileLine* fl, const string& name) - : ASTGEN_SUPER(fl), m_name(name) { } + : ASTGEN_SUPER(fl) + , m_name(name) {} virtual string name() const { return m_name; } ASTNODE_NODE_FUNCS(IntfRef) }; @@ -2303,27 +2607,37 @@ public: class AstCell : public AstNode { // A instantiation cell or interface call (don't know which until link) private: - FileLine* m_modNameFileline; // Where module the cell instances token was - string m_name; // Cell name - string m_origName; // Original name before dot addition - string m_modName; // Module the cell instances - AstNodeModule* m_modp; // [AfterLink] Pointer to module instanced - bool m_hasIfaceVar:1; // True if a Var has been created for this cell - bool m_recursive:1; // Self-recursive module - bool m_trace:1; // Trace this cell + FileLine* m_modNameFileline; // Where module the cell instances token was + string m_name; // Cell name + string m_origName; // Original name before dot addition + string m_modName; // Module the cell instances + AstNodeModule* m_modp; // [AfterLink] Pointer to module instanced + bool m_hasIfaceVar : 1; // True if a Var has been created for this cell + bool m_recursive : 1; // Self-recursive module + bool m_trace : 1; // Trace this cell public: - AstCell(FileLine* fl, FileLine* mfl, - const string& instName, const string& modName, + AstCell(FileLine* fl, FileLine* mfl, const string& instName, const string& modName, AstPin* pinsp, AstPin* paramsp, AstRange* rangep) : ASTGEN_SUPER(fl) , m_modNameFileline(mfl) - , m_name(instName), m_origName(instName), m_modName(modName) - , m_modp(NULL), m_hasIfaceVar(false), m_recursive(false), m_trace(true) { - addNOp1p(pinsp); addNOp2p(paramsp); setNOp3p(rangep); } + , m_name(instName) + , m_origName(instName) + , m_modName(modName) + , m_modp(NULL) + , m_hasIfaceVar(false) + , m_recursive(false) + , m_trace(true) { + addNOp1p(pinsp); + addNOp2p(paramsp); + setNOp3p(rangep); + } ASTNODE_NODE_FUNCS(Cell) // No cloneRelink, we presume cloneee's want the same module linkages virtual void dump(std::ostream& str) const; - virtual const char* broken() const { BROKEN_RTN(m_modp && !m_modp->brokeExists()); return NULL; } + virtual const char* broken() const { + BROKEN_RTN(m_modp && !m_modp->brokeExists()); + return NULL; + } virtual bool maybePointedTo() const { return true; } // ACCESSORS virtual string name() const { return m_name; } // * = Cell name @@ -2334,9 +2648,12 @@ public: void modName(const string& name) { m_modName = name; } FileLine* modNameFileline() const { return m_modNameFileline; } AstPin* pinsp() const { return VN_CAST(op1p(), Pin); } // op1 = List of cell ports - AstPin* paramsp() const { return VN_CAST(op2p(), Pin); } // op2 = List of parameter #(##) values - AstRange* rangep() const { return VN_CAST(op3p(), Range); } // op3 = Range of arrayed instants (NULL=not ranged) - AstIntfRef* intfRefp() const { return VN_CAST(op4p(), IntfRef); } // op4 = List of interface references + // op2 = List of parameter #(##) values + AstPin* paramsp() const { return VN_CAST(op2p(), Pin); } + // op3 = Range of arrayed instants (NULL=not ranged) + AstRange* rangep() const { return VN_CAST(op3p(), Range); } + // op4 = List of interface references + AstIntfRef* intfRefp() const { return VN_CAST(op4p(), IntfRef); } AstNodeModule* modp() const { return m_modp; } // [AfterLink] = Pointer to module instantiated void addPinsp(AstPin* nodep) { addOp1p(nodep); } void addParamsp(AstPin* nodep) { addOp2p(nodep); } @@ -2357,16 +2674,21 @@ class AstCellInline : public AstNode { // It is augmented with the scope in V3Scope for VPI. // Children: When 2 levels inlined, other CellInline under this private: - string m_name; // Cell name, possibly {a}__DOT__{b}... - string m_origModName; // Original name of the module, ignoring name() changes, for dot lookup - AstScope* m_scopep; // The scope that the cell is inlined into + string m_name; // Cell name, possibly {a}__DOT__{b}... + string m_origModName; // Original name of the module, ignoring name() changes, for dot lookup + AstScope* m_scopep; // The scope that the cell is inlined into public: AstCellInline(FileLine* fl, const string& name, const string& origModName) : ASTGEN_SUPER(fl) - , m_name(name), m_origModName(origModName), m_scopep(NULL) {} + , m_name(name) + , m_origModName(origModName) + , m_scopep(NULL) {} ASTNODE_NODE_FUNCS(CellInline) virtual void dump(std::ostream& str) const; - virtual const char* broken() const { BROKEN_RTN(m_scopep && !m_scopep->brokeExists()); return NULL; } + virtual const char* broken() const { + BROKEN_RTN(m_scopep && !m_scopep->brokeExists()); + return NULL; + } // ACCESSORS virtual string name() const { return m_name; } // * = Cell name string origModName() const { return m_origModName; } // * = modp()->origName() before inlining @@ -2378,13 +2700,14 @@ public: class AstCellRef : public AstNode { // As-of-yet unlinkable reference into a cell private: - string m_name; // Cell name + string m_name; // Cell name public: - AstCellRef(FileLine* fl, - const string& name, AstNode* cellp, AstNode* exprp) + AstCellRef(FileLine* fl, const string& name, AstNode* cellp, AstNode* exprp) : ASTGEN_SUPER(fl) , m_name(name) { - addNOp1p(cellp); addNOp2p(exprp); } + addNOp1p(cellp); + addNOp2p(exprp); + } ASTNODE_NODE_FUNCS(CellRef) // ACCESSORS virtual string name() const { return m_name; } // * = Array name @@ -2395,13 +2718,13 @@ public: class AstCellArrayRef : public AstNode { // As-of-yet unlinkable reference into an array of cells private: - string m_name; // Array name + string m_name; // Array name public: - AstCellArrayRef(FileLine* fl, - const string& name, AstNode* selectExprp) + AstCellArrayRef(FileLine* fl, const string& name, AstNode* selectExprp) : ASTGEN_SUPER(fl) , m_name(name) { - addNOp1p(selectExprp); } + addNOp1p(selectExprp); + } ASTNODE_NODE_FUNCS(CellArrayRef) // ACCESSORS virtual string name() const { return m_name; } // * = Array name @@ -2411,13 +2734,14 @@ public: class AstUnlinkedRef : public AstNode { // As-of-yet unlinkable Ref private: - string m_name; // Var name + string m_name; // Var name public: - AstUnlinkedRef(FileLine* fl, - AstNode* refp, const string& name, AstNode* crp) + AstUnlinkedRef(FileLine* fl, AstNode* refp, const string& name, AstNode* crp) : ASTGEN_SUPER(fl) , m_name(name) { - addNOp1p(refp); addNOp2p(crp); } + addNOp1p(refp); + addNOp2p(crp); + } ASTNODE_NODE_FUNCS(UnlinkedRef) // ACCESSORS virtual string name() const { return m_name; } // * = Var name @@ -2429,7 +2753,7 @@ class AstBind : public AstNode { // Parents: MODULE // Children: CELL private: - string m_name; // Binding to name + string m_name; // Binding to name public: AstBind(FileLine* fl, const string& name, AstNode* cellsp) : ASTGEN_SUPER(fl) @@ -2447,12 +2771,13 @@ public: class AstPort : public AstNode { // A port (in/out/inout) on a module private: - int m_pinNum; // Pin number - string m_name; // Name of pin + int m_pinNum; // Pin number + string m_name; // Name of pin public: AstPort(FileLine* fl, int pinnum, const string& name) : ASTGEN_SUPER(fl) - , m_pinNum(pinnum), m_name(name) {} + , m_pinNum(pinnum) + , m_name(name) {} ASTNODE_NODE_FUNCS(Port) virtual string name() const { return m_name; } // * = Port name int pinNum() const { return m_pinNum; } // * = Pin number, for order based instantiation @@ -2470,18 +2795,24 @@ class AstParseRef : public AstNode { private: VParseRefExp m_expect; // Type we think it should resolve to string m_name; + public: - AstParseRef(FileLine* fl, VParseRefExp expect, const string& name, - AstNode* lhsp, AstNodeFTaskRef* ftaskrefp) - : ASTGEN_SUPER(fl), m_expect(expect), m_name(name) { setNOp1p(lhsp); setNOp2p(ftaskrefp); } + AstParseRef(FileLine* fl, VParseRefExp expect, const string& name, AstNode* lhsp, + AstNodeFTaskRef* ftaskrefp) + : ASTGEN_SUPER(fl) + , m_expect(expect) + , m_name(name) { + setNOp1p(lhsp); + setNOp2p(ftaskrefp); + } ASTNODE_NODE_FUNCS(ParseRef) virtual void dump(std::ostream& str) const; virtual string name() const { return m_name; } // * = Var name virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_expect), V3Hash(m_name)); } virtual bool same(const AstNode* samep) const { const AstParseRef* asamep = static_cast(samep); - return (expect() == asamep->expect() - && m_name == asamep->m_name); } + return (expect() == asamep->expect() && m_name == asamep->m_name); + } virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual void name(const string& name) { m_name = name; } @@ -2495,20 +2826,25 @@ public: class AstPackageRef : public AstNode { private: - AstPackage* m_packagep; // Package hierarchy + AstPackage* m_packagep; // Package hierarchy public: AstPackageRef(FileLine* fl, AstPackage* packagep) - : ASTGEN_SUPER(fl), m_packagep(packagep) {} + : ASTGEN_SUPER(fl) + , m_packagep(packagep) {} ASTNODE_NODE_FUNCS(PackageRef) // METHODS - virtual const char* broken() const { BROKEN_RTN(!m_packagep || !m_packagep->brokeExists()); return NULL; } - virtual void cloneRelink() { if (m_packagep && m_packagep->clonep()) { - m_packagep = m_packagep->clonep(); - }} + virtual const char* broken() const { + BROKEN_RTN(!m_packagep || !m_packagep->brokeExists()); + return NULL; + } + virtual void cloneRelink() { + if (m_packagep && m_packagep->clonep()) { m_packagep = m_packagep->clonep(); } + } virtual bool same(const AstNode* samep) const { - return (m_packagep==static_cast(samep)->m_packagep); } + return (m_packagep == static_cast(samep)->m_packagep); + } virtual V3Hash sameHash() const { return V3Hash(m_packagep); } - virtual void dump(std::ostream& str=std::cout) const; + virtual void dump(std::ostream& str = std::cout) const; AstPackage* packagep() const { return m_packagep; } void packagep(AstPackage* nodep) { m_packagep = nodep; } }; @@ -2518,7 +2854,10 @@ class AstDot : public AstNode { // These are eliminated in the link stage public: AstDot(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl) { setOp1p(lhsp); setOp2p(rhsp); } + : ASTGEN_SUPER(fl) { + setOp1p(lhsp); + setOp2p(rhsp); + } ASTNODE_NODE_FUNCS(Dot) // For parser, make only if non-null package static AstNode* newIfPkg(FileLine* fl, AstPackage* packagep, AstNode* rhsp) { @@ -2591,11 +2930,13 @@ class AstDpiExport : public AstNode { // however we're not *calling* it, so that seems somehow wrong. // (Probably AstNodeFTaskRef should be renamed AstNodeFTaskCall and have-a AstNodeFTaskRef) private: - string m_name; // Name of function - string m_cname; // Name of function on c side + string m_name; // Name of function + string m_cname; // Name of function on c side public: AstDpiExport(FileLine* fl, const string& vname, const string& cname) - : ASTGEN_SUPER(fl), m_name(vname), m_cname(cname) { } + : ASTGEN_SUPER(fl) + , m_name(vname) + , m_cname(cname) {} ASTNODE_NODE_FUNCS(DpiExport) virtual string name() const { return m_name; } virtual void name(const string& name) { m_name = name; } @@ -2611,13 +2952,14 @@ class AstSenItem : public AstNodeSenItem { private: VEdgeType m_edgeType; // Edge type public: - class Combo {}; // for creator type-overload selection + class Combo {}; // for creator type-overload selection class Illegal {}; // for creator type-overload selection class Initial {}; // for creator type-overload selection - class Settle {}; // for creator type-overload selection - class Never {}; // for creator type-overload selection + class Settle {}; // for creator type-overload selection + class Never {}; // for creator type-overload selection AstSenItem(FileLine* fl, VEdgeType edgeType, AstNode* varrefp) - : ASTGEN_SUPER(fl), m_edgeType(edgeType) { + : ASTGEN_SUPER(fl) + , m_edgeType(edgeType) { setOp1p(varrefp); } AstSenItem(FileLine* fl, Combo) @@ -2644,19 +2986,25 @@ public: virtual void dump(std::ostream& str) const; virtual V3Hash sameHash() const { return V3Hash(edgeType()); } virtual bool same(const AstNode* samep) const { - return edgeType()==static_cast(samep)->edgeType(); } + return edgeType() == static_cast(samep)->edgeType(); + } VEdgeType edgeType() const { return m_edgeType; } // * = Posedge/negedge - void edgeType(VEdgeType type) { m_edgeType = type; editCountInc(); } // * = Posedge/negedge + void edgeType(VEdgeType type) { + m_edgeType = type; + editCountInc(); + } // * = Posedge/negedge AstNode* sensp() const { return op1p(); } // op1 = Signal sensitized - AstNodeVarRef* varrefp() const { return VN_CAST(op1p(), NodeVarRef); } // op1 = Signal sensitized + AstNodeVarRef* varrefp() const { + return VN_CAST(op1p(), NodeVarRef); + } // op1 = Signal sensitized // virtual bool isClocked() const { return edgeType().clockedStmt(); } - virtual bool isCombo() const { return edgeType()==VEdgeType::ET_COMBO; } - virtual bool isInitial() const { return edgeType()==VEdgeType::ET_INITIAL; } - virtual bool isIllegal() const { return edgeType()==VEdgeType::ET_ILLEGAL; } - virtual bool isSettle() const { return edgeType()==VEdgeType::ET_SETTLE; } - virtual bool isNever() const { return edgeType()==VEdgeType::ET_NEVER; } - bool hasVar() const { return !(isCombo()||isInitial()||isSettle()||isNever()); } + virtual bool isCombo() const { return edgeType() == VEdgeType::ET_COMBO; } + virtual bool isInitial() const { return edgeType() == VEdgeType::ET_INITIAL; } + virtual bool isIllegal() const { return edgeType() == VEdgeType::ET_ILLEGAL; } + virtual bool isSettle() const { return edgeType() == VEdgeType::ET_SETTLE; } + virtual bool isNever() const { return edgeType() == VEdgeType::ET_NEVER; } + bool hasVar() const { return !(isCombo() || isInitial() || isSettle() || isNever()); } }; class AstSenGate : public AstNodeSenItem { @@ -2667,7 +3015,9 @@ class AstSenGate : public AstNodeSenItem { public: AstSenGate(FileLine* fl, AstSenItem* sensesp, AstNode* rhsp) : ASTGEN_SUPER(fl) { - dtypeSetLogicBool(); addOp1p(sensesp); setOp2p(rhsp); + dtypeSetLogicBool(); + addOp1p(sensesp); + setOp2p(rhsp); } ASTNODE_NODE_FUNCS(SenGate) virtual string emitVerilog() { return "(%l) %f&& (%r)"; } @@ -2691,7 +3041,8 @@ private: bool m_multi; // Created from combo logic by ORing multiple clock domains public: AstSenTree(FileLine* fl, AstNodeSenItem* sensesp) - : ASTGEN_SUPER(fl), m_multi(false) { + : ASTGEN_SUPER(fl) + , m_multi(false) { addNOp1p(sensesp); } ASTNODE_NODE_FUNCS(SenTree) @@ -2699,22 +3050,26 @@ public: virtual bool maybePointedTo() const { return true; } virtual V3Hash sameHash() const { return V3Hash(); } bool isMulti() const { return m_multi; } - AstNodeSenItem* sensesp() const { return VN_CAST(op1p(), NodeSenItem); } // op1 = Sensitivity list + // op1 = Sensitivity list + AstNodeSenItem* sensesp() const { return VN_CAST(op1p(), NodeSenItem); } void addSensesp(AstNodeSenItem* nodep) { addOp1p(nodep); } void multi(bool flag) { m_multi = true; } // METHODS bool hasClocked() const; // Includes a clocked statement - bool hasSettle() const; // Includes a SETTLE SenItem + bool hasSettle() const; // Includes a SETTLE SenItem bool hasInitial() const; // Includes a INITIAL SenItem - bool hasCombo() const; // Includes a COMBO SenItem + bool hasCombo() const; // Includes a COMBO SenItem }; class AstAlways : public AstNode { VAlwaysKwd m_keyword; + public: AstAlways(FileLine* fl, VAlwaysKwd keyword, AstSenTree* sensesp, AstNode* bodysp) - : ASTGEN_SUPER(fl), m_keyword(keyword) { - addNOp1p(sensesp); addNOp2p(bodysp); + : ASTGEN_SUPER(fl) + , m_keyword(keyword) { + addNOp1p(sensesp); + addNOp2p(bodysp); } ASTNODE_NODE_FUNCS(Always) // @@ -2733,7 +3088,8 @@ class AstAlwaysPublic : public AstNodeStmt { public: AstAlwaysPublic(FileLine* fl, AstSenTree* sensesp, AstNode* bodysp) : ASTGEN_SUPER(fl) { - addNOp1p(sensesp); addNOp2p(bodysp); + addNOp1p(sensesp); + addNOp2p(bodysp); } ASTNODE_NODE_FUNCS(AlwaysPublic) virtual V3Hash sameHash() const { return V3Hash(); } @@ -2751,7 +3107,8 @@ class AstAlwaysPost : public AstNode { public: AstAlwaysPost(FileLine* fl, AstSenTree* sensesp, AstNode* bodysp) : ASTGEN_SUPER(fl) { - addNOp1p(sensesp); addNOp2p(bodysp); + addNOp1p(sensesp); + addNOp2p(bodysp); } ASTNODE_NODE_FUNCS(AlwaysPost) // @@ -2766,7 +3123,9 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(Assign) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAssign(this->fileline(), lhsp, rhsp); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstAssign(this->fileline(), lhsp, rhsp); + } virtual bool brokeLhsMustBeLvalue() const { return true; } }; @@ -2786,7 +3145,9 @@ public: AstAssignDly(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(AssignDly) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAssignDly(this->fileline(), lhsp, rhsp); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstAssignDly(this->fileline(), lhsp, rhsp); + } virtual bool isGateOptimizable() const { return false; } virtual string verilogKwd() const { return "<="; } virtual bool brokeLhsMustBeLvalue() const { return true; } @@ -2796,9 +3157,11 @@ class AstAssignW : public AstNodeAssign { // Like assign, but wire/assign's in verilog, the only setting of the specified variable public: AstAssignW(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { } + : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(AssignW) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAssignW(this->fileline(), lhsp, rhsp); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstAssignW(this->fileline(), lhsp, rhsp); + } virtual bool brokeLhsMustBeLvalue() const { return true; } AstAlways* convertToAlways() { AstNode* lhs1p = lhsp()->unlinkFrBack(); @@ -2818,13 +3181,16 @@ public: dtypeFrom(rhsp); } ASTNODE_NODE_FUNCS(AssignVarScope) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAssignVarScope(this->fileline(), lhsp, rhsp); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstAssignVarScope(this->fileline(), lhsp, rhsp); + } virtual bool brokeLhsMustBeLvalue() const { return false; } }; class AstPull : public AstNode { private: bool m_direction; + public: AstPull(FileLine* fl, AstNode* lhsp, bool direction) : ASTGEN_SUPER(fl) { @@ -2833,10 +3199,11 @@ public: } ASTNODE_NODE_FUNCS(Pull) virtual bool same(const AstNode* samep) const { - return direction()==static_cast(samep)->direction(); } + return direction() == static_cast(samep)->direction(); + } void lhsp(AstNode* np) { setOp1p(np); } AstNode* lhsp() const { return op1p(); } // op1 = Assign to - uint32_t direction() const { return (uint32_t) m_direction; } + uint32_t direction() const { return (uint32_t)m_direction; } }; class AstAssignPre : public AstNodeAssign { @@ -2845,7 +3212,9 @@ public: AstAssignPre(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(AssignPre) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAssignPre(this->fileline(), lhsp, rhsp); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstAssignPre(this->fileline(), lhsp, rhsp); + } virtual bool brokeLhsMustBeLvalue() const { return true; } }; @@ -2855,7 +3224,9 @@ public: AstAssignPost(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(AssignPost) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAssignPost(this->fileline(), lhsp, rhsp); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstAssignPost(this->fileline(), lhsp, rhsp); + } virtual bool brokeLhsMustBeLvalue() const { return true; } }; @@ -2867,9 +3238,10 @@ private: bool m_showAt; // Show "at " string m_name; // Text of comment public: - AstComment(FileLine* fl, const string& name, bool showAt=false) + AstComment(FileLine* fl, const string& name, bool showAt = false) : ASTGEN_SUPER(fl) - , m_showAt(showAt), m_name(name) {} + , m_showAt(showAt) + , m_name(name) {} ASTNODE_NODE_FUNCS(Comment) virtual string name() const { return m_name; } // * = Text virtual V3Hash sameHash() const { return V3Hash(); } // Ignore name in comments @@ -2886,7 +3258,8 @@ public: : ASTGEN_SUPER(fl, condp, expr1p, expr2p) {} ASTNODE_NODE_FUNCS(Cond) virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) { - return new AstCond(this->fileline(), condp, expr1p, expr2p); } + return new AstCond(this->fileline(), condp, expr1p, expr2p); + } }; class AstCondBound : public AstNodeCond { @@ -2898,7 +3271,8 @@ public: : ASTGEN_SUPER(fl, condp, expr1p, expr2p) {} ASTNODE_NODE_FUNCS(CondBound) virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) { - return new AstCondBound(this->fileline(), condp, expr1p, expr2p); } + return new AstCondBound(this->fileline(), condp, expr1p, expr2p); + } }; class AstCoverDecl : public AstNodeStmt { @@ -2906,16 +3280,19 @@ class AstCoverDecl : public AstNodeStmt { // Parents: {statement list} // Children: none private: - AstCoverDecl* m_dataDeclp; // [After V3CoverageJoin] Pointer to duplicate declaration to get data from instead - string m_page; - string m_text; - string m_hier; - int m_column; - int m_binNum; // Set by V3EmitCSyms to tell final V3Emit what to increment + AstCoverDecl* m_dataDeclp; // [After V3CoverageJoin] Pointer to duplicate declaration to get + // data from instead + string m_page; + string m_text; + string m_hier; + int m_column; + int m_binNum; // Set by V3EmitCSyms to tell final V3Emit what to increment public: AstCoverDecl(FileLine* fl, int column, const string& page, const string& comment) : ASTGEN_SUPER(fl) { - m_text = comment; m_page = page; m_column = column; + m_text = comment; + m_page = page; + m_column = column; m_binNum = 0; m_dataDeclp = NULL; } @@ -2925,10 +3302,13 @@ public: if (m_dataDeclp && m_dataDeclp->m_dataDeclp) { // Avoid O(n^2) accessing v3fatalSrc("dataDeclp should point to real data, not be a list"); } - return NULL; } - virtual void cloneRelink() { if (m_dataDeclp && m_dataDeclp->clonep()) m_dataDeclp = m_dataDeclp->clonep(); } + return NULL; + } + virtual void cloneRelink() { + if (m_dataDeclp && m_dataDeclp->clonep()) m_dataDeclp = m_dataDeclp->clonep(); + } virtual void dump(std::ostream& str) const; - virtual int instrCount() const { return 1+2*instrCountLd(); } + virtual int instrCount() const { return 1 + 2 * instrCountLd(); } virtual bool maybePointedTo() const { return true; } int column() const { return m_column; } void binNum(int flag) { m_binNum = flag; } @@ -2941,16 +3321,15 @@ public: virtual V3Hash sameHash() const { return V3Hash(); } virtual bool same(const AstNode* samep) const { const AstCoverDecl* asamep = static_cast(samep); - return (fileline() == asamep->fileline() - && hier() == asamep->hier() - && comment() == asamep->comment() - && column() == asamep->column()); } + return (fileline() == asamep->fileline() && hier() == asamep->hier() + && comment() == asamep->comment() && column() == asamep->column()); + } virtual bool isPredictOptimizable() const { return false; } void dataDeclp(AstCoverDecl* nodep) { m_dataDeclp = nodep; } // dataDecl NULL means "use this one", but often you want "this" to // indicate to get data from here AstCoverDecl* dataDeclNullp() const { return m_dataDeclp; } - AstCoverDecl* dataDeclThisp() { return dataDeclNullp()?dataDeclNullp():this; } + AstCoverDecl* dataDeclThisp() { return dataDeclNullp() ? dataDeclNullp() : this; } }; class AstCoverInc : public AstNodeStmt { @@ -2965,13 +3344,19 @@ public: m_declp = declp; } ASTNODE_NODE_FUNCS(CoverInc) - virtual const char* broken() const { BROKEN_RTN(!declp()->brokeExists()); return NULL; } - virtual void cloneRelink() { if (m_declp->clonep()) m_declp = m_declp->clonep(); } + virtual const char* broken() const { + BROKEN_RTN(!declp()->brokeExists()); + return NULL; + } + virtual void cloneRelink() { + if (m_declp->clonep()) m_declp = m_declp->clonep(); + } virtual void dump(std::ostream& str) const; - virtual int instrCount() const { return 1+2*instrCountLd(); } + virtual int instrCount() const { return 1 + 2 * instrCountLd(); } virtual V3Hash sameHash() const { return V3Hash(declp()); } virtual bool same(const AstNode* samep) const { - return declp() == static_cast(samep)->declp(); } + return declp() == static_cast(samep)->declp(); + } virtual bool isGateOptimizable() const { return false; } virtual bool isPredictOptimizable() const { return false; } virtual bool isOutputter() const { return true; } @@ -2991,12 +3376,14 @@ public: setOp3p(changep); } ASTNODE_NODE_FUNCS(CoverToggle) - virtual int instrCount() const { return 3+instrCountBranch()+instrCountLd(); } + virtual int instrCount() const { return 3 + instrCountBranch() + instrCountLd(); } virtual V3Hash sameHash() const { return V3Hash(); } virtual bool same(const AstNode* samep) const { return true; } virtual bool isGateOptimizable() const { return false; } virtual bool isPredictOptimizable() const { return true; } - virtual bool isOutputter() const { return false; } // Though the AstCoverInc under this is an outputter + virtual bool isOutputter() const { + return false; // Though the AstCoverInc under this is an outputter + } // but isPure() true AstCoverInc* incp() const { return VN_CAST(op1p(), CoverInc); } void incp(AstCoverInc* nodep) { setOp1p(nodep); } @@ -3011,8 +3398,7 @@ class AstGenCase : public AstNodeCase { // casesp Children: CASEITEMs public: AstGenCase(FileLine* fl, AstNode* exprp, AstNode* casesp) - : ASTGEN_SUPER(fl, exprp, casesp) { - } + : ASTGEN_SUPER(fl, exprp, casesp) {} ASTNODE_NODE_FUNCS(GenCase) }; @@ -3022,27 +3408,31 @@ class AstCase : public AstNodeCase { // exprp Children: MATHs // casesp Children: CASEITEMs private: - VCaseType m_casex; // 0=case, 1=casex, 2=casez - bool m_fullPragma; // Synthesis full_case - bool m_parallelPragma; // Synthesis parallel_case - bool m_uniquePragma; // unique case - bool m_unique0Pragma; // unique0 case - bool m_priorityPragma; // priority case + VCaseType m_casex; // 0=case, 1=casex, 2=casez + bool m_fullPragma; // Synthesis full_case + bool m_parallelPragma; // Synthesis parallel_case + bool m_uniquePragma; // unique case + bool m_unique0Pragma; // unique0 case + bool m_priorityPragma; // priority case public: AstCase(FileLine* fl, VCaseType casex, AstNode* exprp, AstNode* casesp) : ASTGEN_SUPER(fl, exprp, casesp) { m_casex = casex; - m_fullPragma = false; m_parallelPragma = false; - m_uniquePragma = false; m_unique0Pragma = false; m_priorityPragma = false; + m_fullPragma = false; + m_parallelPragma = false; + m_uniquePragma = false; + m_unique0Pragma = false; + m_priorityPragma = false; } ASTNODE_NODE_FUNCS(Case) - virtual string verilogKwd() const { return casez()?"casez":casex()?"casex":"case"; } + virtual string verilogKwd() const { return casez() ? "casez" : casex() ? "casex" : "case"; } virtual bool same(const AstNode* samep) const { - return m_casex==static_cast(samep)->m_casex; } - bool casex() const { return m_casex==VCaseType::CT_CASEX; } - bool casez() const { return m_casex==VCaseType::CT_CASEZ; } - bool caseInside() const { return m_casex==VCaseType::CT_CASEINSIDE; } - bool caseSimple() const { return m_casex==VCaseType::CT_CASE; } + return m_casex == static_cast(samep)->m_casex; + } + bool casex() const { return m_casex == VCaseType::CT_CASEX; } + bool casez() const { return m_casex == VCaseType::CT_CASEZ; } + bool caseInside() const { return m_casex == VCaseType::CT_CASEINSIDE; } + bool caseSimple() const { return m_casex == VCaseType::CT_CASE; } void caseInsideSet() { m_casex = VCaseType::CT_CASEINSIDE; } bool fullPragma() const { return m_fullPragma; } void fullPragma(bool flag) { m_fullPragma = flag; } @@ -3066,16 +3456,17 @@ private: public: AstCaseItem(FileLine* fl, AstNode* condsp, AstNode* bodysp) : ASTGEN_SUPER(fl) { - addNOp1p(condsp); addNOp2p(bodysp); + addNOp1p(condsp); + addNOp2p(bodysp); m_ignoreOverlap = false; } ASTNODE_NODE_FUNCS(CaseItem) - virtual int instrCount() const { return widthInstrs()+instrCountBranch(); } + virtual int instrCount() const { return widthInstrs() + instrCountBranch(); } AstNode* condsp() const { return op1p(); } // op1 = list of possible matching expressions AstNode* bodysp() const { return op2p(); } // op2 = what to do void condsp(AstNode* nodep) { setOp1p(nodep); } void addBodysp(AstNode* newp) { addOp2p(newp); } - bool isDefault() const { return condsp()==NULL; } + bool isDefault() const { return condsp() == NULL; } bool ignoreOverlap() const { return m_ignoreOverlap; } void ignoreOverlap(bool flag) { m_ignoreOverlap = flag; } }; @@ -3092,21 +3483,32 @@ public: AstSFormatF(FileLine* fl, const string& text, bool hidden, AstNode* exprsp, char missingArgChar = 'd') : ASTGEN_SUPER(fl) - , m_text(text), m_hidden(hidden), m_hasFormat(true), m_missingArgChar(missingArgChar) { + , m_text(text) + , m_hidden(hidden) + , m_hasFormat(true) + , m_missingArgChar(missingArgChar) { dtypeSetString(); - addNOp1p(exprsp); addNOp2p(NULL); } + addNOp1p(exprsp); + addNOp2p(NULL); + } AstSFormatF(FileLine* fl, NoFormat, AstNode* exprsp, char missingArgChar = 'd') : ASTGEN_SUPER(fl) - , m_text(""), m_hidden(true), m_hasFormat(false), m_missingArgChar(missingArgChar) { + , m_text("") + , m_hidden(true) + , m_hasFormat(false) + , m_missingArgChar(missingArgChar) { dtypeSetString(); - addNOp1p(exprsp); addNOp2p(NULL); } + addNOp1p(exprsp); + addNOp2p(NULL); + } ASTNODE_NODE_FUNCS(SFormatF) virtual string name() const { return m_text; } virtual int instrCount() const { return instrCountPli(); } virtual V3Hash sameHash() const { return V3Hash(text()); } virtual bool hasDType() const { return true; } virtual bool same(const AstNode* samep) const { - return text()==static_cast(samep)->text(); } + return text() == static_cast(samep)->text(); + } virtual string verilogKwd() const { return "$sformatf"; } void addExprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output @@ -3115,7 +3517,8 @@ public: AstScopeName* scopeNamep() const { return VN_CAST(op2p(), ScopeName); } void scopeNamep(AstNode* nodep) { setNOp2p(nodep); } bool formatScopeTracking() const { // Track scopeNamep(); Ok if false positive - return (name().find("%m") != string::npos || name().find("%M") != string::npos); } + return (name().find("%m") != string::npos || name().find("%M") != string::npos); + } bool hidden() const { return m_hidden; } void hasFormat(bool flag) { m_hasFormat = flag; } bool hasFormat() const { return m_hasFormat; } @@ -3128,6 +3531,7 @@ class AstDisplay : public AstNodeStmt { // Children: SFORMATF to generate print string private: AstDisplayType m_displayType; + public: AstDisplay(FileLine* fl, AstDisplayType dispType, const string& text, AstNode* filep, AstNode* exprsp, char missingArgChar = 'd') @@ -3145,9 +3549,14 @@ public: } ASTNODE_NODE_FUNCS(Display) virtual void dump(std::ostream& str) const; - virtual const char* broken() const { BROKEN_RTN(!fmtp()); return NULL; } - virtual string verilogKwd() const { return (filep() ? string("$f")+string(displayType().ascii()) - : string("$")+string(displayType().ascii())); } + virtual const char* broken() const { + BROKEN_RTN(!fmtp()); + return NULL; + } + virtual string verilogKwd() const { + return (filep() ? string("$f") + string(displayType().ascii()) + : string("$") + string(displayType().ascii())); + } virtual bool isGateOptimizable() const { return false; } virtual bool isPredictOptimizable() const { return false; } virtual bool isPure() const { return false; } // SPECIAL: $display has 'visual' ordering @@ -3155,11 +3564,13 @@ public: virtual bool isUnlikely() const { return true; } virtual V3Hash sameHash() const { return V3Hash(displayType()); } virtual bool same(const AstNode* samep) const { - return displayType()==static_cast(samep)->displayType(); } + return displayType() == static_cast(samep)->displayType(); + } virtual int instrCount() const { return instrCountPli(); } AstDisplayType displayType() const { return m_displayType; } void displayType(AstDisplayType type) { m_displayType = type; } - bool addNewline() const { return displayType().addNewline(); } // * = Add a newline for $display + // * = Add a newline for $display + bool addNewline() const { return displayType().addNewline(); } void fmtp(AstSFormatF* nodep) { addOp1p(nodep); } // op1 = To-String formatter AstSFormatF* fmtp() const { return VN_CAST(op1p(), SFormatF); } AstNode* filep() const { return op3p(); } @@ -3173,7 +3584,8 @@ class AstDumpCtl : public AstNodeStmt { VDumpCtlType m_ctlType; // Type of operation public: AstDumpCtl(FileLine* fl, VDumpCtlType ctlType, AstNode* exprp = NULL) - : ASTGEN_SUPER(fl), m_ctlType(ctlType) { + : ASTGEN_SUPER(fl) + , m_ctlType(ctlType) { setNOp1p(exprp); } ASTNODE_NODE_FUNCS(DumpCtl) @@ -3196,6 +3608,7 @@ class AstElabDisplay : public AstNode { // Children: SFORMATF to generate print string private: AstDisplayType m_displayType; + public: AstElabDisplay(FileLine* fl, AstDisplayType dispType, AstNode* exprsp) : ASTGEN_SUPER(fl) { @@ -3203,8 +3616,11 @@ public: m_displayType = dispType; } ASTNODE_NODE_FUNCS(ElabDisplay) - virtual const char* broken() const { BROKEN_RTN(!fmtp()); return NULL; } - virtual string verilogKwd() const { return (string("$")+string(displayType().ascii())); } + virtual const char* broken() const { + BROKEN_RTN(!fmtp()); + return NULL; + } + virtual string verilogKwd() const { return (string("$") + string(displayType().ascii())); } virtual bool isGateOptimizable() const { return false; } virtual bool isPredictOptimizable() const { return false; } virtual bool isPure() const { return false; } // SPECIAL: $display has 'visual' ordering @@ -3212,7 +3628,8 @@ public: virtual bool isUnlikely() const { return true; } virtual V3Hash sameHash() const { return V3Hash(displayType()); } virtual bool same(const AstNode* samep) const { - return displayType()==static_cast(samep)->displayType(); } + return displayType() == static_cast(samep)->displayType(); + } virtual int instrCount() const { return instrCountPli(); } AstDisplayType displayType() const { return m_displayType; } void displayType(AstDisplayType type) { m_displayType = type; } @@ -3232,7 +3649,10 @@ public: setOp3p(lhsp); } ASTNODE_NODE_FUNCS(SFormat) - virtual const char* broken() const { BROKEN_RTN(!fmtp()); return NULL; } + virtual const char* broken() const { + BROKEN_RTN(!fmtp()); + return NULL; + } virtual string verilogKwd() const { return "$sformat"; } virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } virtual string emitC() { V3ERROR_NA_RETURN(""); } @@ -3256,7 +3676,9 @@ class AstSysFuncAsTask : public AstNodeStmt { // Children: a system function public: AstSysFuncAsTask(FileLine* fl, AstNode* exprsp) - : ASTGEN_SUPER(fl) { addNOp1p(exprsp); } + : ASTGEN_SUPER(fl) { + addNOp1p(exprsp); + } ASTNODE_NODE_FUNCS(SysFuncAsTask) virtual string verilogKwd() const { return ""; } virtual bool isGateOptimizable() const { return true; } @@ -3275,7 +3697,9 @@ class AstSysIgnore : public AstNodeStmt { // Children: varrefs or exprs public: AstSysIgnore(FileLine* fl, AstNode* exprsp) - : ASTGEN_SUPER(fl) { addNOp1p(exprsp); } + : ASTGEN_SUPER(fl) { + addNOp1p(exprsp); + } ASTNODE_NODE_FUNCS(SysIgnore) virtual string verilogKwd() const { return "$ignored"; } virtual bool isGateOptimizable() const { return false; } // Though deleted before opt @@ -3359,8 +3783,7 @@ class AstFRead : public AstNodeMath { // Children: low index // Children: count public: - AstFRead(FileLine* fl, AstNode* memp, AstNode* filep, - AstNode* startp, AstNode* countp) + AstFRead(FileLine* fl, AstNode* memp, AstNode* filep, AstNode* startp, AstNode* countp) : ASTGEN_SUPER(fl) { setOp1p(memp); setOp2p(filep); @@ -3442,8 +3865,7 @@ class AstFSeek : public AstNodeMath { // Children: offset // Children: operation public: - AstFSeek(FileLine* fl, AstNode* filep, - AstNode* offset, AstNode* operation) + AstFSeek(FileLine* fl, AstNode* filep, AstNode* offset, AstNode* operation) : ASTGEN_SUPER(fl) { setOp2p(filep); setNOp3p(offset); @@ -3473,10 +3895,12 @@ class AstFScanF : public AstNodeMath { // Children: file which must be a varref // Children: varrefs to load private: - string m_text; + string m_text; + public: AstFScanF(FileLine* fl, const string& text, AstNode* filep, AstNode* exprsp) - : ASTGEN_SUPER(fl), m_text(text) { + : ASTGEN_SUPER(fl) + , m_text(text) { addNOp1p(exprsp); setNOp2p(filep); } @@ -3492,7 +3916,8 @@ public: virtual bool cleanOut() const { return false; } virtual V3Hash sameHash() const { return V3Hash(text()); } virtual bool same(const AstNode* samep) const { - return text()==static_cast(samep)->text(); } + return text() == static_cast(samep)->text(); + } AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output string text() const { return m_text; } // * = Text to display @@ -3506,10 +3931,12 @@ class AstSScanF : public AstNodeMath { // Children: file which must be a varref // Children: varrefs to load private: - string m_text; + string m_text; + public: AstSScanF(FileLine* fl, const string& text, AstNode* fromp, AstNode* exprsp) - : ASTGEN_SUPER(fl), m_text(text) { + : ASTGEN_SUPER(fl) + , m_text(text) { addNOp1p(exprsp); setOp2p(fromp); } @@ -3525,7 +3952,8 @@ public: virtual bool cleanOut() const { return false; } virtual V3Hash sameHash() const { return V3Hash(text()); } virtual bool same(const AstNode* samep) const { - return text()==static_cast(samep)->text(); } + return text() == static_cast(samep)->text(); + } AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output string text() const { return m_text; } // * = Text to display @@ -3538,11 +3966,14 @@ class AstNodeReadWriteMem : public AstNodeStmt { private: bool m_isHex; // readmemh, not readmemb public: - AstNodeReadWriteMem(AstType t, FileLine* fl, bool hex, - AstNode* filenamep, AstNode* memp, + AstNodeReadWriteMem(AstType t, FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp) - : AstNodeStmt(t, fl), m_isHex(hex) { - setOp1p(filenamep); setOp2p(memp); setNOp3p(lsbp); setNOp4p(msbp); + : AstNodeStmt(t, fl) + , m_isHex(hex) { + setOp1p(filenamep); + setOp2p(memp); + setNOp3p(lsbp); + setNOp4p(msbp); } virtual bool isGateOptimizable() const { return false; } virtual bool isPredictOptimizable() const { return false; } @@ -3551,7 +3982,7 @@ public: virtual bool isUnlikely() const { return true; } virtual V3Hash sameHash() const { return V3Hash(); } virtual bool same(const AstNode* samep) const { - return isHex()==static_cast(samep)->isHex(); + return isHex() == static_cast(samep)->isHex(); } bool isHex() const { return m_isHex; } AstNode* filenamep() const { return op1p(); } @@ -3573,11 +4004,10 @@ public: class AstWriteMem : public AstNodeReadWriteMem { public: - AstWriteMem(FileLine* fl, - AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp) - : ASTGEN_SUPER(fl, true, filenamep, memp, lsbp, msbp) { } + AstWriteMem(FileLine* fl, AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp) + : ASTGEN_SUPER(fl, true, filenamep, memp, lsbp, msbp) {} ASTNODE_NODE_FUNCS(WriteMem) - virtual string verilogKwd() const { return (isHex()?"$writememh":"$writememb"); } + virtual string verilogKwd() const { return (isHex() ? "$writememh" : "$writememb"); } virtual const char* cFuncPrefixp() const { return "VL_WRITEMEM_"; } }; @@ -3628,7 +4058,8 @@ class AstValuePlusArgs : public AstNodeMath { public: AstValuePlusArgs(FileLine* fl, AstNode* searchp, AstNode* outp) : ASTGEN_SUPER(fl) { - setOp1p(searchp); setOp2p(outp); + setOp1p(searchp); + setOp2p(outp); } ASTNODE_NODE_FUNCS(ValuePlusArgs) virtual string verilogKwd() const { return "$value$plusargs"; } @@ -3649,7 +4080,8 @@ class AstTestPlusArgs : public AstNodeMath { // Parents: expr // Child: variable to set. If NULL then this is a $test$plusargs instead of $value$plusargs private: - string m_text; + string m_text; + public: AstTestPlusArgs(FileLine* fl, const string& text) : ASTGEN_SUPER(fl) @@ -3664,7 +4096,8 @@ public: virtual bool cleanOut() const { return true; } virtual V3Hash sameHash() const { return V3Hash(text()); } virtual bool same(const AstNode* samep) const { - return text() == static_cast(samep)->text(); } + return text() == static_cast(samep)->text(); + } string text() const { return m_text; } // * = Text to display void text(const string& text) { m_text = text; } }; @@ -3680,7 +4113,9 @@ class AstForeach : public AstNodeStmt { public: AstForeach(FileLine* fl, AstNode* arrayp, AstNode* varsp, AstNode* bodysp) : ASTGEN_SUPER(fl) { - setOp1p(arrayp); addNOp2p(varsp); addNOp4p(bodysp); + setOp1p(arrayp); + addNOp2p(varsp); + addNOp4p(bodysp); } ASTNODE_NODE_FUNCS(Foreach) AstNode* arrayp() const { return op1p(); } // op1 = array @@ -3696,7 +4131,8 @@ class AstRepeat : public AstNodeStmt { public: AstRepeat(FileLine* fl, AstNode* countp, AstNode* bodysp) : ASTGEN_SUPER(fl) { - setOp2p(countp); addNOp3p(bodysp); + setOp2p(countp); + addNOp3p(bodysp); } ASTNODE_NODE_FUNCS(Repeat) AstNode* countp() const { return op2p(); } // op2 = condition to continue @@ -3709,12 +4145,15 @@ public: class AstWhile : public AstNodeStmt { public: - AstWhile(FileLine* fl, AstNode* condp, AstNode* bodysp, AstNode* incsp=NULL) + AstWhile(FileLine* fl, AstNode* condp, AstNode* bodysp, AstNode* incsp = NULL) : ASTGEN_SUPER(fl) { - setOp2p(condp); addNOp3p(bodysp); addNOp4p(incsp); + setOp2p(condp); + addNOp3p(bodysp); + addNOp4p(incsp); } ASTNODE_NODE_FUNCS(While) - AstNode* precondsp() const { return op1p(); } // op1 = prepare statements for condition (exec every loop) + // op1 = prepare statements for condition (exec every loop) + AstNode* precondsp() const { return op1p(); } AstNode* condp() const { return op2p(); } // op2 = condition to continue AstNode* bodysp() const { return op3p(); } // op3 = body of loop AstNode* incsp() const { return op4p(); } // op4 = increment (if from a FOR loop) @@ -3736,7 +4175,9 @@ public: ASTNODE_NODE_FUNCS(Break) virtual string verilogKwd() const { return "break"; } virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool isBrancher() const { return true; } // SPECIAL: We don't process code after breaks + virtual bool isBrancher() const { + return true; // SPECIAL: We don't process code after breaks + } }; class AstContinue : public AstNodeStmt { @@ -3746,7 +4187,9 @@ public: ASTNODE_NODE_FUNCS(Continue) virtual string verilogKwd() const { return "continue"; } virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool isBrancher() const { return true; } // SPECIAL: We don't process code after breaks + virtual bool isBrancher() const { + return true; // SPECIAL: We don't process code after breaks + } }; class AstDisable : public AstNodeStmt { @@ -3754,11 +4197,14 @@ private: string m_name; // Name of block public: AstDisable(FileLine* fl, const string& name) - : ASTGEN_SUPER(fl), m_name(name) {} + : ASTGEN_SUPER(fl) + , m_name(name) {} ASTNODE_NODE_FUNCS(Disable) virtual string name() const { return m_name; } // * = Block name void name(const string& flag) { m_name = flag; } - virtual bool isBrancher() const { return true; } // SPECIAL: We don't process code after breaks + virtual bool isBrancher() const { + return true; // SPECIAL: We don't process code after breaks + } }; class AstReturn : public AstNodeStmt { @@ -3771,7 +4217,9 @@ public: virtual string verilogKwd() const { return "return"; } virtual V3Hash sameHash() const { return V3Hash(); } AstNode* lhsp() const { return op1p(); } - virtual bool isBrancher() const { return true; } // SPECIAL: We don't process code after breaks + virtual bool isBrancher() const { + return true; // SPECIAL: We don't process code after breaks + } }; class AstGenIf : public AstNodeIf { @@ -3783,13 +4231,15 @@ public: class AstIf : public AstNodeIf { private: - bool m_uniquePragma; // unique case - bool m_unique0Pragma; // unique0 case - bool m_priorityPragma; // priority case + bool m_uniquePragma; // unique case + bool m_unique0Pragma; // unique0 case + bool m_priorityPragma; // priority case public: - AstIf(FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp=NULL) + AstIf(FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp = NULL) : ASTGEN_SUPER(fl, condp, ifsp, elsesp) { - m_uniquePragma = false; m_unique0Pragma = false; m_priorityPragma = false; + m_uniquePragma = false; + m_unique0Pragma = false; + m_priorityPragma = false; } ASTNODE_NODE_FUNCS(If) bool uniquePragma() const { return m_uniquePragma; } @@ -3809,7 +4259,8 @@ private: int m_labelNum; // Set by V3EmitCSyms to tell final V3Emit what to increment public: AstJumpLabel(FileLine* fl, AstNode* stmtsp) - : ASTGEN_SUPER(fl), m_labelNum(0) { + : ASTGEN_SUPER(fl) + , m_labelNum(0) { addNOp1p(stmtsp); } virtual int instrCount() const { return 0; } @@ -3835,15 +4286,24 @@ public: m_labelp = labelp; } ASTNODE_NODE_FUNCS(JumpGo) - virtual const char* broken() const { BROKEN_RTN(!labelp()->brokeExistsAbove()); return NULL; } - virtual void cloneRelink() { if (m_labelp->clonep()) m_labelp = m_labelp->clonep(); } + virtual const char* broken() const { + BROKEN_RTN(!labelp()->brokeExistsAbove()); + return NULL; + } + virtual void cloneRelink() { + if (m_labelp->clonep()) m_labelp = m_labelp->clonep(); + } virtual void dump(std::ostream& str) const; virtual int instrCount() const { return instrCountBranch(); } virtual V3Hash sameHash() const { return V3Hash(labelp()); } - virtual bool same(const AstNode* samep) const { // Also same if identical tree structure all the way down, but hard to detect - return labelp() == static_cast(samep)->labelp(); } + virtual bool same(const AstNode* samep) const { + // Also same if identical tree structure all the way down, but hard to detect + return labelp() == static_cast(samep)->labelp(); + } virtual bool isGateOptimizable() const { return false; } - virtual bool isBrancher() const { return true; } // SPECIAL: We don't process code after breaks + virtual bool isBrancher() const { + return true; // SPECIAL: We don't process code after breaks + } AstJumpLabel* labelp() const { return m_labelp; } }; @@ -3858,8 +4318,12 @@ public: dtypeSetUInt32(); // Always used on, and returns word entities } ASTNODE_NODE_FUNCS(ChangeXor) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstChangeXor(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opChangeXor(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstChangeXor(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opChangeXor(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f^ %r)"; } virtual string emitC() { return "VL_CHANGEXOR_%li(%lw, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "^"; } @@ -3879,7 +4343,9 @@ public: // Null lhs+rhs used to indicate change needed with no spec vars AstChangeDet(FileLine* fl, AstNode* lhsp, AstNode* rhsp, bool clockReq) : ASTGEN_SUPER(fl) { - setNOp1p(lhsp); setNOp2p(rhsp); m_clockReq = clockReq; + setNOp1p(lhsp); + setNOp2p(rhsp); + m_clockReq = clockReq; } ASTNODE_NODE_FUNCS(ChangeDet) AstNode* lhsp() const { return op1p(); } @@ -3897,10 +4363,10 @@ class AstBegin : public AstNode { // Parents: statement // Children: statements private: - string m_name; // Name of block - bool m_unnamed; // Originally unnamed (name change does not affect this) - bool m_generate; // Underneath a generate - bool m_implied; // Not inserted by user + string m_name; // Name of block + bool m_unnamed; // Originally unnamed (name change does not affect this) + bool m_generate; // Underneath a generate + bool m_implied; // Not inserted by user public: // Node that simply puts name into the output stream AstBegin(FileLine* fl, const string& name, AstNode* stmtsp, bool generate = false, @@ -3954,12 +4420,14 @@ class AstInside : public AstNodeMath { public: AstInside(FileLine* fl, AstNode* exprp, AstNode* itemsp) : ASTGEN_SUPER(fl) { - addOp1p(exprp); addOp2p(itemsp); + addOp1p(exprp); + addOp2p(itemsp); dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(Inside) AstNode* exprp() const { return op1p(); } // op1 = LHS expression to compare with - AstNode* itemsp() const { return op2p(); } // op2 = RHS, possibly a list of expr or AstInsideRange + // op2 = RHS, possibly a list of expr or AstInsideRange + AstNode* itemsp() const { return op2p(); } virtual string emitVerilog() { return "%l inside { %r }"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const { return false; } // NA @@ -3969,7 +4437,8 @@ class AstInsideRange : public AstNodeMath { public: AstInsideRange(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl) { - addOp1p(lhsp); addOp2p(rhsp); + addOp1p(lhsp); + addOp2p(rhsp); } ASTNODE_NODE_FUNCS(InsideRange) AstNode* lhsp() const { return op1p(); } // op1 = LHS @@ -3988,7 +4457,9 @@ class AstInitItem : public AstNode { public: // Parents: INITARRAY AstInitItem(FileLine* fl, AstNode* valuep) - : ASTGEN_SUPER(fl) { addOp1p(valuep); } + : ASTGEN_SUPER(fl) { + addOp1p(valuep); + } ASTNODE_NODE_FUNCS(InitItem) virtual bool maybePointedTo() const { return true; } virtual bool hasDType() const { return false; } // See valuep()'s dtype instead @@ -4006,6 +4477,7 @@ class AstInitArray : public AstNode { // Children: AstInitItem public: typedef std::map KeyItemMap; + private: KeyItemMap m_map; // Node value for each array index public: @@ -4056,8 +4528,11 @@ public: } AstNode* getIndexValuep(uint32_t index) const { KeyItemMap::const_iterator it = m_map.find(index); - if (it == m_map.end()) return NULL; - else return it->second->valuep(); + if (it == m_map.end()) { + return NULL; + } else { + return it->second->valuep(); + } } AstNode* getIndexDefaultedValuep(uint32_t index) const { AstNode* valuep = getIndexValuep(index); @@ -4141,7 +4616,8 @@ public: virtual V3Hash sameHash() const { return V3Hash(pragType()); } virtual bool isPredictOptimizable() const { return false; } virtual bool same(const AstNode* samep) const { - return pragType() == static_cast(samep)->pragType(); } + return pragType() == static_cast(samep)->pragType(); + } }; class AstStop : public AstNodeStmt { @@ -4156,8 +4632,7 @@ public: virtual bool isUnlikely() const { return true; } virtual int instrCount() const { return 0; } // Rarely executes virtual V3Hash sameHash() const { return V3Hash(fileline()->lineno()); } - virtual bool same(const AstNode* samep) const { - return fileline() == samep->fileline(); } + virtual bool same(const AstNode* samep) const { return fileline() == samep->fileline(); } }; class AstFinish : public AstNodeStmt { @@ -4172,8 +4647,7 @@ public: virtual bool isUnlikely() const { return true; } virtual int instrCount() const { return 0; } // Rarely executes virtual V3Hash sameHash() const { return V3Hash(fileline()->lineno()); } - virtual bool same(const AstNode* samep) const { - return fileline() == samep->fileline(); } + virtual bool same(const AstNode* samep) const { return fileline() == samep->fileline(); } }; class AstNullCheck : public AstNodeUniop { @@ -4203,29 +4677,30 @@ class AstTraceDecl : public AstNodeStmt { // Parents: {statement list} // Children: none private: - string m_showname; // Name of variable - uint32_t m_code; // Trace identifier code; converted to ASCII by trace routines - VNumRange m_bitRange; // Property of var the trace details - VNumRange m_arrayRange; // Property of var the trace details - uint32_t m_codeInc; // Code increment - AstVarType m_varType; // Type of variable (for localparam vs. param) + string m_showname; // Name of variable + uint32_t m_code; // Trace identifier code; converted to ASCII by trace routines + VNumRange m_bitRange; // Property of var the trace details + VNumRange m_arrayRange; // Property of var the trace details + uint32_t m_codeInc; // Code increment + AstVarType m_varType; // Type of variable (for localparam vs. param) AstBasicDTypeKwd m_declKwd; // Keyword at declaration time - VDirection m_declDirection; // Declared direction input/output etc - bool m_isScoped; // Uses run-time scope (for interfaces) + VDirection m_declDirection; // Declared direction input/output etc + bool m_isScoped; // Uses run-time scope (for interfaces) public: AstTraceDecl(FileLine* fl, const string& showname, AstVar* varp, // For input/output state etc - AstNode* valuep, - const VNumRange& bitRange, const VNumRange& arrayRange, + AstNode* valuep, const VNumRange& bitRange, const VNumRange& arrayRange, bool isScoped) : ASTGEN_SUPER(fl) - , m_showname(showname), m_bitRange(bitRange), m_arrayRange(arrayRange) + , m_showname(showname) + , m_bitRange(bitRange) + , m_arrayRange(arrayRange) , m_isScoped(isScoped) { dtypeFrom(valuep); m_code = 0; - m_codeInc = ((arrayRange.ranged() ? arrayRange.elements() : 1) - * valuep->dtypep()->widthWords() - * (VL_EDATASIZE / (8*sizeof(uint32_t)))); // A code is always 32-bits + m_codeInc + = ((arrayRange.ranged() ? arrayRange.elements() : 1) * valuep->dtypep()->widthWords() + * (VL_EDATASIZE / (8 * sizeof(uint32_t)))); // A code is always 32-bits m_varType = varp->varType(); m_declKwd = varp->declKwd(); m_declDirection = varp->declDirection(); @@ -4254,7 +4729,7 @@ class AstTraceInc : public AstNodeStmt { // Parents: {statement list} // Children: incremental value private: - AstTraceDecl* m_declp; // [After V3Trace] Pointer to declaration + AstTraceDecl* m_declp; // [After V3Trace] Pointer to declaration public: AstTraceInc(FileLine* fl, AstTraceDecl* declp, AstNode* valuep) : ASTGEN_SUPER(fl) { @@ -4263,20 +4738,28 @@ public: addNOp2p(valuep); } ASTNODE_NODE_FUNCS(TraceInc) - virtual const char* broken() const { BROKEN_RTN(!declp()->brokeExists()); return NULL; } - virtual void cloneRelink() { if (m_declp->clonep()) m_declp = m_declp->clonep(); } + virtual const char* broken() const { + BROKEN_RTN(!declp()->brokeExists()); + return NULL; + } + virtual void cloneRelink() { + if (m_declp->clonep()) m_declp = m_declp->clonep(); + } virtual void dump(std::ostream& str) const; - virtual int instrCount() const { return 10+2*instrCountLd(); } + virtual int instrCount() const { return 10 + 2 * instrCountLd(); } virtual bool hasDType() const { return true; } virtual V3Hash sameHash() const { return V3Hash(declp()); } virtual bool same(const AstNode* samep) const { - return declp() == static_cast(samep)->declp(); } + return declp() == static_cast(samep)->declp(); + } virtual bool isGateOptimizable() const { return false; } virtual bool isPredictOptimizable() const { return false; } virtual bool isOutputter() const { return true; } // but isPure() true // op1 = Statements before the value - AstNode* precondsp() const { return op1p(); } // op1 = prepare statements for condition (exec every loop) + AstNode* precondsp() const { + return op1p(); + } // op1 = prepare statements for condition (exec every loop) void addPrecondsp(AstNode* newp) { addOp1p(newp); } // op2 = Value to trace AstTraceDecl* declp() const { return m_declp; } // Where defined @@ -4288,8 +4771,9 @@ class AstActive : public AstNode { // Parents: MODULE | CFUNC // Children: SENTREE, statements private: - string m_name; + string m_name; AstSenTree* m_sensesp; + public: AstActive(FileLine* fl, const string& name, AstSenTree* sensesp) : ASTGEN_SUPER(fl) { @@ -4298,13 +4782,16 @@ public: m_sensesp = sensesp; } ASTNODE_NODE_FUNCS(Active) - virtual void dump(std::ostream& str=std::cout) const; + virtual void dump(std::ostream& str = std::cout) const; virtual string name() const { return m_name; } - virtual const char* broken() const { BROKEN_RTN(m_sensesp && !m_sensesp->brokeExists()); return NULL; } + virtual const char* broken() const { + BROKEN_RTN(m_sensesp && !m_sensesp->brokeExists()); + return NULL; + } virtual void cloneRelink() { if (m_sensesp->clonep()) { m_sensesp = m_sensesp->clonep(); - UASSERT(m_sensesp, "Bad clone cross link: "<(samep)->m_dpiExport; } + return m_dpiExport == static_cast(samep)->m_dpiExport; + } virtual string emitVerilog() { return ""; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const { return true; } @@ -4366,13 +4856,17 @@ public: AstText* scopeEntrp() const { return VN_CAST(op2p(), Text); } void scopeEntrp(AstNode* nodep) { addOp2p(nodep); } string scopeSymName() const { // Name for __Vscope variable including children - return scopeNameFormatter(scopeAttrp()); } + return scopeNameFormatter(scopeAttrp()); + } string scopeDpiName() const { // Name for DPI import scope - return scopeNameFormatter(scopeEntrp()); } + return scopeNameFormatter(scopeEntrp()); + } string scopePrettySymName() const { // Name for __Vscope variable including children - return scopePrettyNameFormatter(scopeAttrp()); } + return scopePrettyNameFormatter(scopeAttrp()); + } string scopePrettyDpiName() const { // Name for __Vscope variable including children - return scopePrettyNameFormatter(scopeEntrp()); } + return scopePrettyNameFormatter(scopeEntrp()); + } bool dpiExport() const { return m_dpiExport; } void dpiExport(bool flag) { m_dpiExport = flag; } }; @@ -4384,11 +4878,13 @@ public: addNOp1p(bodysp); } ASTNODE_NODE_FUNCS(UdpTable) - AstUdpTableLine* bodysp() const { return VN_CAST(op1p(), UdpTableLine); } // op1 = List of UdpTableLines + // op1 = List of UdpTableLines + AstUdpTableLine* bodysp() const { return VN_CAST(op1p(), UdpTableLine); } }; class AstUdpTableLine : public AstNode { - string m_text; + string m_text; + public: AstUdpTableLine(FileLine* fl, const string& text) : ASTGEN_SUPER(fl) @@ -4407,16 +4903,18 @@ private: bool m_reset; // Random reset, versus always random public: AstRand(FileLine* fl, AstNodeDType* dtp, bool reset) - : ASTGEN_SUPER(fl) { dtypep(dtp); m_reset = reset; } + : ASTGEN_SUPER(fl) { + dtypep(dtp); + m_reset = reset; + } explicit AstRand(FileLine* fl) : ASTGEN_SUPER(fl) , m_reset(false) {} ASTNODE_NODE_FUNCS(Rand) virtual string emitVerilog() { return "%f$random"; } virtual string emitC() { - return (m_reset ? - "VL_RAND_RESET_%nq(%nw, %P)" - :"VL_RANDOM_%nq(%nw, %P)"); } + return (m_reset ? "VL_RAND_RESET_%nq(%nw, %P)" : "VL_RANDOM_%nq(%nw, %P)"); + } virtual bool cleanOut() const { return true; } virtual bool isGateOptimizable() const { return false; } virtual bool isPredictOptimizable() const { return false; } @@ -4428,7 +4926,9 @@ public: class AstTime : public AstNodeTermop { public: explicit AstTime(FileLine* fl) - : ASTGEN_SUPER(fl) { dtypeSetUInt64(); } + : ASTGEN_SUPER(fl) { + dtypeSetUInt64(); + } ASTNODE_NODE_FUNCS(Time) virtual string emitVerilog() { return "%f$time"; } virtual string emitC() { return "VL_TIME_%nq()"; } @@ -4443,7 +4943,9 @@ public: class AstTimeD : public AstNodeTermop { public: explicit AstTimeD(FileLine* fl) - : ASTGEN_SUPER(fl) { dtypeSetDouble(); } + : ASTGEN_SUPER(fl) { + dtypeSetDouble(); + } ASTNODE_NODE_FUNCS(TimeD) virtual string emitVerilog() { return "%f$realtime"; } virtual string emitC() { return "VL_TIME_D()"; } @@ -4484,7 +4986,9 @@ public: class AstNegate : public AstNodeUniop { public: AstNegate(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(Negate) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNegate(lhs); } virtual string emitVerilog() { return "%f(- %l)"; } @@ -4496,7 +5000,9 @@ public: class AstNegateD : public AstNodeUniop { public: AstNegateD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetDouble(); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetDouble(); + } ASTNODE_NODE_FUNCS(NegateD) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNegateD(lhs); } virtual string emitVerilog() { return "%f(- %l)"; } @@ -4511,7 +5017,9 @@ public: class AstRedAnd : public AstNodeUniop { public: AstRedAnd(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(RedAnd) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedAnd(lhs); } virtual string emitVerilog() { return "%f(& %l)"; } @@ -4523,7 +5031,9 @@ public: class AstRedOr : public AstNodeUniop { public: AstRedOr(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(RedOr) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedOr(lhs); } virtual string emitVerilog() { return "%f(| %l)"; } @@ -4535,37 +5045,48 @@ public: class AstRedXor : public AstNodeUniop { public: AstRedXor(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(RedXor) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXor(lhs); } virtual string emitVerilog() { return "%f(^ %l)"; } virtual string emitC() { return "VL_REDXOR_%lq(%lW, %P, %li)"; } virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const {int w = lhsp()->width(); - return (w!=1 && w!=2 && w!=4 && w!=8 && w!=16); } + virtual bool cleanLhs() const { + int w = lhsp()->width(); + return (w != 1 && w != 2 && w != 4 && w != 8 && w != 16); + } virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return 1+V3Number::log2b(width()); } + virtual int instrCount() const { return 1 + V3Number::log2b(width()); } }; class AstRedXnor : public AstNodeUniop { // AstRedXnors are replaced with AstRedXors in V3Const. public: AstRedXnor(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(RedXnor) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXnor(lhs); } virtual string emitVerilog() { return "%f(~^ %l)"; } - virtual string emitC() { v3fatalSrc("REDXNOR should have became REDXOR"); return ""; } + virtual string emitC() { + v3fatalSrc("REDXNOR should have became REDXOR"); + return ""; + } virtual bool cleanOut() const { return false; } virtual bool cleanLhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return 1+V3Number::log2b(width()); } + virtual int instrCount() const { return 1 + V3Number::log2b(width()); } }; class AstLenN : public AstNodeUniop { // Length of a string public: AstLenN(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetSigned32(); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetSigned32(); + } ASTNODE_NODE_FUNCS(LenN) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opLenN(lhs); } virtual string emitVerilog() { return "%f(%l)"; } @@ -4577,7 +5098,9 @@ public: class AstLogNot : public AstNodeUniop { public: AstLogNot(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(LogNot) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opLogNot(lhs); } virtual string emitVerilog() { return "%f(! %l)"; } @@ -4590,7 +5113,9 @@ public: class AstNot : public AstNodeUniop { public: AstNot(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(Not) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNot(lhs); } virtual string emitVerilog() { return "%f(~ %l)"; } @@ -4606,14 +5131,18 @@ public: AstExtend(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} AstExtend(FileLine* fl, AstNode* lhsp, int width) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetLogicSized(width, AstNumeric::UNSIGNED); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetLogicSized(width, AstNumeric::UNSIGNED); + } ASTNODE_NODE_FUNCS(Extend) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); } virtual string emitVerilog() { return "%l"; } virtual string emitC() { return "VL_EXTEND_%nq%lq(%nw,%lw, %P, %li)"; } virtual bool cleanOut() const { return true; } virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } // Because the EXTEND operator self-casts + virtual bool sizeMattersLhs() const { + return false; // Because the EXTEND operator self-casts + } virtual int instrCount() const { return 0; } }; class AstExtendS : public AstNodeUniop { @@ -4623,7 +5152,9 @@ public: : ASTGEN_SUPER(fl, lhsp) {} AstExtendS(FileLine* fl, AstNode* lhsp, int width) // Important that widthMin be correct, as opExtend requires it after V3Expand - : ASTGEN_SUPER(fl, lhsp) { dtypeSetLogicSized(width, AstNumeric::UNSIGNED); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetLogicSized(width, AstNumeric::UNSIGNED); + } ASTNODE_NODE_FUNCS(ExtendS) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opExtendS(lhs, lhsp()->widthMinV()); @@ -4632,7 +5163,9 @@ public: virtual string emitC() { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; } virtual bool cleanOut() const { return false; } virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } // Because the EXTEND operator self-casts + virtual bool sizeMattersLhs() const { + return false; // Because the EXTEND operator self-casts + } virtual int instrCount() const { return 0; } virtual bool signedFlavor() const { return true; } }; @@ -4642,9 +5175,13 @@ public: AstSigned(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { UASSERT_OBJ(!v3Global.assertDTypesResolved(), this, - "not coded to create after dtypes resolved"); } + "not coded to create after dtypes resolved"); + } ASTNODE_NODE_FUNCS(Signed) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.opAssign(lhs); + out.isSigned(false); + } virtual string emitVerilog() { return "%f$signed(%l)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const { return false; } @@ -4658,9 +5195,13 @@ public: AstUnsigned(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { UASSERT_OBJ(!v3Global.assertDTypesResolved(), this, - "not coded to create after dtypes resolved"); } + "not coded to create after dtypes resolved"); + } ASTNODE_NODE_FUNCS(Unsigned) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.opAssign(lhs); + out.isSigned(false); + } virtual string emitVerilog() { return "%f$unsigned(%l)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const { return false; } @@ -4672,7 +5213,9 @@ class AstRToIS : public AstNodeUniop { // $rtoi(lhs) public: AstRToIS(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetSigned32(); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetSigned32(); + } ASTNODE_NODE_FUNCS(RToIS) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRToIS(lhs); } virtual string emitVerilog() { return "%f$rtoi(%l)"; } @@ -4701,7 +5244,9 @@ public: class AstIToRD : public AstNodeUniop { public: AstIToRD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetDouble(); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetDouble(); + } ASTNODE_NODE_FUNCS(IToRD) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opIToRD(lhs); } virtual string emitVerilog() { return "%f$itor(%l)"; } @@ -4714,7 +5259,9 @@ public: class AstRealToBits : public AstNodeUniop { public: AstRealToBits(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetUInt64(); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetUInt64(); + } ASTNODE_NODE_FUNCS(RealToBits) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRealToBits(lhs); } virtual string emitVerilog() { return "%f$realtobits(%l)"; } @@ -4727,7 +5274,9 @@ public: class AstBitsToRealD : public AstNodeUniop { public: AstBitsToRealD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetDouble(); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetDouble(); + } ASTNODE_NODE_FUNCS(BitsToRealD) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opBitsToRealD(lhs); } virtual string emitVerilog() { return "%f$bitstoreal(%l)"; } @@ -4749,7 +5298,7 @@ public: virtual bool cleanOut() const { return false; } virtual bool cleanLhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return widthInstrs()*16; } + virtual int instrCount() const { return widthInstrs() * 16; } }; class AstCountOnes : public AstNodeUniop { // Number of bits set in vector @@ -4763,13 +5312,15 @@ public: virtual bool cleanOut() const { return false; } virtual bool cleanLhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return widthInstrs()*16; } + virtual int instrCount() const { return widthInstrs() * 16; } }; class AstIsUnknown : public AstNodeUniop { // True if any unknown bits public: AstIsUnknown(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(IsUnknown) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opIsUnknown(lhs); } virtual string emitVerilog() { return "%f$isunknown(%l)"; } @@ -4782,7 +5333,9 @@ class AstOneHot : public AstNodeUniop { // True if only single bit set in vector public: AstOneHot(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(OneHot) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opOneHot(lhs); } virtual string emitVerilog() { return "%f$onehot(%l)"; } @@ -4790,13 +5343,15 @@ public: virtual bool cleanOut() const { return true; } virtual bool cleanLhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return widthInstrs()*4; } + virtual int instrCount() const { return widthInstrs() * 4; } }; class AstOneHot0 : public AstNodeUniop { // True if only single bit, or no bits set in vector public: AstOneHot0(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(OneHot0) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opOneHot0(lhs); } virtual string emitVerilog() { return "%f$onehot0(%l)"; } @@ -4804,7 +5359,7 @@ public: virtual bool cleanOut() const { return true; } virtual bool cleanLhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return widthInstrs()*3; } + virtual int instrCount() const { return widthInstrs() * 3; } }; class AstCast : public AstNode { @@ -4812,7 +5367,8 @@ class AstCast : public AstNode { public: AstCast(FileLine* fl, AstNode* lhsp, AstNodeDType* dtp) : ASTGEN_SUPER(fl) { - setOp1p(lhsp); setOp2p(dtp); + setOp1p(lhsp); + setOp2p(dtp); dtypeFrom(dtp); } ASTNODE_NODE_FUNCS(Cast) @@ -4832,7 +5388,8 @@ class AstCastParse : public AstNode { public: AstCastParse(FileLine* fl, AstNode* lhsp, AstNode* dtp) : ASTGEN_SUPER(fl) { - setOp1p(lhsp); setOp2p(dtp); + setOp1p(lhsp); + setOp2p(dtp); } ASTNODE_NODE_FUNCS(CastParse) virtual string emitVerilog() { return "((%d)'(%l))"; } @@ -4849,7 +5406,8 @@ class AstCastSize : public AstNode { public: AstCastSize(FileLine* fl, AstNode* lhsp, AstConst* rhsp) : ASTGEN_SUPER(fl) { - setOp1p(lhsp); setOp2p(rhsp); + setOp1p(lhsp); + setOp2p(rhsp); } ASTNODE_NODE_FUNCS(CastSize) // No hasDType because widthing removes this node before the hasDType check @@ -4865,13 +5423,14 @@ public: class AstCCast : public AstNodeUniop { // Cast to C-based data type private: - int m_size; + int m_size; + public: - AstCCast(FileLine* fl, AstNode* lhsp, int setwidth, int minwidth=-1) + AstCCast(FileLine* fl, AstNode* lhsp, int setwidth, int minwidth = -1) : ASTGEN_SUPER(fl, lhsp) { m_size = setwidth; if (setwidth) { - if (minwidth==-1) minwidth = setwidth; + if (minwidth == -1) minwidth = setwidth; dtypeSetLogicUnsized(setwidth, minwidth, AstNumeric::UNSIGNED); } } @@ -4889,8 +5448,9 @@ public: virtual bool sizeMattersLhs() const { return false; } // Special cased in V3Cast virtual V3Hash sameHash() const { return V3Hash(size()); } virtual bool same(const AstNode* samep) const { - return size() == static_cast(samep)->size(); } - virtual void dump(std::ostream& str=std::cout) const; + return size() == static_cast(samep)->size(); + } + virtual void dump(std::ostream& str = std::cout) const; // int size() const { return m_size; } }; @@ -4899,7 +5459,9 @@ class AstCvtPackString : public AstNodeUniop { // Convert to Verilator Packed String (aka verilog "string") public: AstCvtPackString(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetString(); } // Really, width should be dtypep -> STRING + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetString(); + } ASTNODE_NODE_FUNCS(CvtPackString) virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; } virtual string emitVerilog() { return "%f$_CAST(%l)"; } @@ -4922,7 +5484,7 @@ public: virtual bool cleanOut() const { return true; } virtual bool cleanLhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return widthInstrs()*16; } + virtual int instrCount() const { return widthInstrs() * 16; } virtual bool isPure() const { return false; } // SPECIAL: $display has 'visual' ordering AstNode* filep() const { return lhsp(); } }; @@ -4963,7 +5525,7 @@ public: virtual bool cleanOut() const { return false; } virtual bool cleanLhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return widthInstrs()*64; } + virtual int instrCount() const { return widthInstrs() * 64; } virtual bool isPure() const { return false; } // SPECIAL: $display has 'visual' ordering AstNode* filep() const { return lhsp(); } }; @@ -4973,9 +5535,12 @@ public: AstFUngetC(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(FUngetC) - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + V3ERROR_NA; + } virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { - return new AstFUngetC(this->fileline(), lhsp, rhsp); } + return new AstFUngetC(this->fileline(), lhsp, rhsp); + } virtual string emitVerilog() { return "%f$ungetc(%r, %l)"; } // Non-existent filehandle returns EOF virtual string emitC() { return "(%li ? (ungetc(%ri, VL_CVT_I_FP(%li)) >= 0 ? 0 : -1) : -1)"; } @@ -4993,7 +5558,9 @@ public: class AstNodeSystemUniop : public AstNodeUniop { public: AstNodeSystemUniop(AstType t, FileLine* fl, AstNode* lhsp) - : AstNodeUniop(t, fl, lhsp) { dtypeSetDouble(); } + : AstNodeUniop(t, fl, lhsp) { + dtypeSetDouble(); + } ASTNODE_BASE_FUNCS(NodeSystemUniop) virtual bool cleanOut() const { return true; } virtual bool cleanLhs() const { return false; } @@ -5007,7 +5574,9 @@ public: AstLogD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(LogD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(log(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(log(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$ln(%l)"; } virtual string emitC() { return "log(%li)"; } }; @@ -5016,7 +5585,9 @@ public: AstLog10D(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(Log10D) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(log10(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(log10(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$log10(%l)"; } virtual string emitC() { return "log10(%li)"; } }; @@ -5026,7 +5597,9 @@ public: AstExpD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(ExpD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(exp(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(exp(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$exp(%l)"; } virtual string emitC() { return "exp(%li)"; } }; @@ -5036,7 +5609,9 @@ public: AstSqrtD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(SqrtD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(sqrt(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(sqrt(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$sqrt(%l)"; } virtual string emitC() { return "sqrt(%li)"; } }; @@ -5046,7 +5621,9 @@ public: AstFloorD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(FloorD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(floor(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(floor(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$floor(%l)"; } virtual string emitC() { return "floor(%li)"; } }; @@ -5056,7 +5633,9 @@ public: AstCeilD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(CeilD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(ceil(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(ceil(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$ceil(%l)"; } virtual string emitC() { return "ceil(%li)"; } }; @@ -5066,7 +5645,9 @@ public: AstSinD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(SinD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(sin(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(sin(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$sin(%l)"; } virtual string emitC() { return "sin(%li)"; } }; @@ -5076,7 +5657,9 @@ public: AstCosD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(CosD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(cos(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(cos(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$cos(%l)"; } virtual string emitC() { return "cos(%li)"; } }; @@ -5086,7 +5669,9 @@ public: AstTanD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(TanD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(tan(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(tan(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$tan(%l)"; } virtual string emitC() { return "tan(%li)"; } }; @@ -5096,7 +5681,9 @@ public: AstAsinD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(AsinD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(asin(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(asin(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$asin(%l)"; } virtual string emitC() { return "asin(%li)"; } }; @@ -5106,7 +5693,9 @@ public: AstAcosD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(AcosD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(acos(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(acos(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$acos(%l)"; } virtual string emitC() { return "acos(%li)"; } }; @@ -5116,7 +5705,9 @@ public: AstAtanD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(AtanD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(atan(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(atan(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$atan(%l)"; } virtual string emitC() { return "atan(%li)"; } }; @@ -5126,7 +5717,9 @@ public: AstSinhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(SinhD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(sinh(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(sinh(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$sinh(%l)"; } virtual string emitC() { return "sinh(%li)"; } }; @@ -5136,7 +5729,9 @@ public: AstCoshD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(CoshD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(cosh(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(cosh(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$cosh(%l)"; } virtual string emitC() { return "cosh(%li)"; } }; @@ -5146,7 +5741,9 @@ public: AstTanhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(TanhD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(tanh(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(tanh(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$tanh(%l)"; } virtual string emitC() { return "tanh(%li)"; } }; @@ -5156,7 +5753,9 @@ public: AstAsinhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(AsinhD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(asinh(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(asinh(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$asinh(%l)"; } virtual string emitC() { return "asinh(%li)"; } }; @@ -5166,7 +5765,9 @@ public: AstAcoshD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(AcoshD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(acosh(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(acosh(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$acosh(%l)"; } virtual string emitC() { return "acosh(%li)"; } }; @@ -5176,7 +5777,9 @@ public: AstAtanhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(AtanhD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.setDouble(atanh(lhs.toDouble())); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(atanh(lhs.toDouble())); + } virtual string emitVerilog() { return "%f$atanh(%l)"; } virtual string emitC() { return "atanh(%li)"; } }; @@ -5184,7 +5787,9 @@ class AstToLowerN : public AstNodeUniop { // string.tolower() public: AstToLowerN(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetString(); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetString(); + } ASTNODE_NODE_FUNCS(ToLowerN) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opToLowerN(lhs); } virtual string emitVerilog() { return "%l.tolower()"; } @@ -5197,7 +5802,9 @@ class AstToUpperN : public AstNodeUniop { // string.toupper() public: AstToUpperN(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER(fl, lhsp) { dtypeSetString(); } + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetString(); + } ASTNODE_NODE_FUNCS(ToUpperN) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opToUpperN(lhs); } virtual string emitVerilog() { return "%l.toupper()"; } @@ -5210,7 +5817,8 @@ public: class AstAtoN : public AstNodeUniop { // string.atoi(), atobin(), atohex(), atooct(), atoireal() public: - enum FmtType {ATOI = 10, ATOHEX = 16, ATOOCT = 8, ATOBIN = 2, ATOREAL = -1}; + enum FmtType { ATOI = 10, ATOHEX = 16, ATOOCT = 8, ATOBIN = 2, ATOREAL = -1 }; + private: FmtType m_fmt; // Operation type public: @@ -5254,10 +5862,16 @@ public: class AstLogOr : public AstNodeBiop { public: AstLogOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(LogOr) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLogOr(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLogOr(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstLogOr(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opLogOr(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f|| %r)"; } virtual string emitC() { return "VL_LOGOR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "||"; } @@ -5266,15 +5880,21 @@ public: virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs()+instrCountBranch(); } + virtual int instrCount() const { return widthInstrs() + instrCountBranch(); } }; class AstLogAnd : public AstNodeBiop { public: AstLogAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(LogAnd) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLogAnd(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLogAnd(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstLogAnd(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opLogAnd(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f&& %r)"; } virtual string emitC() { return "VL_LOGAND_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "&&"; } @@ -5283,17 +5903,21 @@ public: virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs()+instrCountBranch(); } + virtual int instrCount() const { return widthInstrs() + instrCountBranch(); } }; class AstLogEq : public AstNodeBiCom { public: AstLogEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(LogEq) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { - return new AstLogEq(this->fileline(), lhsp, rhsp); } + return new AstLogEq(this->fileline(), lhsp, rhsp); + } virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { - out.opLogEq(lhs, rhs); } + out.opLogEq(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f<-> %r)"; } virtual string emitC() { return "VL_LOGEQ_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "<->"; } @@ -5302,17 +5926,21 @@ public: virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs()+instrCountBranch(); } + virtual int instrCount() const { return widthInstrs() + instrCountBranch(); } }; class AstLogIf : public AstNodeBiop { public: AstLogIf(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(LogIf) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { - return new AstLogIf(this->fileline(), lhsp, rhsp); } + return new AstLogIf(this->fileline(), lhsp, rhsp); + } virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { - out.opLogIf(lhs, rhs); } + out.opLogIf(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f-> %r)"; } virtual string emitC() { return "VL_LOGIF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "->"; } @@ -5321,15 +5949,21 @@ public: virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs()+instrCountBranch(); } + virtual int instrCount() const { return widthInstrs() + instrCountBranch(); } }; class AstOr : public AstNodeBiComAsv { public: AstOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(Or) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstOr(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opOr(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstOr(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opOr(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f| %r)"; } virtual string emitC() { return "VL_OR_%lq(%lW, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "|"; } @@ -5342,10 +5976,16 @@ public: class AstAnd : public AstNodeBiComAsv { public: AstAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(And) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAnd(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAnd(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstAnd(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opAnd(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f& %r)"; } virtual string emitC() { return "VL_AND_%lq(%lW, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "&"; } @@ -5358,10 +5998,16 @@ public: class AstXor : public AstNodeBiComAsv { public: AstXor(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(Xor) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstXor(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opXor(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstXor(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opXor(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f^ %r)"; } virtual string emitC() { return "VL_XOR_%lq(%lW, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "^"; } @@ -5374,10 +6020,16 @@ public: class AstXnor : public AstNodeBiComAsv { public: AstXnor(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(Xnor) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstXnor(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opXnor(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstXnor(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opXnor(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f^ ~ %r)"; } virtual string emitC() { return "VL_XNOR_%lq(%lW, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "^ ~"; } @@ -5390,11 +6042,18 @@ public: class AstEq : public AstNodeBiCom { public: AstEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(Eq) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEq(this->fileline(), lhsp, rhsp); } - static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstEq/AstEqD - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEq(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstEq(this->fileline(), lhsp, rhsp); + } + static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, + AstNode* rhsp); // Return AstEq/AstEqD + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opEq(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f== %r)"; } virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "=="; } @@ -5407,10 +6066,16 @@ public: class AstEqD : public AstNodeBiCom { public: AstEqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(EqD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEqD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEqD(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstEqD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opEqD(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f== %r)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { return "=="; } @@ -5425,10 +6090,16 @@ public: class AstEqN : public AstNodeBiCom { public: AstEqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(EqN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEqN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEqN(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstEqN(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opEqN(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f== %r)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { return "=="; } @@ -5443,10 +6114,16 @@ public: class AstNeq : public AstNodeBiCom { public: AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(Neq) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstNeq(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeq(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstNeq(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opNeq(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f!= %r)"; } virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "!="; } @@ -5459,10 +6136,16 @@ public: class AstNeqD : public AstNodeBiCom { public: AstNeqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(NeqD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstNeqD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeqD(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstNeqD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opNeqD(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f!= %r)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { return "!="; } @@ -5477,10 +6160,16 @@ public: class AstNeqN : public AstNodeBiCom { public: AstNeqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(NeqN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstNeqN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeqN(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstNeqN(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opNeqN(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f!= %r)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { return "!="; } @@ -5495,10 +6184,16 @@ public: class AstLt : public AstNodeBiop { public: AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(Lt) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLt(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLt(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstLt(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opLt(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f< %r)"; } virtual string emitC() { return "VL_LT_%lq(%lW, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "<"; } @@ -5511,10 +6206,16 @@ public: class AstLtD : public AstNodeBiop { public: AstLtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(LtD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLtD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtD(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstLtD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opLtD(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f< %r)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { return "<"; } @@ -5529,10 +6230,16 @@ public: class AstLtS : public AstNodeBiop { public: AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(LtS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLtS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtS(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstLtS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opLtS(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f< %r)"; } virtual string emitC() { return "VL_LTS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return ""; } @@ -5546,10 +6253,16 @@ public: class AstLtN : public AstNodeBiop { public: AstLtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(LtN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLtN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtN(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstLtN(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opLtN(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f< %r)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { return "<"; } @@ -5564,10 +6277,16 @@ public: class AstGt : public AstNodeBiop { public: AstGt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(Gt) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGt(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGt(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstGt(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opGt(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f> %r)"; } virtual string emitC() { return "VL_GT_%lq(%lW, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return ">"; } @@ -5580,10 +6299,16 @@ public: class AstGtD : public AstNodeBiop { public: AstGtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(GtD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGtD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtD(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstGtD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opGtD(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f> %r)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { return ">"; } @@ -5598,10 +6323,16 @@ public: class AstGtS : public AstNodeBiop { public: AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(GtS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGtS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtS(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstGtS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opGtS(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f> %r)"; } virtual string emitC() { return "VL_GTS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return ""; } @@ -5615,10 +6346,16 @@ public: class AstGtN : public AstNodeBiop { public: AstGtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(GtN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGtN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtN(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstGtN(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opGtN(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f> %r)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { return ">"; } @@ -5633,11 +6370,18 @@ public: class AstGte : public AstNodeBiop { public: AstGte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(Gte) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGte(this->fileline(), lhsp, rhsp); } - static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstGte/AstGteS/AstGteD - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGte(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstGte(this->fileline(), lhsp, rhsp); + } + static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, + AstNode* rhsp); // Return AstGte/AstGteS/AstGteD + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opGte(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f>= %r)"; } virtual string emitC() { return "VL_GTE_%lq(%lW, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return ">="; } @@ -5650,10 +6394,16 @@ public: class AstGteD : public AstNodeBiop { public: AstGteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(GteD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGteD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteD(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstGteD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opGteD(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f>= %r)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { return ">="; } @@ -5668,10 +6418,16 @@ public: class AstGteS : public AstNodeBiop { public: AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(GteS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGteS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteS(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstGteS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opGteS(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f>= %r)"; } virtual string emitC() { return "VL_GTES_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return ""; } @@ -5685,10 +6441,16 @@ public: class AstGteN : public AstNodeBiop { public: AstGteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(GteN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGteN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteN(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstGteN(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opGteN(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f>= %r)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { return ">="; } @@ -5703,11 +6465,18 @@ public: class AstLte : public AstNodeBiop { public: AstLte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(Lte) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLte(this->fileline(), lhsp, rhsp); } - static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstLte/AstLteS/AstLteD - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLte(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstLte(this->fileline(), lhsp, rhsp); + } + static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, + AstNode* rhsp); // Return AstLte/AstLteS/AstLteD + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opLte(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f<= %r)"; } virtual string emitC() { return "VL_LTE_%lq(%lW, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "<="; } @@ -5720,10 +6489,16 @@ public: class AstLteD : public AstNodeBiop { public: AstLteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(LteD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLteD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteD(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstLteD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opLteD(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f<= %r)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { return "<="; } @@ -5738,10 +6513,16 @@ public: class AstLteS : public AstNodeBiop { public: AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(LteS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLteS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteS(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstLteS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opLteS(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f<= %r)"; } virtual string emitC() { return "VL_LTES_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return ""; } @@ -5755,10 +6536,16 @@ public: class AstLteN : public AstNodeBiop { public: AstLteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(LteN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstLteN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteN(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstLteN(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opLteN(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f<= %r)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { return "<="; } @@ -5772,13 +6559,17 @@ public: }; class AstShiftL : public AstNodeBiop { public: - AstShiftL(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth=0) + AstShiftL(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth = 0) : ASTGEN_SUPER(fl, lhsp, rhsp) { if (setwidth) { dtypeSetLogicSized(setwidth, AstNumeric::UNSIGNED); } } ASTNODE_NODE_FUNCS(ShiftL) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstShiftL(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opShiftL(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstShiftL(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opShiftL(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f<< %r)"; } virtual string emitC() { return "VL_SHIFTL_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "<<"; } @@ -5790,13 +6581,17 @@ public: }; class AstShiftR : public AstNodeBiop { public: - AstShiftR(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth=0) + AstShiftR(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth = 0) : ASTGEN_SUPER(fl, lhsp, rhsp) { if (setwidth) { dtypeSetLogicSized(setwidth, AstNumeric::UNSIGNED); } } ASTNODE_NODE_FUNCS(ShiftR) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstShiftR(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opShiftR(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstShiftR(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opShiftR(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f>> %r)"; } virtual string emitC() { return "VL_SHIFTR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return ">>"; } @@ -5811,15 +6606,18 @@ class AstShiftRS : public AstNodeBiop { // Shift right with sign extension, >>> operator // Output data type's width determines which bit is used for sign extension public: - AstShiftRS(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth=0) + AstShiftRS(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth = 0) : ASTGEN_SUPER(fl, lhsp, rhsp) { // Important that widthMin be correct, as opExtend requires it after V3Expand if (setwidth) { dtypeSetLogicSized(setwidth, AstNumeric::SIGNED); } } ASTNODE_NODE_FUNCS(ShiftRS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstShiftRS(this->fileline(), lhsp, rhsp); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstShiftRS(this->fileline(), lhsp, rhsp); + } virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { - out.opShiftRS(lhs, rhs, lhsp()->widthMinV()); } + out.opShiftRS(lhs, rhs, lhsp()->widthMinV()); + } virtual string emitVerilog() { return "%k(%l %f>>> %r)"; } virtual string emitC() { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return ""; } @@ -5833,10 +6631,16 @@ public: class AstAdd : public AstNodeBiComAsv { public: AstAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(Add) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAdd(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAdd(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstAdd(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opAdd(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f+ %r)"; } virtual string emitC() { return "VL_ADD_%lq(%lW, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "+"; } @@ -5849,10 +6653,16 @@ public: class AstAddD : public AstNodeBiComAsv { public: AstAddD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetDouble(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetDouble(); + } ASTNODE_NODE_FUNCS(AddD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAddD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAddD(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstAddD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opAddD(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f+ %r)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { return "+"; } @@ -5867,10 +6677,16 @@ public: class AstSub : public AstNodeBiop { public: AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(Sub) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstSub(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opSub(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstSub(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opSub(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f- %r)"; } virtual string emitC() { return "VL_SUB_%lq(%lW, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "-"; } @@ -5883,10 +6699,16 @@ public: class AstSubD : public AstNodeBiop { public: AstSubD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetDouble(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetDouble(); + } ASTNODE_NODE_FUNCS(SubD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstSubD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opSubD(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstSubD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opSubD(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f- %r)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { return "-"; } @@ -5901,10 +6723,16 @@ public: class AstMul : public AstNodeBiComAsv { public: AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(Mul) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstMul(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMul(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstMul(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opMul(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f* %r)"; } virtual string emitC() { return "VL_MUL_%lq(%lW, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "*"; } @@ -5913,15 +6741,21 @@ public: virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return true; } virtual bool sizeMattersRhs() const { return true; } - virtual int instrCount() const { return widthInstrs()*instrCountMul(); } + virtual int instrCount() const { return widthInstrs() * instrCountMul(); } }; class AstMulD : public AstNodeBiComAsv { public: AstMulD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetDouble(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetDouble(); + } ASTNODE_NODE_FUNCS(MulD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstMulD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMulD(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstMulD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opMulD(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f* %r)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { return "*"; } @@ -5936,10 +6770,16 @@ public: class AstMulS : public AstNodeBiComAsv { public: AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(MulS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstMulS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMulS(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstMulS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opMulS(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f* %r)"; } virtual string emitC() { return "VL_MULS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return ""; } @@ -5948,16 +6788,22 @@ public: virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return true; } virtual bool sizeMattersRhs() const { return true; } - virtual int instrCount() const { return widthInstrs()*instrCountMul(); } + virtual int instrCount() const { return widthInstrs() * instrCountMul(); } virtual bool signedFlavor() const { return true; } }; class AstDiv : public AstNodeBiop { public: AstDiv(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(Div) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstDiv(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDiv(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstDiv(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opDiv(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f/ %r)"; } virtual string emitC() { return "VL_DIV_%nq%lq%rq(%lw, %P, %li, %ri)"; } virtual bool cleanOut() const { return false; } @@ -5965,15 +6811,21 @@ public: virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return true; } virtual bool sizeMattersRhs() const { return true; } - virtual int instrCount() const { return widthInstrs()*instrCountDiv(); } + virtual int instrCount() const { return widthInstrs() * instrCountDiv(); } }; class AstDivD : public AstNodeBiop { public: AstDivD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetDouble(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetDouble(); + } ASTNODE_NODE_FUNCS(DivD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstDivD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDivD(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstDivD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opDivD(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f/ %r)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { return "/"; } @@ -5988,10 +6840,16 @@ public: class AstDivS : public AstNodeBiop { public: AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(DivS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstDivS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDivS(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstDivS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opDivS(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f/ %r)"; } virtual string emitC() { return "VL_DIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; } virtual bool cleanOut() const { return false; } @@ -5999,16 +6857,22 @@ public: virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return true; } virtual bool sizeMattersRhs() const { return true; } - virtual int instrCount() const { return widthInstrs()*instrCountDiv(); } + virtual int instrCount() const { return widthInstrs() * instrCountDiv(); } virtual bool signedFlavor() const { return true; } }; class AstModDiv : public AstNodeBiop { public: AstModDiv(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(ModDiv) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstModDiv(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opModDiv(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstModDiv(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opModDiv(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f%% %r)"; } virtual string emitC() { return "VL_MODDIV_%nq%lq%rq(%lw, %P, %li, %ri)"; } virtual bool cleanOut() const { return false; } @@ -6016,15 +6880,21 @@ public: virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return true; } virtual bool sizeMattersRhs() const { return true; } - virtual int instrCount() const { return widthInstrs()*instrCountDiv(); } + virtual int instrCount() const { return widthInstrs() * instrCountDiv(); } }; class AstModDivS : public AstNodeBiop { public: AstModDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(ModDivS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstModDivS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opModDivS(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstModDivS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opModDivS(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f%% %r)"; } virtual string emitC() { return "VL_MODDIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; } virtual bool cleanOut() const { return false; } @@ -6032,16 +6902,22 @@ public: virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return true; } virtual bool sizeMattersRhs() const { return true; } - virtual int instrCount() const { return widthInstrs()*instrCountDiv(); } + virtual int instrCount() const { return widthInstrs() * instrCountDiv(); } virtual bool signedFlavor() const { return true; } }; class AstPow : public AstNodeBiop { public: AstPow(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(Pow) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstPow(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPow(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstPow(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opPow(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f** %r)"; } virtual string emitC() { return "VL_POW_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } virtual bool cleanOut() const { return false; } @@ -6049,15 +6925,21 @@ public: virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return true; } virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs()*instrCountMul()*10; } + virtual int instrCount() const { return widthInstrs() * instrCountMul() * 10; } }; class AstPowD : public AstNodeBiop { public: AstPowD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetDouble(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetDouble(); + } ASTNODE_NODE_FUNCS(PowD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstPowD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowD(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstPowD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opPowD(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f** %r)"; } virtual string emitC() { return "pow(%li,%ri)"; } virtual bool cleanOut() const { return false; } @@ -6065,16 +6947,22 @@ public: virtual bool cleanRhs() const { return false; } virtual bool sizeMattersLhs() const { return false; } virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountDoubleDiv()*5; } + virtual int instrCount() const { return instrCountDoubleDiv() * 5; } virtual bool doubleFlavor() const { return true; } }; class AstPowSU : public AstNodeBiop { public: AstPowSU(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(PowSU) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstPowSU(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowSU(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstPowSU(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opPowSU(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f** %r)"; } virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,0)"; } virtual bool cleanOut() const { return false; } @@ -6082,16 +6970,22 @@ public: virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return true; } virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs()*instrCountMul()*10; } + virtual int instrCount() const { return widthInstrs() * instrCountMul() * 10; } virtual bool signedFlavor() const { return true; } }; class AstPowSS : public AstNodeBiop { public: AstPowSS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(PowSS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstPowSS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowSS(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstPowSS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opPowSS(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f** %r)"; } virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,1)"; } virtual bool cleanOut() const { return false; } @@ -6099,16 +6993,22 @@ public: virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return true; } virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs()*instrCountMul()*10; } + virtual int instrCount() const { return widthInstrs() * instrCountMul() * 10; } virtual bool signedFlavor() const { return true; } }; class AstPowUS : public AstNodeBiop { public: AstPowUS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(PowUS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstPowUS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowUS(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstPowUS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opPowUS(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f** %r)"; } virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 0,1)"; } virtual bool cleanOut() const { return false; } @@ -6116,16 +7016,22 @@ public: virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return true; } virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs()*instrCountMul()*10; } + virtual int instrCount() const { return widthInstrs() * instrCountMul() * 10; } virtual bool signedFlavor() const { return true; } }; class AstEqCase : public AstNodeBiCom { public: AstEqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(EqCase) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEqCase(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opCaseEq(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstEqCase(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opCaseEq(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f=== %r)"; } virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "=="; } @@ -6138,10 +7044,16 @@ public: class AstNeqCase : public AstNodeBiCom { public: AstNeqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(NeqCase) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstNeqCase(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opCaseNeq(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstNeqCase(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opCaseNeq(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f!== %r)"; } virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "!="; } @@ -6155,11 +7067,18 @@ class AstEqWild : public AstNodeBiop { // Note wildcard operator rhs differs from lhs public: AstEqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(EqWild) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEqWild(this->fileline(), lhsp, rhsp); } - static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstEqWild/AstEqD - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildEq(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstEqWild(this->fileline(), lhsp, rhsp); + } + static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, + AstNode* rhsp); // Return AstEqWild/AstEqD + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opWildEq(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f==? %r)"; } virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "=="; } @@ -6172,10 +7091,16 @@ public: class AstNeqWild : public AstNodeBiop { public: AstNeqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetLogicBool(); + } ASTNODE_NODE_FUNCS(NeqWild) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstNeqWild(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opWildNeq(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstNeqWild(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opWildNeq(lhs, rhs); + } virtual string emitVerilog() { return "%k(%l %f!=? %r)"; } virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return "!="; } @@ -6191,31 +7116,41 @@ public: AstConcat(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { if (lhsp->dtypep() && rhsp->dtypep()) { - dtypeSetLogicSized(lhsp->dtypep()->width()+rhsp->dtypep()->width(), + dtypeSetLogicSized(lhsp->dtypep()->width() + rhsp->dtypep()->width(), AstNumeric::UNSIGNED); } } ASTNODE_NODE_FUNCS(Concat) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstConcat(this->fileline(), lhsp, rhsp); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstConcat(this->fileline(), lhsp, rhsp); + } virtual string emitVerilog() { return "%f{%l, %k%r}"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opConcat(lhs, rhs); } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opConcat(lhs, rhs); + } virtual string emitC() { return "VL_CONCAT_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } virtual bool cleanOut() const { return true; } virtual bool cleanLhs() const { return true; } virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs()*2; } + virtual int instrCount() const { return widthInstrs() * 2; } }; class AstConcatN : public AstNodeBiop { // String concatenate public: AstConcatN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetString(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetString(); + } ASTNODE_NODE_FUNCS(ConcatN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstConcatN(this->fileline(), lhsp, rhsp); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstConcatN(this->fileline(), lhsp, rhsp); + } virtual string emitVerilog() { return "%f{%l, %k%r}"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opConcatN(lhs, rhs); } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opConcatN(lhs, rhs); + } virtual string emitC() { return "VL_CONCATN_NNN(%li, %ri)"; } virtual bool cleanOut() const { return true; } virtual bool cleanLhs() const { return true; } @@ -6232,19 +7167,27 @@ private: void init() { if (lhsp()) { if (const AstConst* constp = VN_CAST(rhsp(), Const)) { - dtypeSetLogicSized(lhsp()->width()*constp->toUInt(), - AstNumeric::UNSIGNED); + dtypeSetLogicSized(lhsp()->width() * constp->toUInt(), AstNumeric::UNSIGNED); } } } + public: AstReplicate(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { init(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + init(); + } AstReplicate(FileLine* fl, AstNode* lhsp, uint32_t repCount) - : ASTGEN_SUPER(fl, lhsp, new AstConst(fl, repCount)) { init(); } + : ASTGEN_SUPER(fl, lhsp, new AstConst(fl, repCount)) { + init(); + } ASTNODE_NODE_FUNCS(Replicate) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstReplicate(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opRepl(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstReplicate(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opRepl(lhs, rhs); + } virtual string emitVerilog() { return "%f{%r{%k%l}}"; } virtual string emitC() { return "VL_REPLICATE_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } virtual bool cleanOut() const { return false; } @@ -6252,20 +7195,29 @@ public: virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs()*2; } + virtual int instrCount() const { return widthInstrs() * 2; } }; class AstReplicateN : public AstNodeBiop { // String replicate private: void init() { dtypeSetString(); } + public: AstReplicateN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { init(); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + init(); + } AstReplicateN(FileLine* fl, AstNode* lhsp, uint32_t repCount) - : ASTGEN_SUPER(fl, lhsp, new AstConst(fl, repCount)) { init(); } + : ASTGEN_SUPER(fl, lhsp, new AstConst(fl, repCount)) { + init(); + } ASTNODE_NODE_FUNCS(ReplicateN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstReplicateN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opReplN(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstReplicateN(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opReplN(lhs, rhs); + } virtual string emitVerilog() { return "%f{%r{%k%l}}"; } virtual string emitC() { return "VL_REPLICATEN_NN%rq(0,0,%rw, %li, %ri)"; } virtual bool cleanOut() const { return false; } @@ -6273,7 +7225,7 @@ public: virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs()*2; } + virtual int instrCount() const { return widthInstrs() * 2; } virtual bool stringFlavor() const { return true; } }; class AstStreamL : public AstNodeStream { @@ -6282,16 +7234,20 @@ public: AstStreamL(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(StreamL) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstStreamL(this->fileline(), lhsp, rhsp); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstStreamL(this->fileline(), lhsp, rhsp); + } virtual string emitVerilog() { return "%f{ << %r %k{%l} }"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opStreamL(lhs, rhs); } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opStreamL(lhs, rhs); + } virtual string emitC() { return "VL_STREAML_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } virtual bool cleanOut() const { return true; } virtual bool cleanLhs() const { return true; } virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return true; } virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs()*2; } + virtual int instrCount() const { return widthInstrs() * 2; } }; class AstStreamR : public AstNodeStream { // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp() @@ -6299,16 +7255,20 @@ public: AstStreamR(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(StreamR) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstStreamR(this->fileline(), lhsp, rhsp); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstStreamR(this->fileline(), lhsp, rhsp); + } virtual string emitVerilog() { return "%f{ >> %r %k{%l} }"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAssign(lhs); } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opAssign(lhs); + } virtual string emitC() { return isWide() ? "VL_ASSIGN_W(%nw, %P, %li)" : "%li"; } virtual bool cleanOut() const { return false; } virtual bool cleanLhs() const { return false; } virtual bool cleanRhs() const { return false; } virtual bool sizeMattersLhs() const { return true; } virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs()*2; } + virtual int instrCount() const { return widthInstrs() * 2; } }; class AstBufIf1 : public AstNodeBiop { // lhs is enable, rhs is data to drive @@ -6316,10 +7276,16 @@ class AstBufIf1 : public AstNodeBiop { // bit enables respective rhsp bit public: AstBufIf1(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeFrom(lhsp); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } ASTNODE_NODE_FUNCS(BufIf1) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstBufIf1(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opBufIf1(lhs, rhs); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstBufIf1(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + out.opBufIf1(lhs, rhs); + } virtual string emitVerilog() { return "bufif(%r,%l)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } // Lclean || Rclean virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); } // Lclean || Rclean @@ -6334,8 +7300,12 @@ public: AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(FGetS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstFGetS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstFGetS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + V3ERROR_NA; + } virtual string emitVerilog() { return "%f$fgets(%l,%r)"; } virtual string emitC() { return "VL_FGETS_%nqX%rq(%lw, %P, &(%li), %ri)"; } virtual bool cleanOut() const { return false; } @@ -6343,7 +7313,7 @@ public: virtual bool cleanRhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs()*64; } + virtual int instrCount() const { return widthInstrs() * 64; } AstNode* strgp() const { return lhsp(); } AstNode* filep() const { return rhsp(); } }; @@ -6351,7 +7321,9 @@ public: class AstNodeSystemBiop : public AstNodeBiop { public: AstNodeSystemBiop(AstType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : AstNodeBiop(t, fl, lhsp, rhsp) { dtypeSetDouble(); } + : AstNodeBiop(t, fl, lhsp, rhsp) { + dtypeSetDouble(); + } virtual bool cleanOut() const { return false; } virtual bool cleanLhs() const { return false; } virtual bool cleanRhs() const { return false; } @@ -6366,9 +7338,12 @@ public: AstAtan2D(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(Atan2D) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstAtan2D(this->fileline(), lhsp, rhsp); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstAtan2D(this->fileline(), lhsp, rhsp); + } virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { - out.setDouble(atan2(lhs.toDouble(), rhs.toDouble())); } + out.setDouble(atan2(lhs.toDouble(), rhs.toDouble())); + } virtual string emitVerilog() { return "%f$atan2(%l,%r)"; } virtual string emitC() { return "atan2(%li,%ri)"; } }; @@ -6378,9 +7353,12 @@ public: AstHypotD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(HypotD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstHypotD(this->fileline(), lhsp, rhsp); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + return new AstHypotD(this->fileline(), lhsp, rhsp); + } virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { - out.setDouble(hypot(lhs.toDouble(), rhs.toDouble())); } + out.setDouble(hypot(lhs.toDouble(), rhs.toDouble())); + } virtual string emitVerilog() { return "%f$hypot(%l,%r)"; } virtual string emitC() { return "hypot(%li,%ri)"; } }; @@ -6389,10 +7367,12 @@ class AstPutcN : public AstNodeTriop { // Verilog string.putc() public: AstPutcN(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* ths) - : ASTGEN_SUPER(fl, lhsp, rhsp, ths) { dtypeSetString(); } + : ASTGEN_SUPER(fl, lhsp, rhsp, ths) { + dtypeSetString(); + } ASTNODE_NODE_FUNCS(PutcN) - virtual void numberOperate(V3Number& out, const V3Number& lhs, - const V3Number& rhs, const V3Number& ths) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) { out.opPutcN(lhs, rhs, ths); } virtual string name() const { return "putc"; } @@ -6412,7 +7392,9 @@ class AstGetcN : public AstNodeBiop { // Verilog string.getc() public: AstGetcN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetBitSized(8, AstNumeric::UNSIGNED); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetBitSized(8, AstNumeric::UNSIGNED); + } ASTNODE_NODE_FUNCS(GetcN) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGetcN(this->fileline(), lhsp, rhsp); @@ -6436,7 +7418,9 @@ class AstGetcRefN : public AstNodeBiop { // Spec says is of type byte (not string of single character) public: AstGetcRefN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetBitSized(8, AstNumeric::UNSIGNED); } + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetBitSized(8, AstNumeric::UNSIGNED); + } ASTNODE_NODE_FUNCS(GetcRefN) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstGetcRefN(this->fileline(), lhsp, rhsp); @@ -6458,10 +7442,12 @@ class AstSubstrN : public AstNodeTriop { // Verilog string.substr() public: AstSubstrN(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* ths) - : ASTGEN_SUPER(fl, lhsp, rhsp, ths) { dtypeSetString(); } + : ASTGEN_SUPER(fl, lhsp, rhsp, ths) { + dtypeSetString(); + } ASTNODE_NODE_FUNCS(SubstrN) - virtual void numberOperate(V3Number& out, const V3Number& lhs, - const V3Number& rhs, const V3Number& ths) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) { out.opSubstrN(lhs, rhs, ths); } virtual string name() const { return "substr"; } @@ -6515,10 +7501,15 @@ class AstPast : public AstNodeMath { // Children: expression public: AstPast(FileLine* fl, AstNode* exprp, AstNode* ticksp) - : ASTGEN_SUPER(fl) { addOp1p(exprp); addNOp2p(ticksp); } + : ASTGEN_SUPER(fl) { + addOp1p(exprp); + addNOp2p(ticksp); + } ASTNODE_NODE_FUNCS(Past) virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + V3ERROR_NA; + } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const { V3ERROR_NA_RETURN(""); } @@ -6537,7 +7528,9 @@ class AstSampled : public AstNodeMath { // Children: expression public: AstSampled(FileLine* fl, AstNode* exprp) - : ASTGEN_SUPER(fl) { addOp1p(exprp); } + : ASTGEN_SUPER(fl) { + addOp1p(exprp); + } ASTNODE_NODE_FUNCS(Sampled) virtual string emitVerilog() { return "$sampled(%l)"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } @@ -6555,16 +7548,22 @@ class AstPattern : public AstNodeMath { // Children: expression, AstPattern, AstPatReplicate public: AstPattern(FileLine* fl, AstNode* itemsp) - : ASTGEN_SUPER(fl) { addNOp2p(itemsp); } + : ASTGEN_SUPER(fl) { + addNOp2p(itemsp); + } ASTNODE_NODE_FUNCS(Pattern) virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + V3ERROR_NA; + } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const { V3ERROR_NA_RETURN(""); } virtual int instrCount() const { return widthInstrs(); } AstNodeDType* getChildDTypep() const { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Type assigning to + AstNodeDType* childDTypep() const { + return VN_CAST(op1p(), NodeDType); + } // op1 = Type assigning to void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } AstNode* itemsp() const { return op2p(); } // op2 = AstPatReplicate, AstPatMember, etc @@ -6574,18 +7573,25 @@ class AstPatMember : public AstNodeMath { // Parents: AstPattern // Children: expression, AstPattern, replication count private: - bool m_default; + bool m_default; + public: AstPatMember(FileLine* fl, AstNode* lhsp, AstNode* keyp, AstNode* repp) - : ASTGEN_SUPER(fl) { addOp1p(lhsp), setNOp2p(keyp), setNOp3p(repp); m_default = false; } + : ASTGEN_SUPER(fl) { + addOp1p(lhsp), setNOp2p(keyp), setNOp3p(repp); + m_default = false; + } ASTNODE_NODE_FUNCS(PatMember) - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + V3ERROR_NA; + } virtual string emitVerilog() { return lhssp() ? "%f{%r{%k%l}}" : "%l"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const { V3ERROR_NA_RETURN(""); } virtual int instrCount() const { return widthInstrs() * 2; } - AstNode* lhssp() const { return op1p(); } // op1 = expression to assign or another AstPattern (list if replicated) + // op1 = expression to assign or another AstPattern (list if replicated) + AstNode* lhssp() const { return op1p(); } AstNode* keyp() const { return op2p(); } // op2 = assignment key (Const, id Text) AstNode* repp() const { return op3p(); } // op3 = replication count, or NULL for count 1 bool isDefault() const { return m_default; } @@ -6606,7 +7612,8 @@ public: addNOp2p(bodysp); } ASTNODE_NODE_FUNCS(Clocking) - AstNodeSenItem* sensesp() const { return VN_CAST(op1p(), NodeSenItem); } // op1 = Sensitivity list + // op1 = Sensitivity list + AstNodeSenItem* sensesp() const { return VN_CAST(op1p(), NodeSenItem); } AstNode* bodysp() const { return op2p(); } // op2 = Body }; @@ -6626,7 +7633,9 @@ public: } ASTNODE_NODE_FUNCS(PropClocked) virtual bool hasDType() const { return true; } // Used under Cover, which expects a bool child - AstNodeSenItem* sensesp() const { return VN_CAST(op1p(), NodeSenItem); } // op1 = Sensitivity list + AstNodeSenItem* sensesp() const { + return VN_CAST(op1p(), NodeSenItem); + } // op1 = Sensitivity list AstNode* disablep() const { return op2p(); } // op2 = disable AstNode* propp() const { return op3p(); } // op3 = property }; @@ -6639,8 +7648,8 @@ private: bool m_immediate; // Immediate assertion/cover string m_name; // Name to report public: - AstNodeCoverOrAssert(AstType t, FileLine* fl, AstNode* propp, AstNode* passsp, - bool immediate, const string& name="") + AstNodeCoverOrAssert(AstType t, FileLine* fl, AstNode* propp, AstNode* passsp, bool immediate, + const string& name = "") : AstNodeStmt(t, fl) , m_immediate(immediate) , m_name(name) { @@ -6652,7 +7661,7 @@ public: virtual V3Hash sameHash() const { return V3Hash(name()); } virtual bool same(const AstNode* samep) const { return samep->name() == name(); } virtual void name(const string& name) { m_name = name; } - virtual void dump(std::ostream& str=std::cout) const; + virtual void dump(std::ostream& str = std::cout) const; AstNode* propp() const { return op1p(); } // op1 = property AstSenTree* sentreep() const { return VN_CAST(op2p(), SenTree); } // op2 = clock domain void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain @@ -6663,8 +7672,8 @@ public: class AstAssert : public AstNodeCoverOrAssert { public: ASTNODE_NODE_FUNCS(Assert) - AstAssert(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, - bool immediate, const string& name = "") + AstAssert(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, bool immediate, + const string& name = "") : ASTGEN_SUPER(fl, propp, passsp, immediate, name) { addNOp3p(failsp); } @@ -6674,8 +7683,8 @@ public: class AstCover : public AstNodeCoverOrAssert { public: ASTNODE_NODE_FUNCS(Cover) - AstCover(FileLine* fl, AstNode* propp, AstNode* stmtsp, - bool immediate, const string& name = "") + AstCover(FileLine* fl, AstNode* propp, AstNode* stmtsp, bool immediate, + const string& name = "") : ASTGEN_SUPER(fl, propp, stmtsp, immediate, name) {} AstNode* coverincp() const { return op3p(); } // op3 = coverage node void coverincp(AstCoverInc* nodep) { addOp3p(nodep); } // op3 = coverage node @@ -6696,8 +7705,9 @@ class AstNodeSimpleText : public AstNodeText { private: bool m_tracking; // When emit, it's ok to parse the string to do indentation public: - AstNodeSimpleText(AstType t, FileLine* fl, const string& textp, bool tracking=false) - : AstNodeText(t, fl, textp), m_tracking(tracking) {} + AstNodeSimpleText(AstType t, FileLine* fl, const string& textp, bool tracking = false) + : AstNodeText(t, fl, textp) + , m_tracking(tracking) {} ASTNODE_BASE_FUNCS(NodeSimpleText) void tracking(bool flag) { m_tracking = flag; } bool tracking() const { return m_tracking; } @@ -6705,7 +7715,7 @@ public: class AstText : public AstNodeSimpleText { public: - AstText(FileLine* fl, const string& textp, bool tracking=false) + AstText(FileLine* fl, const string& textp, bool tracking = false) : ASTGEN_SUPER(fl, textp, tracking) {} ASTNODE_NODE_FUNCS(Text) }; @@ -6723,7 +7733,7 @@ public: bool commas() const { return m_commas; } AstNode* nodesp() const { return op1p(); } void addNodep(AstNode* nodep) { addOp1p(nodep); } - void addText(FileLine* fl, const string& textp, bool tracking=false) { + void addText(FileLine* fl, const string& textp, bool tracking = false) { addNodep(new AstText(fl, textp, tracking)); } }; @@ -6807,7 +7817,7 @@ class AstNodeFile : public AstNode { // Parents: NETLIST // Children: AstTextBlock private: - string m_name; ///< Filename + string m_name; ///< Filename public: AstNodeFile(AstType t, FileLine* fl, const string& name) : AstNode(t, fl) { @@ -6831,7 +7841,7 @@ public: AstVFile(FileLine* fl, const string& name) : ASTGEN_SUPER(fl, name) {} ASTNODE_NODE_FUNCS(VFile) - virtual void dump(std::ostream& str=std::cout) const; + virtual void dump(std::ostream& str = std::cout) const; }; //====================================================================== @@ -6841,9 +7851,9 @@ class AstCFile : public AstNodeFile { // C++ output file // Parents: NETLIST private: - bool m_slow:1; ///< Compile w/o optimization - bool m_source:1; ///< Source file (vs header file) - bool m_support:1; ///< Support file (non systemc) + bool m_slow : 1; ///< Compile w/o optimization + bool m_source : 1; ///< Source file (vs header file) + bool m_support : 1; ///< Support file (non systemc) public: AstCFile(FileLine* fl, const string& name) : ASTGEN_SUPER(fl, name) { @@ -6852,7 +7862,7 @@ public: m_support = false; } ASTNODE_NODE_FUNCS(CFile) - virtual void dump(std::ostream& str=std::cout) const; + virtual void dump(std::ostream& str = std::cout) const; bool slow() const { return m_slow; } void slow(bool flag) { m_slow = flag; } bool source() const { return m_source; } @@ -6867,34 +7877,34 @@ class AstCFunc : public AstNode { // Children: VAR/statements private: AstCFuncType m_funcType; - AstScope* m_scopep; - string m_name; - string m_cname; // C name, for dpiExports - string m_rtnType; // void, bool, or other return type - string m_argTypes; - string m_ifdef; // #ifdef symbol around this function - VBoolOrUnknown m_isConst; // Function is declared const (*this not changed) - VBoolOrUnknown m_isStatic; // Function is declared static (no this) - bool m_dontCombine:1; // V3Combine shouldn't compare this func tree, it's special - bool m_skipDecl:1; // Don't declare it - bool m_declPrivate:1; // Declare it private - bool m_formCallTree:1; // Make a global function to call entire tree of functions - bool m_slow:1; // Slow routine, called once or just at init time - bool m_funcPublic:1; // From user public task/function - bool m_isConstructor:1; // Is C class constructor - bool m_isDestructor:1; // Is C class destructor - bool m_isMethod:1; // Is inside a class definition - bool m_isInline:1; // Inline function - bool m_isVirtual:1; // Virtual function - bool m_symProlog:1; // Setup symbol table for later instructions - bool m_entryPoint:1; // User may call into this top level function - bool m_pure:1; // Pure function - bool m_dpiExport:1; // From dpi export - bool m_dpiExportWrapper:1; // From dpi export; static function with dispatch table - bool m_dpiImport:1; // From dpi import - bool m_dpiImportWrapper:1; // Wrapper from dpi import + AstScope* m_scopep; + string m_name; + string m_cname; // C name, for dpiExports + string m_rtnType; // void, bool, or other return type + string m_argTypes; + string m_ifdef; // #ifdef symbol around this function + VBoolOrUnknown m_isConst; // Function is declared const (*this not changed) + VBoolOrUnknown m_isStatic; // Function is declared static (no this) + bool m_dontCombine : 1; // V3Combine shouldn't compare this func tree, it's special + bool m_skipDecl : 1; // Don't declare it + bool m_declPrivate : 1; // Declare it private + bool m_formCallTree : 1; // Make a global function to call entire tree of functions + bool m_slow : 1; // Slow routine, called once or just at init time + bool m_funcPublic : 1; // From user public task/function + bool m_isConstructor : 1; // Is C class constructor + bool m_isDestructor : 1; // Is C class destructor + bool m_isMethod : 1; // Is inside a class definition + bool m_isInline : 1; // Inline function + bool m_isVirtual : 1; // Virtual function + bool m_symProlog : 1; // Setup symbol table for later instructions + bool m_entryPoint : 1; // User may call into this top level function + bool m_pure : 1; // Pure function + bool m_dpiExport : 1; // From dpi export + bool m_dpiExportWrapper : 1; // From dpi export; static function with dispatch table + bool m_dpiImport : 1; // From dpi import + bool m_dpiImportWrapper : 1; // Wrapper from dpi import public: - AstCFunc(FileLine* fl, const string& name, AstScope* scopep, const string& rtnType="") + AstCFunc(FileLine* fl, const string& name, AstScope* scopep, const string& rtnType = "") : ASTGEN_SUPER(fl) { m_funcType = AstCFuncType::FT_NORMAL; m_isConst = VBoolOrUnknown::BU_UNKNOWN; // Unknown until analyzed @@ -6923,17 +7933,19 @@ public: } ASTNODE_NODE_FUNCS(CFunc) virtual string name() const { return m_name; } - virtual const char* broken() const { BROKEN_RTN((m_scopep && !m_scopep->brokeExists())); return NULL; } + virtual const char* broken() const { + BROKEN_RTN((m_scopep && !m_scopep->brokeExists())); + return NULL; + } virtual bool maybePointedTo() const { return true; } - virtual void dump(std::ostream& str=std::cout) const; + virtual void dump(std::ostream& str = std::cout) const; virtual V3Hash sameHash() const { return V3Hash(); } virtual bool same(const AstNode* samep) const { const AstCFunc* asamep = static_cast(samep); - return ((funcType() == asamep->funcType()) - && (rtnTypeVoid() == asamep->rtnTypeVoid()) + return ((funcType() == asamep->funcType()) && (rtnTypeVoid() == asamep->rtnTypeVoid()) && (argTypes() == asamep->argTypes()) - && (!(dpiImport() || dpiExport()) - || name() == asamep->name())); } + && (!(dpiImport() || dpiExport()) || name() == asamep->name())); + } // virtual void name(const string& name) { m_name = name; } virtual int instrCount() const { return dpiImport() ? instrCountDpi() : 0; } @@ -6947,8 +7959,8 @@ public: string cname() const { return m_cname; } AstScope* scopep() const { return m_scopep; } void scopep(AstScope* nodep) { m_scopep = nodep; } - string rtnTypeVoid() const { return ((m_rtnType=="") ? "void" : m_rtnType); } - bool dontCombine() const { return m_dontCombine || funcType()!=AstCFuncType::FT_NORMAL; } + string rtnTypeVoid() const { return ((m_rtnType == "") ? "void" : m_rtnType); } + bool dontCombine() const { return m_dontCombine || funcType() != AstCFuncType::FT_NORMAL; } void dontCombine(bool flag) { m_dontCombine = flag; } bool dontInline() const { return dontCombine() || slow() || skipDecl() || funcPublic(); } bool skipDecl() const { return m_skipDecl; } @@ -7002,7 +8014,9 @@ public: AstNode* finalsp() const { return op4p(); } void addFinalsp(AstNode* nodep) { addOp4p(nodep); } // Special methods - bool emptyBody() const { return argsp()==NULL && initsp()==NULL && stmtsp()==NULL && finalsp()==NULL; } + bool emptyBody() const { + return argsp() == NULL && initsp() == NULL && stmtsp() == NULL && finalsp() == NULL; + } }; class AstCCall : public AstNodeCCall { @@ -7079,12 +8093,16 @@ private: public: // Emit C textual math function (like AstUCFunc) AstCMath(FileLine* fl, AstNode* exprsp) - : ASTGEN_SUPER(fl), m_cleanOut(true), m_pure(false) { + : ASTGEN_SUPER(fl) + , m_cleanOut(true) + , m_pure(false) { addOp1p(exprsp); dtypeFrom(exprsp); } - AstCMath(FileLine* fl, const string& textStmt, int setwidth, bool cleanOut=true) - : ASTGEN_SUPER(fl), m_cleanOut(cleanOut), m_pure(true) { + AstCMath(FileLine* fl, const string& textStmt, int setwidth, bool cleanOut = true) + : ASTGEN_SUPER(fl) + , m_cleanOut(cleanOut) + , m_pure(true) { addNOp1p(new AstText(fl, textStmt, true)); if (setwidth) { dtypeSetLogicSized(setwidth, AstNumeric::UNSIGNED); } } @@ -7143,6 +8161,7 @@ class AstCUse : public AstNode { private: VUseType m_useType; // What sort of use this is string m_name; + public: AstCUse(FileLine* fl, VUseType useType, const string& name) : ASTGEN_SUPER(fl) @@ -7159,17 +8178,21 @@ class AstMTaskBody : public AstNode { // Hold statements for each MTask private: ExecMTask* m_execMTaskp; + public: explicit AstMTaskBody(FileLine* fl) : ASTGEN_SUPER(fl) , m_execMTaskp(NULL) {} ASTNODE_NODE_FUNCS(MTaskBody); - virtual const char* broken() const { BROKEN_RTN(!m_execMTaskp); return NULL; } + virtual const char* broken() const { + BROKEN_RTN(!m_execMTaskp); + return NULL; + } AstNode* stmtsp() const { return op1p(); } void addStmtsp(AstNode* nodep) { addOp1p(nodep); } ExecMTask* execMTaskp() const { return m_execMTaskp; } void execMTaskp(ExecMTask* execMTaskp) { m_execMTaskp = execMTaskp; } - virtual void dump(std::ostream& str=std::cout) const; + virtual void dump(std::ostream& str = std::cout) const; }; class AstExecGraph : public AstNode { @@ -7182,12 +8205,15 @@ class AstExecGraph : public AstNode { // them without traversing the graph (it's not always needed to // traverse the graph.) private: - V3Graph *m_depGraphp; // contains ExecMTask's + V3Graph* m_depGraphp; // contains ExecMTask's public: explicit AstExecGraph(FileLine* fl); ASTNODE_NODE_FUNCS_NO_DTOR(ExecGraph) virtual ~AstExecGraph(); - virtual const char* broken() const { BROKEN_RTN(!m_depGraphp); return NULL; } + virtual const char* broken() const { + BROKEN_RTN(!m_depGraphp); + return NULL; + } const V3Graph* depGraphp() const { return m_depGraphp; } V3Graph* mutableDepGraphp() { return m_depGraphp; } void addMTaskBody(AstMTaskBody* bodyp) { addOp1p(bodyp); } @@ -7210,26 +8236,28 @@ class AstTypeTable : public AstNode { AstVoidDType* m_voidp; AstBasicDType* m_basicps[AstBasicDTypeKwd::_ENUM_MAX]; // - typedef std::map DetailedMap; + typedef std::map DetailedMap; DetailedMap m_detailedMap; + public: explicit AstTypeTable(FileLine* fl) - : ASTGEN_SUPER(fl), m_voidp(NULL) { - for (int i=0; i1 mode public: AstNetlist() @@ -7258,26 +8286,33 @@ public: return NULL; } AstNodeModule* modulesp() const { // op1 = List of modules - return VN_CAST(op1p(), NodeModule); } + return VN_CAST(op1p(), NodeModule); + } AstNodeModule* topModulep() const { // * = Top module in hierarchy (first one added, for now) - return VN_CAST(op1p(), NodeModule); } + return VN_CAST(op1p(), NodeModule); + } void addModulep(AstNodeModule* modulep) { addOp1p(modulep); } AstNodeFile* filesp() const { return VN_CAST(op2p(), NodeFile); } // op2 = List of files void addFilesp(AstNodeFile* filep) { addOp2p(filep); } AstNode* miscsp() const { return op3p(); } // op3 = List of dtypes etc void addMiscsp(AstNode* nodep) { addOp3p(nodep); } AstTypeTable* typeTablep() { return m_typeTablep; } - void addTypeTablep(AstTypeTable* nodep) { m_typeTablep = nodep; addMiscsp(nodep); } + void addTypeTablep(AstTypeTable* nodep) { + m_typeTablep = nodep; + addMiscsp(nodep); + } AstPackage* dollarUnitPkgp() const { return m_dollarUnitPkgp; } AstPackage* dollarUnitPkgAddp() { if (!m_dollarUnitPkgp) { m_dollarUnitPkgp = new AstPackage(fileline(), AstPackage::dollarUnitName()); - m_dollarUnitPkgp->inLibrary(true); // packages are always libraries; don't want to make them a "top" + // packages are always libraries; don't want to make them a "top" + m_dollarUnitPkgp->inLibrary(true); m_dollarUnitPkgp->modTrace(false); // may reconsider later m_dollarUnitPkgp->internal(true); addModulep(m_dollarUnitPkgp); } - return m_dollarUnitPkgp; } + return m_dollarUnitPkgp; + } AstCFunc* evalp() const { return m_evalp; } void evalp(AstCFunc* evalp) { m_evalp = evalp; } AstExecGraph* execGraphp() const { return m_execGraphp; } diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index 80cd56fe8..e1fc1cbf9 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -42,14 +42,14 @@ class BeginState { private: // NODE STATE - //Entire netlist: + // Entire netlist: // AstNodeFTask::user1 -> bool, 1=processed - AstUser1InUse m_inuser1; - bool m_anyFuncInBegin; + AstUser1InUse m_inuser1; + bool m_anyFuncInBegin; + public: - BeginState() { - m_anyFuncInBegin = false; - } + BeginState() + : m_anyFuncInBegin(false) {} ~BeginState() {} void userMarkChanged(AstNode* nodep) { nodep->user1(true); @@ -63,12 +63,12 @@ public: class BeginVisitor : public AstNVisitor { private: // STATE - BeginState* m_statep; // Current global state - AstNodeModule* m_modp; // Current module - AstNodeFTask* m_ftaskp; // Current function/task - string m_namedScope; // Name of begin blocks above us - string m_unnamedScope; // Name of begin blocks, including unnamed blocks - int m_ifDepth; // Current if depth + BeginState* m_statep; // Current global state + AstNodeModule* m_modp; // Current module + AstNodeFTask* m_ftaskp; // Current function/task + string m_namedScope; // Name of begin blocks above us + string m_unnamedScope; // Name of begin blocks, including unnamed blocks + int m_ifDepth; // Current if depth // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -83,11 +83,11 @@ private: m_modp = origModp; } virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { - UINFO(8," "<name(m_unnamedScope+"__DOT__"+nodep->name()); - UINFO(8," rename to "<name()<name(m_unnamedScope + "__DOT__" + nodep->name()); + UINFO(8, " rename to " << nodep->name() << endl); m_statep->userMarkChanged(nodep); } // BEGIN wrapping a function rename that function, but don't affect @@ -109,28 +109,34 @@ private: } virtual void visit(AstBegin* nodep) VL_OVERRIDE { // Begin blocks were only useful in variable creation, change names and delete - UINFO(8," "<name() != "") { // Else unneeded unnamed block // Create data for dotted variable resolution string dottedname = nodep->name() + "__DOT__"; // So always found string::size_type pos; - while ((pos=dottedname.find("__DOT__")) != string::npos) { + while ((pos = dottedname.find("__DOT__")) != string::npos) { string ident = dottedname.substr(0, pos); - dottedname = dottedname.substr(pos+strlen("__DOT__")); + dottedname = dottedname.substr(pos + strlen("__DOT__")); if (nodep->name() != "") { - if (m_namedScope=="") m_namedScope = ident; - else m_namedScope = m_namedScope + "__DOT__"+ident; + if (m_namedScope == "") { + m_namedScope = ident; + } else { + m_namedScope = m_namedScope + "__DOT__" + ident; + } + } + if (m_unnamedScope == "") { + m_unnamedScope = ident; + } else { + m_unnamedScope = m_unnamedScope + "__DOT__" + ident; } - if (m_unnamedScope=="") m_unnamedScope = ident; - else m_unnamedScope = m_unnamedScope + "__DOT__"+ident; // Create CellInline for dotted var resolution if (!m_ftaskp) { - AstCellInline* inlinep = new AstCellInline(nodep->fileline(), - m_unnamedScope, "__BEGIN__"); + AstCellInline* inlinep + = new AstCellInline(nodep->fileline(), m_unnamedScope, "__BEGIN__"); m_modp->addInlinesp(inlinep); // Must be parsed before any AstCells } } @@ -147,7 +153,11 @@ private: AstNode* addsp = NULL; if (AstNode* stmtsp = nodep->stmtsp()) { stmtsp->unlinkFrBackWithNext(); - if (addsp) { addsp = addsp->addNextNull(stmtsp); } else { addsp = stmtsp; } + if (addsp) { + addsp = addsp->addNextNull(stmtsp); + } else { + addsp = stmtsp; + } } if (addsp) { nodep->replaceWith(addsp); @@ -159,12 +169,15 @@ private: virtual void visit(AstVar* nodep) VL_OVERRIDE { if (m_unnamedScope != "") { // Rename it - nodep->name(m_unnamedScope+"__DOT__"+nodep->name()); + nodep->name(m_unnamedScope + "__DOT__" + nodep->name()); m_statep->userMarkChanged(nodep); // Move to module nodep->unlinkFrBack(); - if (m_ftaskp) m_ftaskp->addStmtsp(nodep); // Begins under funcs just move into the func - else m_modp->addStmtp(nodep); + if (m_ftaskp) { + m_ftaskp->addStmtsp(nodep); // Begins under funcs just move into the func + } else { + m_modp->addStmtp(nodep); + } } } virtual void visit(AstTypedef* nodep) VL_OVERRIDE { @@ -175,17 +188,20 @@ private: // Move to module nodep->unlinkFrBack(); // Begins under funcs just move into the func - if (m_ftaskp) m_ftaskp->addStmtsp(nodep); - else m_modp->addStmtp(nodep); + if (m_ftaskp) { + m_ftaskp->addStmtsp(nodep); + } else { + m_modp->addStmtp(nodep); + } } } virtual void visit(AstCell* nodep) VL_OVERRIDE { - UINFO(8," CELL "<userMarkChanged(nodep); // Rename it - nodep->name(m_namedScope+"__DOT__"+nodep->name()); - UINFO(8," rename to "<name()<name(m_namedScope + "__DOT__" + nodep->name()); + UINFO(8, " rename to " << nodep->name() << endl); // Move to module nodep->unlinkFrBack(); m_modp->addStmtp(nodep); @@ -193,10 +209,10 @@ private: iterateChildren(nodep); } virtual void visit(AstVarXRef* nodep) VL_OVERRIDE { - UINFO(9, " VARXREF "<inlinedDots() == "") { nodep->inlinedDots(m_namedScope); - UINFO(9, " rescope to "<scopeAttrp(); if (afterp) afterp->unlinkFrBackWithNext(); - nodep->scopeAttrp(new AstText(nodep->fileline(), string("__DOT__")+m_namedScope)); + nodep->scopeAttrp(new AstText(nodep->fileline(), string("__DOT__") + m_namedScope)); if (afterp) nodep->scopeAttrp(afterp); } iterateChildren(nodep); @@ -218,14 +234,15 @@ private: iterateChildren(nodep); } // VISITORS - LINT CHECK - virtual void visit(AstIf* nodep) VL_OVERRIDE { // Note not AstNodeIf; other types don't get covered + virtual void visit(AstIf* nodep) VL_OVERRIDE { // not AstNodeIf; other types not covered // Check IFDEPTH warning - could be in other transform files if desire int prevIfDepth = m_ifDepth; - if (m_ifDepth == -1 || v3Global.opt.ifDepth()<1) { // Turned off + if (m_ifDepth == -1 || v3Global.opt.ifDepth() < 1) { // Turned off } else if (nodep->uniquePragma() || nodep->unique0Pragma() || nodep->priorityPragma()) { m_ifDepth = -1; } else if (++m_ifDepth > v3Global.opt.ifDepth()) { - nodep->v3warn(IFDEPTH,"Deep 'if' statement; suggest unique/priority to avoid slow logic"); + nodep->v3warn(IFDEPTH, + "Deep 'if' statement; suggest unique/priority to avoid slow logic"); nodep->fileline()->modifyWarnOff(V3ErrorCode::IFDEPTH, true); // Warn only once m_ifDepth = -1; } @@ -258,14 +275,14 @@ private: // VISITORS virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { if (nodep->taskp()->user1()) { // It was converted - UINFO(9, " relinkFTask "<name(nodep->taskp()->name()); } iterateChildren(nodep); } virtual void visit(AstVarRef* nodep) VL_OVERRIDE { if (nodep->varp()->user1()) { // It was converted - UINFO(9, " relinVarRef "<name(nodep->varp()->name()); } iterateChildren(nodep); @@ -273,9 +290,9 @@ private: virtual void visit(AstIfaceRefDType* nodep) VL_OVERRIDE { // May have changed cell names // TypeTable is always after all modules, so names are stable - UINFO(8," IFACEREFDTYPE "<cellp()) nodep->cellName(nodep->cellp()->name()); - UINFO(8," rename to "<= 3); } diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index b27dc4b04..21db1485f 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -42,35 +42,35 @@ class BrokenTable : public AstNVisitor { private: // MEMBERS // For each node, we keep if it exists or not. - typedef vl_unordered_map NodeMap; // Performance matters (when --debug) + typedef vl_unordered_map NodeMap; // Performance matters (when --debug) static NodeMap s_nodes; // Set of all nodes that exist // BITMASK - enum { FLAG_ALLOCATED = 0x01 }; // new() and not delete()ed - enum { FLAG_IN_TREE = 0x02 }; // Is in netlist tree - enum { FLAG_LINKABLE = 0x04 }; // Is in netlist tree, can be linked to - enum { FLAG_LEAKED = 0x08 }; // Known to have been leaked - enum { FLAG_UNDER_NOW = 0x10 }; // Is in tree as parent of current node + enum { FLAG_ALLOCATED = 0x01 }; // new() and not delete()ed + enum { FLAG_IN_TREE = 0x02 }; // Is in netlist tree + enum { FLAG_LINKABLE = 0x04 }; // Is in netlist tree, can be linked to + enum { FLAG_LEAKED = 0x08 }; // Known to have been leaked + enum { FLAG_UNDER_NOW = 0x10 }; // Is in tree as parent of current node public: // METHODS static void deleted(const AstNode* nodep) { // Called by operator delete on any node - only if VL_LEAK_CHECKS - if (debug()>=9) cout<<"-nodeDel: "<= 9) cout << "-nodeDel: " << cvtToHex(nodep) << endl; NodeMap::iterator iter = s_nodes.find(nodep); - UASSERT_OBJ(!(iter==s_nodes.end() || !(iter->second & FLAG_ALLOCATED)), + UASSERT_OBJ(!(iter == s_nodes.end() || !(iter->second & FLAG_ALLOCATED)), reinterpret_cast(nodep), "Deleting AstNode object that was never tracked or already deleted"); - if (iter!=s_nodes.end()) s_nodes.erase(iter); + if (iter != s_nodes.end()) s_nodes.erase(iter); } #if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 4 // GCC 4.4.* compiler warning bug, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=39390 -# pragma GCC diagnostic ignored "-Wstrict-aliasing" +#pragma GCC diagnostic ignored "-Wstrict-aliasing" #endif static void addNewed(const AstNode* nodep) { // Called by operator new on any node - only if VL_LEAK_CHECKS - if (debug()>=9) cout<<"-nodeNew: "<= 9) cout << "-nodeNew: " << cvtToHex(nodep) << endl; NodeMap::iterator iter = s_nodes.find(nodep); - UASSERT_OBJ(!(iter !=s_nodes.end() && (iter->second & FLAG_ALLOCATED)), - nodep, "Newing AstNode object that is already allocated"); + UASSERT_OBJ(!(iter != s_nodes.end() && (iter->second & FLAG_ALLOCATED)), nodep, + "Newing AstNode object that is already allocated"); if (iter == s_nodes.end()) { int flags = FLAG_ALLOCATED; // This int needed to appease GCC 4.1.2 s_nodes.insert(make_pair(nodep, flags)); @@ -80,9 +80,9 @@ public: // Called by BrokenCheckVisitor when each node entered/exited if (!okIfLinkedTo(nodep)) return; NodeMap::iterator iter = s_nodes.find(nodep); - if (iter!=s_nodes.end()) { + if (iter != s_nodes.end()) { iter->second &= ~FLAG_UNDER_NOW; - if (flag) iter->second |= FLAG_UNDER_NOW; + if (flag) iter->second |= FLAG_UNDER_NOW; } } static void addInTree(AstNode* nodep, bool linkable) { @@ -103,7 +103,7 @@ public: UASSERT_OBJ(!(iter->second & FLAG_IN_TREE), nodep, "AstNode is already in tree at another location"); } - int or_flags = FLAG_IN_TREE | (linkable?FLAG_LINKABLE:0); + int or_flags = FLAG_IN_TREE | (linkable ? FLAG_LINKABLE : 0); if (iter == s_nodes.end()) { s_nodes.insert(make_pair(nodep, or_flags)); } else { @@ -149,12 +149,12 @@ public: } } static void doneWithTree() { - for (int backs=0; backs<2; backs++) { // Those with backp() are probably under one leaking without + for (int backs = 0; backs < 2; + backs++) { // Those with backp() are probably under one leaking without for (NodeMap::iterator it = s_nodes.begin(); it != s_nodes.end(); ++it) { - if ((it->second & FLAG_ALLOCATED) - && !(it->second & FLAG_IN_TREE) + if ((it->second & FLAG_ALLOCATED) && !(it->second & FLAG_IN_TREE) && !(it->second & FLAG_LEAKED) - && (it->first->backp() ? backs==1 : backs==0)) { + && (it->first->backp() ? backs == 1 : backs == 0)) { // Use only AstNode::dump instead of the virtual one, as there // may be varp() and other cross links that are bad. if (v3Global.opt.debugCheck()) { @@ -163,11 +163,12 @@ public: // watch AstNode::s_editCntGbl==#### // run // bt - std::cerr<<"%Error: LeakedNode"<<(it->first->backp()?"Back: ":": "); - AstNode* rawp = const_cast - (static_cast(it->first)); + std::cerr << "%Error: LeakedNode" + << (it->first->backp() ? "Back: " : ": "); + AstNode* rawp + = const_cast(static_cast(it->first)); rawp->AstNode::dump(std::cerr); - std::cerr<second |= FLAG_LEAKED; @@ -175,6 +176,7 @@ public: } } } + public: // CONSTRUCTORS BrokenTable() {} @@ -213,9 +215,7 @@ private: public: // CONSTRUCTORS - explicit BrokenMarkVisitor(AstNetlist* nodep) { - iterate(nodep); - } + explicit BrokenMarkVisitor(AstNetlist* nodep) { iterate(nodep); } virtual ~BrokenMarkVisitor() {} }; @@ -226,27 +226,27 @@ class BrokenCheckVisitor : public AstNVisitor { private: void checkWidthMin(const AstNode* nodep) { UASSERT_OBJ(nodep->width() == nodep->widthMin() - || v3Global.widthMinUsage() != VWidthMinUsage::MATCHES_WIDTH, + || v3Global.widthMinUsage() != VWidthMinUsage::MATCHES_WIDTH, nodep, "Width != WidthMin"); } void processAndIterate(AstNode* nodep) { BrokenTable::setUnder(nodep, true); const char* whyp = nodep->broken(); UASSERT_OBJ(!whyp, nodep, - "Broken link in node (or something without maybePointedTo): "<dtypep()) { UASSERT_OBJ(nodep->dtypep()->brokeExists(), nodep, - "Broken link in node->dtypep() to "<dtypep())); + "Broken link in node->dtypep() to " << cvtToHex(nodep->dtypep())); UASSERT_OBJ(VN_IS(nodep->dtypep(), NodeDType), nodep, - "Non-dtype link in node->dtypep() to "<dtypep())); + "Non-dtype link in node->dtypep() to " << cvtToHex(nodep->dtypep())); } if (v3Global.assertDTypesResolved()) { if (nodep->hasDType()) { UASSERT_OBJ(nodep->dtypep(), nodep, - "No dtype on node with hasDType(): "<prettyTypeName()); + "No dtype on node with hasDType(): " << nodep->prettyTypeName()); } else { UASSERT_OBJ(!nodep->dtypep(), nodep, - "DType on node without hasDType(): "<prettyTypeName()); + "DType on node without hasDType(): " << nodep->prettyTypeName()); } UASSERT_OBJ(!nodep->getChildDTypep(), nodep, "childDTypep() non-null on node after should have removed"); @@ -258,8 +258,7 @@ private: } virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { processAndIterate(nodep); - UASSERT_OBJ(!(v3Global.assertDTypesResolved() - && nodep->brokeLhsMustBeLvalue() + UASSERT_OBJ(!(v3Global.assertDTypesResolved() && nodep->brokeLhsMustBeLvalue() && VN_IS(nodep->lhsp(), NodeVarRef) && !VN_CAST(nodep->lhsp(), NodeVarRef)->lvalue()), nodep, "Assignment LHS is not an lvalue"); @@ -268,11 +267,10 @@ private: // Process not just iterate processAndIterate(nodep); } + public: // CONSTRUCTORS - explicit BrokenCheckVisitor(AstNetlist* nodep) { - iterate(nodep); - } + explicit BrokenCheckVisitor(AstNetlist* nodep) { iterate(nodep); } virtual ~BrokenCheckVisitor() {} }; @@ -280,27 +278,21 @@ public: // Broken class functions void V3Broken::brokenAll(AstNetlist* nodep) { - //UINFO(9,__FUNCTION__<<": "<fileline(), - m_basename+"_"+cvtToStr(++m_funcNum), NULL, "void"); + m_funcp = new AstCFunc(m_modp->fileline(), m_basename + "_" + cvtToStr(++m_funcNum), + NULL, "void"); m_funcp->isStatic(false); m_funcp->declPrivate(true); m_funcp->slow(!VN_IS(m_modp, Class)); // Only classes construct on fast path @@ -75,9 +74,8 @@ public: m_numStmts += 1; } - V3CCtorsVisitor(AstNodeModule* nodep, const string& basename, - const string& argsp="", const string& callargsp="", - const string& stmt="") { + V3CCtorsVisitor(AstNodeModule* nodep, const string& basename, const string& argsp = "", + const string& callargsp = "", const string& stmt = "") { m_basename = basename; m_argsp = argsp; m_callargsp = callargsp; @@ -89,13 +87,12 @@ public: m_tlFuncp->isStatic(false); m_tlFuncp->slow(!VN_IS(m_modp, Class)); // Only classes construct on fast path m_tlFuncp->argTypes(m_argsp); - if (stmt != "") { - m_tlFuncp->addStmtsp(new AstCStmt(nodep->fileline(), stmt)); - } + if (stmt != "") { m_tlFuncp->addStmtsp(new AstCStmt(nodep->fileline(), stmt)); } m_funcp = m_tlFuncp; m_modp->addStmtp(m_tlFuncp); } ~V3CCtorsVisitor() {} + private: VL_UNCOPYABLE(V3CCtorsVisitor); }; @@ -122,15 +119,16 @@ void V3CCtors::evalAsserts() { if (varp->isWide()) { newp = new AstWordSel( varp->fileline(), newp, - new AstConst(varp->fileline(), varp->widthWords()-1)); + new AstConst(varp->fileline(), varp->widthWords() - 1)); } uint64_t value = VL_MASK_Q(storedWidth) & ~VL_MASK_Q(lastWordWidth); newp = new AstAnd(varp->fileline(), newp, new AstConst(varp->fileline(), AstConst::WidthedValue(), storedWidth, value)); - AstNodeIf* ifp = new AstIf(varp->fileline(), newp, - new AstCStmt(varp->fileline(), - "Verilated::overWidthError(\""+varp->prettyName()+"\");")); + AstNodeIf* ifp = new AstIf( + varp->fileline(), newp, + new AstCStmt(varp->fileline(), "Verilated::overWidthError(\"" + + varp->prettyName() + "\");")); ifp->branchPred(VBranchPred::BP_UNLIKELY); newp = ifp; funcp->addStmtsp(newp); @@ -142,10 +140,10 @@ void V3CCtors::evalAsserts() { } void V3CCtors::cctorsAll() { - UINFO(2,__FUNCTION__<<": "<modulesp(); - modp; modp = VN_CAST(modp->nextp(), NodeModule)) { + for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; + modp = VN_CAST(modp->nextp(), NodeModule)) { // Process each module in turn AstCFunc* varResetFuncp; { @@ -158,8 +156,7 @@ void V3CCtors::cctorsAll() { for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) { if (AstVar* varp = VN_CAST(np, Var)) { - if (!varp->isIfaceParent() && !varp->isIfaceRef() - && !varp->noReset()) { + if (!varp->isIfaceParent() && !varp->isIfaceRef() && !varp->noReset()) { var_reset.add(new AstCReset(varp->fileline(), new AstVarRef(varp->fileline(), varp, true))); } @@ -168,10 +165,8 @@ void V3CCtors::cctorsAll() { } if (v3Global.opt.coverage()) { V3CCtorsVisitor configure_coverage( - modp, "_configure_coverage", - EmitCBaseVisitor::symClassVar() + ", bool first", - "vlSymsp, first", - "if (false && vlSymsp && first) {} // Prevent unused\n"); + modp, "_configure_coverage", EmitCBaseVisitor::symClassVar() + ", bool first", + "vlSymsp, first", "if (false && vlSymsp && first) {} // Prevent unused\n"); for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) { if (AstCoverDecl* coverp = VN_CAST(np, CoverDecl)) { AstNode* backp = coverp->backp(); diff --git a/src/V3Case.cpp b/src/V3Case.cpp index c81caf941..e125afcd7 100644 --- a/src/V3Case.cpp +++ b/src/V3Case.cpp @@ -45,9 +45,9 @@ #include #include -#define CASE_OVERLAP_WIDTH 16 // Maximum width we can check for overlaps in -#define CASE_BARF 999999 // Magic width when non-constant -#define CASE_ENCODER_GROUP_DEPTH 8 // Levels of priority to be ORed together in top IF tree +#define CASE_OVERLAP_WIDTH 16 // Maximum width we can check for overlaps in +#define CASE_BARF 999999 // Magic width when non-constant +#define CASE_ENCODER_GROUP_DEPTH 8 // Levels of priority to be ORed together in top IF tree //###################################################################### @@ -64,8 +64,8 @@ private: } // Detect multiple defaults bool hitDefault = false; - for (AstCaseItem* itemp = nodep->itemsp(); - itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; + itemp = VN_CAST(itemp->nextp(), CaseItem)) { if (itemp->isDefault()) { if (hitDefault) { itemp->v3error("Multiple default statements in case statement."); @@ -78,8 +78,8 @@ private: { m_caseExprp = nodep; iterate(nodep->exprp()); - for (AstCaseItem* itemp = nodep->itemsp(); - itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; + itemp = VN_CAST(itemp->nextp(), CaseItem)) { iterateAndNextNull(itemp->condsp()); } m_caseExprp = NULL; @@ -89,16 +89,20 @@ private: // See also neverItem if (m_caseExprp && nodep->num().isFourState()) { if (VN_IS(m_caseExprp, GenCase)) { - nodep->v3error("Use of x/? constant in generate case statement, (no such thing as 'generate casez')"); + nodep->v3error("Use of x/? constant in generate case statement, " + "(no such thing as 'generate casez')"); } else if (VN_IS(m_caseExprp, Case) && VN_CAST(m_caseExprp, Case)->casex()) { // Don't sweat it, we already complained about casex in general - } else if (VN_IS(m_caseExprp, Case) && (VN_CAST(m_caseExprp, Case)->casez() - || VN_CAST(m_caseExprp, Case)->caseInside())) { + } else if (VN_IS(m_caseExprp, Case) + && (VN_CAST(m_caseExprp, Case)->casez() + || VN_CAST(m_caseExprp, Case)->caseInside())) { if (nodep->num().isUnknown()) { - nodep->v3warn(CASEWITHX, "Use of x constant in casez statement, (perhaps intended ?/z in constant)"); + nodep->v3warn(CASEWITHX, "Use of x constant in casez statement, " + "(perhaps intended ?/z in constant)"); } } else { - nodep->v3warn(CASEWITHX, "Use of x/? constant in case statement, (perhaps intended casex/casez)"); + nodep->v3warn(CASEWITHX, "Use of x/? constant in case statement, " + "(perhaps intended casex/casez)"); } } } @@ -121,17 +125,18 @@ private: // NODE STATE // Cleared each Case // AstIf::user3() -> bool. Set true to indicate clone not needed - AstUser3InUse m_inuser3; + AstUser3InUse m_inuser3; // STATE VDouble0 m_statCaseFast; // Statistic tracking VDouble0 m_statCaseSlow; // Statistic tracking // Per-CASE - int m_caseWidth; // Width of valueItems - int m_caseItems; // Number of caseItem unique values - bool m_caseNoOverlapsAllCovered; // Proven to be synopsys parallel_case compliant - AstNode* m_valueItem[1<itemsp(); - itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { - for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; + itemp = VN_CAST(itemp->nextp(), CaseItem)) { + for (AstNode* icondp = itemp->condsp(); icondp; icondp = icondp->nextp()) { if (icondp->width() > width) width = icondp->width(); if (icondp->isDouble()) opaque = true; if (!VN_IS(icondp, Const)) width = CASE_BARF; // Can't parse; not a constant @@ -151,38 +156,39 @@ private: } } m_caseWidth = width; - if (width==0 || width > CASE_OVERLAP_WIDTH || opaque) { + if (width == 0 || width > CASE_OVERLAP_WIDTH || opaque) { m_caseNoOverlapsAllCovered = false; return false; // Too wide for analysis } - UINFO(8,"Simple case statement: "<itemsp(); - itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { - for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) { - //if (debug()>=9) icondp->dumpTree(cout, " caseitem: "); + for (AstCaseItem* itemp = nodep->itemsp(); itemp; + itemp = VN_CAST(itemp->nextp(), CaseItem)) { + for (AstNode* icondp = itemp->condsp(); icondp; icondp = icondp->nextp()) { + // if (debug() >= 9) icondp->dumpTree(cout, " caseitem: "); AstConst* iconstp = VN_CAST(icondp, Const); UASSERT_OBJ(iconstp, nodep, "above 'can't parse' should have caught this"); if (neverItem(nodep, iconstp)) { // X in casez can't ever be executed } else { - V3Number nummask (itemp, iconstp->width()); + V3Number nummask(itemp, iconstp->width()); nummask.opBitsNonX(iconstp->num()); uint32_t mask = nummask.toUInt(); - V3Number numval (itemp, iconstp->width()); + V3Number numval(itemp, iconstp->width()); numval.opBitsOne(iconstp->num()); - uint32_t val = numval.toUInt(); - for (uint32_t i=0; i<(1UL<ignoreOverlap() && !bitched) { - icondp->v3warn(CASEOVERLAP, "Case values overlap (example pattern 0x" - <v3warn(CASEOVERLAP, + "Case values overlap (example pattern 0x" + << std::hex << i << ")"); bitched = true; m_caseNoOverlapsAllCovered = false; } @@ -192,15 +198,16 @@ private: } // Defaults were moved to last in the caseitem list by V3LinkDot if (itemp->isDefault()) { // Case statement's default... Fill the table - for (uint32_t i=0; i<(1UL<v3warn(CASEINCOMPLETE, "Case values incompletely covered (example pattern 0x" - <v3warn(CASEINCOMPLETE, "Case values incompletely covered " + "(example pattern 0x" + << std::hex << i << ")"); m_caseNoOverlapsAllCovered = false; return false; } @@ -213,24 +220,23 @@ private: // Convert valueItem from AstCaseItem* to the expression // Not done earlier, as we may now have a NULL because it's just a ";" NOP branch - for (uint32_t i=0; i<(1UL<bodysp(); } return true; // All is fine } AstNode* replaceCaseFastRecurse(AstNode* cexprp, int msb, uint32_t upperValue) { - if (msb<0) { + if (msb < 0) { // There's no space for a IF. We know upperValue is thus down to a specific // exact value, so just return the tree value // Note can't clone here, as we're going to check for equivalence above return m_valueItem[upperValue]; - } - else { + } else { // Make left and right subtrees // cexpr[msb:lsb] == 1 - AstNode* tree0p = replaceCaseFastRecurse(cexprp, msb-1, upperValue | 0); - AstNode* tree1p = replaceCaseFastRecurse(cexprp, msb-1, upperValue | (1UL<deleteTree(), tree1p); @@ -256,14 +263,12 @@ private: if (tree1p && !tree1p->user3()) tree1p = tree1p->cloneTree(true); // Alternate scheme if we ever do multiple bits at a time: - //V3Number nummask (cexprp, cexprp->width(), (1UL<fileline(), cexprp->cloneTree(false), + // V3Number nummask (cexprp, cexprp->width(), (1UL<fileline(), cexprp->cloneTree(false), // new AstConst(cexprp->fileline(), nummask)); - AstNode* and1p = new AstSel(cexprp->fileline(), cexprp->cloneTree(false), - msb, 1); - AstNode* eqp = new AstNeq(cexprp->fileline(), - new AstConst(cexprp->fileline(), 0), - and1p); + AstNode* and1p = new AstSel(cexprp->fileline(), cexprp->cloneTree(false), msb, 1); + AstNode* eqp + = new AstNeq(cexprp->fileline(), new AstConst(cexprp->fileline(), 0), and1p); AstIf* ifp = new AstIf(cexprp->fileline(), eqp, tree1p, tree0p); ifp->user3(1); // So we don't bother to clone it return ifp; @@ -276,10 +281,10 @@ private: // IF(msb-1, 01, 00)) AstNode* cexprp = nodep->exprp()->unlinkFrBack(); - if (debug()>=9) { - for (uint32_t i=0; i<(1UL<= 9) { + for (uint32_t i = 0; i < (1UL << m_caseWidth); ++i) { if (AstNode* itemp = m_valueItem[i]) { - UINFO(9,"Value "<user3()) ifrootp = ifrootp->cloneTree(true); - if (ifrootp) nodep->replaceWith(ifrootp); - else nodep->unlinkFrBack(); + if (ifrootp) { + nodep->replaceWith(ifrootp); + } else { + nodep->unlinkFrBack(); + } VL_DO_DANGLING(nodep->deleteTree(), nodep); VL_DO_DANGLING(cexprp->deleteTree(), cexprp); - if (debug()>=9) ifrootp->dumpTree(cout, " _simp: "); + if (debug() >= 9) ifrootp->dumpTree(cout, " _simp: "); } void replaceCaseComplicated(AstCase* nodep) { @@ -307,9 +315,10 @@ private: AstNode* cexprp = nodep->exprp()->unlinkFrBack(); // We'll do this in two stages. First stage, convert the conditions to // the appropriate IF AND terms. - if (debug()>=9) nodep->dumpTree(cout, " _comp_IN: "); + if (debug() >= 9) nodep->dumpTree(cout, " _comp_IN: "); bool hadDefault = false; - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; + itemp = VN_CAST(itemp->nextp(), CaseItem)) { if (!itemp->condsp()) { // Default clause. Just make true, we'll optimize it away later itemp->condsp(new AstConst(itemp->fileline(), AstConst::LogicTrue())); @@ -318,7 +327,7 @@ private: // Expressioned clause AstNode* icondNextp = NULL; AstNode* ifexprp = NULL; // If expression to test - for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondNextp) { + for (AstNode* icondp = itemp->condsp(); icondp; icondp = icondNextp) { icondNextp = icondp->nextp(); icondp->unlinkFrBack(); @@ -326,7 +335,8 @@ private: AstConst* iconstp = VN_CAST(icondp, Const); if (iconstp && neverItem(nodep, iconstp)) { // X in casez can't ever be executed - VL_DO_DANGLING(icondp->deleteTree(), icondp); VL_DANGLING(iconstp); + VL_DO_DANGLING(icondp->deleteTree(), icondp); + VL_DANGLING(iconstp); // For simplicity, make expression that is not equal, and let later // optimizations remove it condp = new AstConst(itemp->fileline(), AstConst::LogicFalse()); @@ -336,16 +346,17 @@ private: irangep->rhsp()->unlinkFrBack()); } else if (iconstp && iconstp->num().isFourState() && (nodep->casex() || nodep->casez() || nodep->caseInside())) { - V3Number nummask (itemp, iconstp->width()); + V3Number nummask(itemp, iconstp->width()); nummask.opBitsNonX(iconstp->num()); - V3Number numval (itemp, iconstp->width()); + V3Number numval(itemp, iconstp->width()); numval.opBitsOne(iconstp->num()); AstNode* and1p = new AstAnd(itemp->fileline(), cexprp->cloneTree(false), new AstConst(itemp->fileline(), nummask)); AstNode* and2p = new AstAnd(itemp->fileline(), new AstConst(itemp->fileline(), numval), new AstConst(itemp->fileline(), nummask)); - VL_DO_DANGLING(icondp->deleteTree(), icondp); VL_DANGLING(iconstp); + VL_DO_DANGLING(icondp->deleteTree(), icondp); + VL_DANGLING(iconstp); condp = AstEq::newTyped(itemp->fileline(), and1p, and2p); } else { // Not a caseX mask, we can simply build CASEEQ(cexpr icond) @@ -367,11 +378,10 @@ private: if (!hadDefault) { // If there was no default, add a empty one, this greatly simplifies below code // and constant propagation will just eliminate it for us later. - nodep->addItemsp(new AstCaseItem(nodep->fileline(), - new AstConst(nodep->fileline(), AstConst::LogicTrue()), - NULL)); + nodep->addItemsp(new AstCaseItem( + nodep->fileline(), new AstConst(nodep->fileline(), AstConst::LogicTrue()), NULL)); } - if (debug()>=9) nodep->dumpTree(cout, " _comp_COND: "); + if (debug() >= 9) nodep->dumpTree(cout, " _comp_COND: "); // Now build the IF statement tree // The tree can be quite huge. Pull ever group of 8 out, and make a OR tree. // This reduces the depth for the bottom elements, at the cost of @@ -382,46 +392,56 @@ private: AstNode* grouprootp = NULL; AstIf* groupnextp = NULL; AstIf* itemnextp = NULL; - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; + itemp = VN_CAST(itemp->nextp(), CaseItem)) { AstNode* istmtsp = itemp->bodysp(); // Maybe null -- no action. if (istmtsp) istmtsp->unlinkFrBackWithNext(); // Expressioned clause AstNode* ifexprp = itemp->condsp()->unlinkFrBack(); - { // Prepare for next group + { // Prepare for next group if (++depth > CASE_ENCODER_GROUP_DEPTH) depth = 1; if (depth == 1) { // First group or starting new group itemnextp = NULL; - AstIf* newp = new AstIf(itemp->fileline(), - ifexprp->cloneTree(true), NULL, NULL); - if (groupnextp) groupnextp->addElsesp(newp); - else grouprootp = newp; + AstIf* newp + = new AstIf(itemp->fileline(), ifexprp->cloneTree(true), NULL, NULL); + if (groupnextp) { + groupnextp->addElsesp(newp); + } else { + grouprootp = newp; + } groupnextp = newp; } else { // Continue group, modify if condition to OR in this new condition AstNode* condp = groupnextp->condp()->unlinkFrBack(); - groupnextp->condp(new AstOr(ifexprp->fileline(), - condp, - ifexprp->cloneTree(true))); + groupnextp->condp( + new AstOr(ifexprp->fileline(), condp, ifexprp->cloneTree(true))); } } - { // Make the new lower IF and attach in the tree - AstNode* itemexprp = ifexprp; VL_DANGLING(ifexprp); - if (depth == (CASE_ENCODER_GROUP_DEPTH)) { // End of group - can skip the condition + { // Make the new lower IF and attach in the tree + AstNode* itemexprp = ifexprp; + VL_DANGLING(ifexprp); + if (depth == CASE_ENCODER_GROUP_DEPTH) { // End of group - can skip the condition VL_DO_DANGLING(itemexprp->deleteTree(), itemexprp); itemexprp = new AstConst(itemp->fileline(), AstConst::LogicTrue()); } AstIf* newp = new AstIf(itemp->fileline(), itemexprp, istmtsp, NULL); - if (itemnextp) itemnextp->addElsesp(newp); - else groupnextp->addIfsp(newp); // First in a new group + if (itemnextp) { + itemnextp->addElsesp(newp); + } else { + groupnextp->addIfsp(newp); // First in a new group + } itemnextp = newp; } } - if (debug()>=9) nodep->dumpTree(cout, " _comp_TREE: "); + if (debug() >= 9) nodep->dumpTree(cout, " _comp_TREE: "); // Handle any assertions replaceCaseParallel(nodep, false); // Replace the CASE... with IF... - if (debug()>=9 && grouprootp) grouprootp->dumpTree(cout, " _new: "); - if (grouprootp) nodep->replaceWith(grouprootp); - else nodep->unlinkFrBack(); + if (debug() >= 9 && grouprootp) grouprootp->dumpTree(cout, " _new: "); + if (grouprootp) { + nodep->replaceWith(grouprootp); + } else { + nodep->unlinkFrBack(); + } VL_DO_DANGLING(nodep->deleteTree(), nodep); } @@ -451,7 +471,7 @@ private: virtual void visit(AstCase* nodep) VL_OVERRIDE { V3Case::caseLint(nodep); iterateChildren(nodep); - if (debug()>=9) nodep->dumpTree(cout, " case_old: "); + if (debug() >= 9) nodep->dumpTree(cout, " case_old: "); if (isCaseTreeFast(nodep) && v3Global.opt.oCase()) { // It's a simple priority encoder or complete statement // we can make a tree of statements to avoid extra comparisons @@ -471,9 +491,7 @@ public: m_caseWidth = 0; m_caseItems = 0; m_caseNoOverlapsAllCovered = false; - for (uint32_t i=0; i<(1UL<= 3); } void V3Case::caseLint(AstNodeCase* nodep) { - UINFO(4,__FUNCTION__<<": "<unlinkFrBack(&relinkHandle); // AstCCast* castp = new AstCCast(nodep->fileline(), nodep, needsize, nodep->widthMin()); relinkHandle.relink(castp); - //if (debug()>8) castp->dumpTree(cout, "-castins: "); + // if (debug() > 8) castp->dumpTree(cout, "-castins: "); // ensureLower32Cast(castp); nodep->user1(1); // Now must be of known size } int castSize(AstNode* nodep) { - if (nodep->isQuad()) return VL_QUADSIZE; - else if (nodep->width() <= 8) return 8; - else if (nodep->width() <= 16) return 16; - else return VL_IDATASIZE; + if (nodep->isQuad()) { + return VL_QUADSIZE; + } else if (nodep->width() <= 8) { + return 8; + } else if (nodep->width() <= 16) { + return 16; + } else { + return VL_IDATASIZE; + } } void ensureCast(AstNode* nodep) { - if (castSize(nodep->backp()) != castSize(nodep) - || !nodep->user1()) { + if (castSize(nodep->backp()) != castSize(nodep) || !nodep->user1()) { insertCast(nodep, castSize(nodep->backp())); } } @@ -91,8 +95,7 @@ private: // really needs to be CAST(uint64(CAST(uint32(x))). // Otherwise a (uint64)(a>b) would return wrong value, as // less than has nondeterministic signedness. - if (nodep->isQuad() && !nodep->lhsp()->isQuad() - && !VN_IS(nodep->lhsp(), CCast)) { + if (nodep->isQuad() && !nodep->lhsp()->isQuad() && !VN_IS(nodep->lhsp(), CCast)) { insertCast(nodep->lhsp(), VL_IDATASIZE); } } @@ -114,16 +117,13 @@ private: } virtual void visit(AstNodeBiop* nodep) VL_OVERRIDE { iterateChildren(nodep); - nodep->user1(nodep->lhsp()->user1() - | nodep->rhsp()->user1()); + nodep->user1(nodep->lhsp()->user1() | nodep->rhsp()->user1()); if (nodep->sizeMattersLhs()) ensureCast(nodep->lhsp()); if (nodep->sizeMattersRhs()) ensureCast(nodep->rhsp()); } virtual void visit(AstNodeTriop* nodep) VL_OVERRIDE { iterateChildren(nodep); - nodep->user1(nodep->lhsp()->user1() - | nodep->rhsp()->user1() - | nodep->thsp()->user1()); + nodep->user1(nodep->lhsp()->user1() | nodep->rhsp()->user1() | nodep->thsp()->user1()); if (nodep->sizeMattersLhs()) ensureCast(nodep->lhsp()); if (nodep->sizeMattersRhs()) ensureCast(nodep->rhsp()); if (nodep->sizeMattersThs()) ensureCast(nodep->thsp()); @@ -136,7 +136,7 @@ private: virtual void visit(AstNegate* nodep) VL_OVERRIDE { iterateChildren(nodep); nodep->user1(nodep->lhsp()->user1()); - if (nodep->lhsp()->widthMin()==1) { + if (nodep->lhsp()->widthMin() == 1) { // We want to avoid a GCC "converting of negative value" warning // from our expansion of // out = {32{a out = - (alvalue() - && !VN_IS(nodep->backp(), CCast) - && VN_IS(nodep->backp(), NodeMath) - && !VN_IS(nodep->backp(), ArraySel) - && nodep->backp()->width() + if (!nodep->lvalue() && !VN_IS(nodep->backp(), CCast) && VN_IS(nodep->backp(), NodeMath) + && !VN_IS(nodep->backp(), ArraySel) && nodep->backp()->width() && castSize(nodep) != castSize(nodep->varp())) { // Cast vars to IData first, else below has upper bits wrongly set // CData x=3; out = (QData)(x<<30); @@ -187,9 +184,7 @@ private: public: // CONSTRUCTORS - explicit CastVisitor(AstNetlist* nodep) { - iterate(nodep); - } + explicit CastVisitor(AstNetlist* nodep) { iterate(nodep); } virtual ~CastVisitor() {} }; @@ -197,9 +192,7 @@ public: // Cast class functions void V3Cast::castAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Cdc.cpp b/src/V3Cdc.cpp index 0fc002f27..358160c49 100644 --- a/src/V3Cdc.cpp +++ b/src/V3Cdc.cpp @@ -40,7 +40,7 @@ #include #include -#define CDC_WEIGHT_ASYNC 0x1000 // Weight for edges that feed async logic +#define CDC_WEIGHT_ASYNC 0x1000 // Weight for edges that feed async logic //###################################################################### @@ -53,18 +53,23 @@ public: // Graph support classes class CdcEitherVertex : public V3GraphVertex { - AstScope* m_scopep; - AstNode* m_nodep; + AstScope* m_scopep; + AstNode* m_nodep; AstSenTree* m_srcDomainp; AstSenTree* m_dstDomainp; - bool m_srcDomainSet:1; - bool m_dstDomainSet:1; - bool m_asyncPath:1; + bool m_srcDomainSet : 1; + bool m_dstDomainSet : 1; + bool m_asyncPath : 1; + public: CdcEitherVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep) - : V3GraphVertex(graphp), m_scopep(scopep), m_nodep(nodep) - , m_srcDomainp(NULL), m_dstDomainp(NULL) - , m_srcDomainSet(false), m_dstDomainSet(false) + : V3GraphVertex(graphp) + , m_scopep(scopep) + , m_nodep(nodep) + , m_srcDomainp(NULL) + , m_dstDomainp(NULL) + , m_srcDomainSet(false) + , m_dstDomainSet(false) , m_asyncPath(false) {} virtual ~CdcEitherVertex() {} // ACCESSORS @@ -85,18 +90,22 @@ public: class CdcVarVertex : public CdcEitherVertex { AstVarScope* m_varScp; - int m_cntAsyncRst; - bool m_fromFlop; + int m_cntAsyncRst; + bool m_fromFlop; + public: CdcVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) : CdcEitherVertex(graphp, scopep, varScp) - , m_varScp(varScp), m_cntAsyncRst(0), m_fromFlop(false) {} + , m_varScp(varScp) + , m_cntAsyncRst(0) + , m_fromFlop(false) {} virtual ~CdcVarVertex() {} // ACCESSORS AstVarScope* varScp() const { return m_varScp; } - virtual string name() const { return (cvtToHex(m_varScp)+" "+varScp()->name()); } + virtual string name() const { return (cvtToHex(m_varScp) + " " + varScp()->name()); } virtual string dotColor() const { - return fromFlop() ? "green" : cntAsyncRst() ? "red" : "blue"; } + return fromFlop() ? "green" : cntAsyncRst() ? "red" : "blue"; + } int cntAsyncRst() const { return m_cntAsyncRst; } void cntAsyncRst(int flag) { m_cntAsyncRst = flag; } bool fromFlop() const { return m_fromFlop; } @@ -104,19 +113,26 @@ public: }; class CdcLogicVertex : public CdcEitherVertex { - bool m_hazard:1; - bool m_isFlop:1; + bool m_hazard : 1; + bool m_isFlop : 1; + public: CdcLogicVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep, AstSenTree* sensenodep) : CdcEitherVertex(graphp, scopep, nodep) - , m_hazard(false), m_isFlop(false) - { srcDomainp(sensenodep); dstDomainp(sensenodep); } + , m_hazard(false) + , m_isFlop(false) { + srcDomainp(sensenodep); + dstDomainp(sensenodep); + } virtual ~CdcLogicVertex() {} // ACCESSORS - virtual string name() const { return (cvtToHex(nodep())+"@"+scopep()->prettyName()); } + virtual string name() const { return (cvtToHex(nodep()) + "@" + scopep()->prettyName()); } virtual string dotColor() const { return hazard() ? "black" : "yellow"; } bool hazard() const { return m_hazard; } - void setHazard(AstNode* nodep) { m_hazard = true; nodep->user3(true); } + void setHazard(AstNode* nodep) { + m_hazard = true; + nodep->user3(true); + } void clearHazard() { m_hazard = false; } bool isFlop() const { return m_isFlop; } void isFlop(bool flag) { m_isFlop = flag; } @@ -127,16 +143,19 @@ public: class CdcDumpVisitor : public CdcBaseVisitor { private: // NODE STATE - //Entire netlist: + // Entire netlist: // {statement}Node::user3 -> bool, indicating not hazard std::ofstream* m_ofp; // Output file - string m_prefix; + string m_prefix; virtual void visit(AstNode* nodep) VL_OVERRIDE { - *m_ofp<user3()) *m_ofp<<" %%"; - else *m_ofp<<" "; - *m_ofp<prettyTypeName()<<" "<user3()) { + *m_ofp << " %%"; + } else { + *m_ofp << " "; + } + *m_ofp << nodep->prettyTypeName() << " " << endl; string lastPrefix = m_prefix; m_prefix = lastPrefix + "1:"; iterateAndNextNull(nodep->op1p()); @@ -163,19 +182,20 @@ public: class CdcWidthVisitor : public CdcBaseVisitor { private: - int m_maxLineno; - size_t m_maxFilenameLen; + int m_maxLineno; + size_t m_maxFilenameLen; virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); // Keeping line+filename lengths separate is much faster than calling ascii().length() if (nodep->fileline()->lineno() >= m_maxLineno) { - m_maxLineno = nodep->fileline()->lineno()+1; + m_maxLineno = nodep->fileline()->lineno() + 1; } if (nodep->fileline()->filename().length() >= m_maxFilenameLen) { - m_maxFilenameLen = nodep->fileline()->filename().length()+1; + m_maxFilenameLen = nodep->fileline()->filename().length() + 1; } } + public: // CONSTRUCTORS explicit CdcWidthVisitor(AstNode* nodep) { @@ -201,32 +221,32 @@ public: class CdcVisitor : public CdcBaseVisitor { private: // NODE STATE - //Entire netlist: + // Entire netlist: // AstVarScope::user1p -> CdcVarVertex* for usage var, 0=not set yet // AstVarScope::user2 -> bool Used in sensitivity list // {statement}Node::user1p -> CdcLogicVertex* for this statement // AstNode::user3 -> bool True indicates to print %% (via V3EmitV) - AstUser1InUse m_inuser1; - AstUser2InUse m_inuser2; - AstUser3InUse m_inuser3; + AstUser1InUse m_inuser1; + AstUser2InUse m_inuser2; + AstUser3InUse m_inuser3; // STATE - V3Graph m_graph; // Scoreboard of var usages/dependencies - CdcLogicVertex* m_logicVertexp; // Current statement being tracked, NULL=ignored - AstScope* m_scopep; // Current scope being processed - AstNodeModule* m_modp; // Current module - AstSenTree* m_domainp; // Current sentree - bool m_inDly; // In delayed assign - int m_inSenItem; // Number of senitems - string m_ofFilename; // Output filename - std::ofstream* m_ofp; // Output file - uint32_t m_userGeneration; // Generation count to avoid slow userClearVertices - int m_filelineWidth; // Characters in longest fileline + V3Graph m_graph; // Scoreboard of var usages/dependencies + CdcLogicVertex* m_logicVertexp; // Current statement being tracked, NULL=ignored + AstScope* m_scopep; // Current scope being processed + AstNodeModule* m_modp; // Current module + AstSenTree* m_domainp; // Current sentree + bool m_inDly; // In delayed assign + int m_inSenItem; // Number of senitems + string m_ofFilename; // Output filename + std::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) { if (m_scopep) { - UINFO(4," STMT "<hasClocked()) { // To/from a flop m_logicVertexp->isFlop(true); @@ -238,7 +258,7 @@ private: iterateChildren(nodep); m_logicVertexp = NULL; - if (0 && debug()>=9) { + if (0 && debug() >= 9) { UINFO(9, "Trace Logic:\n"); nodep->dumpTree(cout, "-log1: "); } @@ -248,15 +268,15 @@ private: CdcVarVertex* makeVarVertex(AstVarScope* varscp) { CdcVarVertex* vertexp = reinterpret_cast(varscp->user1p()); if (!vertexp) { - UINFO(6,"New vertex "<user1p(vertexp); if (varscp->varp()->isUsedClock()) {} if (varscp->varp()->isPrimaryIO()) { - // Create IO vertex - note it's relative to the pointed to var, not where we are now - // This allows reporting to easily print the input statement - CdcLogicVertex* ioVertexp = new CdcLogicVertex(&m_graph, varscp->scopep(), - varscp->varp(), NULL); + // Create IO vertex - note it's relative to the pointed to var, not where we are + // now This allows reporting to easily print the input statement + CdcLogicVertex* ioVertexp + = new CdcLogicVertex(&m_graph, varscp->scopep(), varscp->varp(), NULL); if (varscp->varp()->isWritable()) { new V3GraphEdge(&m_graph, vertexp, ioVertexp, 1); } else { @@ -266,10 +286,10 @@ private: } if (m_inSenItem) { varscp->user2(true); // It's like a clock... - // TODO: In the future we could mark it here and do normal clock tree glitch checks also + // TODO: In the future mark it here and do normal clock tree glitch checks also } else if (varscp->user2()) { // It was detected in a sensitivity list earlier // And now it's used as logic. So must be a reset. - vertexp->cntAsyncRst(vertexp->cntAsyncRst()+1); + vertexp->cntAsyncRst(vertexp->cntAsyncRst() + 1); } return vertexp; } @@ -279,9 +299,9 @@ private: nodep->v3warnCode(code, msg); if (!told_file) { told_file = 1; - std::cerr<fileline()<<" "<fileline() << " " << msg << endl; } void setNodeHazard(AstNode* nodep) { @@ -291,28 +311,34 @@ private: // an issue until we find a hitting flop. // Furthermore, a module like a "Or" module would only get flagged // once, even though the signals feeding it are radically different. - if (!m_domainp || m_domainp->hasCombo()) { // Source flop logic in a posedge block is OK for reset (not async though) + if (!m_domainp || m_domainp->hasCombo()) { + // Source flop logic in a posedge block is OK for reset (not async though) if (m_logicVertexp && !nodep->fileline()->warnIsOff(V3ErrorCode::CDCRSTLOGIC)) { - UINFO(8,"Set hazard "<setHazard(nodep); } } } - string spaces(int level) { string out; while (level--) out += " "; return out; } // LCOV_EXCL_LINE + string spaces(int level) { + string out; + while (level--) out += " "; + return out; + } // LCOV_EXCL_LINE string pad(unsigned column, const string& in) { string out = in; - while (out.length()6) m_graph.dump(); - if (debug()>6) m_graph.dumpDotFilePrefixed("cdc_pre"); + UINFO(3, __FUNCTION__ << ": " << endl); + // if (debug() > 6) m_graph.dump(); + if (debug() > 6) m_graph.dumpDotFilePrefixed("cdc_pre"); // - m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue); // This will MAX across edge weights + m_graph.removeRedundantEdges( + &V3GraphEdge::followAlwaysTrue); // This will MAX across edge weights // m_graph.dumpDotFilePrefixed("cdc_simp"); // @@ -321,7 +347,7 @@ private: int filelineWidth() { if (!m_filelineWidth) { - CdcWidthVisitor visitor (v3Global.rootp()); + CdcWidthVisitor visitor(v3Global.rootp()); m_filelineWidth = visitor.maxWidth(); } return m_filelineWidth; @@ -334,15 +360,15 @@ private: // Find all async reset wires, and trace backwards // userClearVertices is very slow, so we use a generation count instead m_graph.userClearVertices(); // user1: uint32_t - was analyzed generation - for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) { + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { if (CdcVarVertex* vvertexp = dynamic_cast(itp)) { if (vvertexp->cntAsyncRst()) { m_userGeneration++; // Effectively a userClearVertices() - UINFO(8, " Trace One async: "<user()>=m_userGeneration) return NULL; // Processed - prevent loop + if (vertexp->user() >= m_userGeneration) return NULL; // Processed - prevent loop vertexp->user(m_userGeneration); CdcEitherVertex* mark_outp = NULL; - UINFO(9," Trace: "<asyncPath(false); @@ -369,8 +395,7 @@ private: // Any logic considered bad, at the moment, anyhow if (vvertexp->hazard() && !mark_outp) mark_outp = vvertexp; // And keep tracing back so the user can understand what's up - } - else if (CdcVarVertex* vvertexp = dynamic_cast(vertexp)) { + } else if (CdcVarVertex* vvertexp = dynamic_cast(vertexp)) { if (mark) vvertexp->asyncPath(true); // If primary I/O, it's ok here back if (vvertexp->varScp()->varp()->isPrimaryInish()) { @@ -403,62 +428,60 @@ private: void dumpAsync(CdcVarVertex* vertexp, CdcEitherVertex* markp) { AstNode* nodep = vertexp->varScp(); - *m_ofp<<"\n"; - *m_ofp<<"\n"; + *m_ofp << "\n"; + *m_ofp << "\n"; CdcEitherVertex* targetp = vertexp; // One example destination flop (of possibly many) for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { CdcEitherVertex* eToVertexp = static_cast(edgep->top()); if (!eToVertexp) targetp = eToVertexp; if (CdcLogicVertex* vvertexp = dynamic_cast(eToVertexp)) { if (vvertexp->isFlop() // IE the target flop that is upsetting us - && edgep->weight() >= CDC_WEIGHT_ASYNC) { // And this signal feeds an async reset line + && edgep->weight() >= CDC_WEIGHT_ASYNC) { // And var feeds an async reset line targetp = eToVertexp; - //UINFO(9," targetasync "<name()<<" "<<" from "<name()<name()<<" "<<" from + // "<name()<name()<<" "<nodep()->fileline()<name()<<" "<nodep()->fileline()<nodep(), V3ErrorCode::CDCRSTLOGIC, - "Logic in path that feeds async reset, via signal: "+nodep->prettyNameQ()); + "Logic in path that feeds async reset, via signal: " + nodep->prettyNameQ()); dumpAsyncRecurse(targetp, "", " ", 0); } - bool dumpAsyncRecurse(CdcEitherVertex* vertexp, const string& prefix, - const string& sep, int level) { + bool dumpAsyncRecurse(CdcEitherVertex* vertexp, const string& prefix, const string& sep, + int level) { // level=0 is special, indicates to dump destination flop // Return true if printed anything // If mark, also mark the output even if nothing hazardous below - if (vertexp->user()>=m_userGeneration) return false; // Processed - prevent loop + if (vertexp->user() >= m_userGeneration) return false; // Processed - prevent loop vertexp->user(m_userGeneration); - if (!vertexp->asyncPath() && level!=0) return false; // Not part of path + if (!vertexp->asyncPath() && level != 0) return false; // Not part of path // Other logic in the path - string cont = prefix+sep; + string cont = prefix + sep; string nextsep = " "; for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { CdcEitherVertex* eFromVertexp = static_cast(edgep->fromp()); - if (dumpAsyncRecurse(eFromVertexp, cont, nextsep, level+1)) { - nextsep = " | "; - } + if (dumpAsyncRecurse(eFromVertexp, cont, nextsep, level + 1)) nextsep = " | "; } // Dump single variable/logic block // See also OrderGraph::loopsVertexCb(V3GraphVertex* vertexp) AstNode* nodep = vertexp->nodep(); - string front = pad(filelineWidth(), nodep->fileline()->ascii()+":")+" "+prefix+" +- "; + string front + = pad(filelineWidth(), nodep->fileline()->ascii() + ":") + " " + prefix + " +- "; if (VN_IS(nodep, VarScope)) { - *m_ofp<prettyName()<prettyName() << endl; + } else { + V3EmitV::verilogPrefixedTree(nodep, *m_ofp, prefix + " +- ", filelineWidth(), vertexp->srcDomainp(), true); - if (debug()) { - CdcDumpVisitor visitor (nodep, m_ofp, front+"DBG: "); - } + if (debug()) { CdcDumpVisitor visitor(nodep, m_ofp, front + "DBG: "); } } nextsep = " | "; - if (level) *m_ofp<(vertexp)) { // Now that we've printed a path with this hazard, don't bother to print any more @@ -479,27 +502,27 @@ private: // module. Disabling flattening though makes us consider each // signal in it's own unique clock domain. - UINFO(3,__FUNCTION__<<": "<verticesNextp()) { + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { if (CdcVarVertex* vvertexp = dynamic_cast(itp)) { - UINFO(9, " Trace One edge: "< ofp (V3File::new_ofstream(filename)); - if (ofp->fail()) v3fatal("Can't write "< ofp(V3File::new_ofstream(filename)); + if (ofp->fail()) v3fatal("Can't write " << filename); + *ofp << "Edge Report for " << v3Global.opt.prefix() << endl; std::deque report; // Sort output by name - for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) { + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { if (CdcVarVertex* vvertexp = dynamic_cast(itp)) { AstVar* varp = vvertexp->varScp()->varp(); { @@ -511,46 +534,50 @@ private: // Module name - doesn't work due to flattening having lost the original // so we assume the modulename matches the filebasename string fname = vvertexp->varScp()->fileline()->filebasename() + ":"; - os<<" "<varScp()->prettyName(); - os<<" SRC="; - if (vvertexp->srcDomainp()) V3EmitV::verilogForTree(vvertexp->srcDomainp(), os); - os<<" DST="; - if (vvertexp->dstDomainp()) V3EmitV::verilogForTree(vvertexp->dstDomainp(), os); - os<varScp()->prettyName(); + os << " SRC="; + if (vvertexp->srcDomainp()) { + V3EmitV::verilogForTree(vvertexp->srcDomainp(), os); + } + os << " DST="; + if (vvertexp->dstDomainp()) { + V3EmitV::verilogForTree(vvertexp->dstDomainp(), os); + } + os << std::setw(0); + os << endl; report.push_back(os.str()); } } } stable_sort(report.begin(), report.end()); - for (std::deque::iterator it = report.begin(); it!=report.end(); ++it) { + for (std::deque::iterator it = report.begin(); it != report.end(); ++it) { *ofp << *it; } } void edgeDomainRecurse(CdcEitherVertex* vertexp, bool traceDests, int level) { // Scan back to inputs/outputs, flops, and compute clock domain information - UINFO(8,spaces(level)<<" Tracein "<user()>=m_userGeneration) return; // Mid-Processed - prevent loop + UINFO(8, spaces(level) << " Tracein " << vertexp << endl); + if (vertexp->user() >= m_userGeneration) return; // Mid-Processed - prevent loop vertexp->user(m_userGeneration); // Variables from flops already are domained - if (traceDests ? vertexp->dstDomainSet() : vertexp->srcDomainSet()) return; // Fully computed + if (traceDests ? vertexp->dstDomainSet() : vertexp->srcDomainSet()) { + return; + } // Fully computed typedef std::set SenSet; SenSet senouts; // List of all sensitivities for new signal if (CdcLogicVertex* vvertexp = dynamic_cast(vertexp)) { if (vvertexp) {} // Unused - } - else if (CdcVarVertex* vvertexp = dynamic_cast(vertexp)) { + } else if (CdcVarVertex* vvertexp = dynamic_cast(vertexp)) { // If primary I/O, give it domain of the input AstVar* varp = vvertexp->varScp()->varp(); if (varp->isPrimaryIO() && varp->isNonOutput() && !traceDests) { - senouts.insert( - new AstSenTree(varp->fileline(), - new AstSenItem(varp->fileline(), AstSenItem::Combo()))); + senouts.insert(new AstSenTree( + varp->fileline(), new AstSenItem(varp->fileline(), AstSenItem::Combo()))); } } @@ -558,23 +585,24 @@ private: if (traceDests) { for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { CdcEitherVertex* eToVertexp = static_cast(edgep->top()); - edgeDomainRecurse(eToVertexp, traceDests, level+1); + edgeDomainRecurse(eToVertexp, traceDests, level + 1); if (eToVertexp->dstDomainp()) senouts.insert(eToVertexp->dstDomainp()); } } else { for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { CdcEitherVertex* eFromVertexp = static_cast(edgep->fromp()); - edgeDomainRecurse(eFromVertexp, traceDests, level+1); + edgeDomainRecurse(eFromVertexp, traceDests, level + 1); if (eFromVertexp->srcDomainp()) senouts.insert(eFromVertexp->srcDomainp()); } } // Convert list of senses into one sense node AstSenTree* senoutp = NULL; - bool senedited = false; - for (SenSet::iterator it=senouts.begin(); it!=senouts.end(); ++it) { - if (!senoutp) senoutp = *it; - else { + bool senedited = false; + for (SenSet::iterator it = senouts.begin(); it != senouts.end(); ++it) { + if (!senoutp) { + senoutp = *it; + } else { if (!senedited) { senedited = true; senoutp = senoutp->cloneTree(true); @@ -583,22 +611,26 @@ private: } } // If multiple domains need to do complicated optimizations - if (senedited) { - senoutp = VN_CAST(V3Const::constifyExpensiveEdit(senoutp), SenTree); - } + if (senedited) { senoutp = VN_CAST(V3Const::constifyExpensiveEdit(senoutp), SenTree); } if (traceDests) { vertexp->dstDomainSet(true); // Note it's set - domainp may be null, so can't use that vertexp->dstDomainp(senoutp); - if (debug()>=9) { - UINFO(9,spaces(level)+" Tracedst "<= 9) { + UINFO(9, spaces(level) + " Tracedst " << vertexp); + if (senoutp) { + V3EmitV::verilogForTree(senoutp, cout); + cout << endl; + } } } else { vertexp->srcDomainSet(true); // Note it's set - domainp may be null, so can't use that vertexp->srcDomainp(senoutp); - if (debug()>=9) { - UINFO(9,spaces(level)+" Tracesrc "<= 9) { + UINFO(9, spaces(level) + " Tracesrc " << vertexp); + if (senoutp) { + V3EmitV::verilogForTree(senoutp, cout); + cout << endl; + } } } } @@ -613,7 +645,7 @@ private: m_modp = origModp; } virtual void visit(AstScope* nodep) VL_OVERRIDE { - UINFO(4," SCOPE "<sensesp(); - if (!m_domainp || m_domainp->hasCombo() || m_domainp->hasClocked()) { // IE not hasSettle/hasInitial + if (!m_domainp || m_domainp->hasCombo() + || m_domainp->hasClocked()) { // IE not hasSettle/hasInitial iterateNewStmt(nodep); } m_domainp = NULL; @@ -636,7 +669,7 @@ private: AstVarScope* varscp = nodep->varScopep(); UASSERT_OBJ(varscp, nodep, "Var didn't get varscoped in V3Scope.cpp"); CdcVarVertex* varvertexp = makeVarVertex(varscp); - UINFO(5," VARREF to "<cntAsyncRst()) { - //UINFO(9," edgeasync "<name()<<" to "<name()<<" to "<name()<<" to "<name()<<" to "<lsbp(), Const)) setNodeHazard(nodep); iterateChildren(nodep); @@ -738,15 +757,16 @@ public: m_filelineWidth = 0; // Make report of all signal names and what clock edges they have - string filename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__cdc.txt"; + string filename = v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "__cdc.txt"; m_ofp = V3File::new_ofstream(filename); - if (m_ofp->fail()) v3fatal("Can't write "<fail()) v3fatal("Can't write " << filename); m_ofFilename = filename; - *m_ofp<<"CDC Report for "<fileline(), - "_change_request_" + cvtToStr(++m_funcNum), - m_scopetopp, "QData"); + m_chgFuncp + = new AstCFunc(m_scopetopp->fileline(), "_change_request_" + cvtToStr(++m_funcNum), + m_scopetopp, "QData"); m_chgFuncp->argTypes(EmitCBaseVisitor::symClassVar()); m_chgFuncp->symProlog(true); m_chgFuncp->declPrivate(true); @@ -89,9 +89,9 @@ public: // we want and is similar to the logic already in use inside // V3EmitC, however, it also means that verbose logging may // miss to print change detect variables. - AstNode* newp = new AstCReturn(m_scopetopp->fileline(), - new AstLogOr(m_scopetopp->fileline(), callp, - returnp->lhsp()->unlinkFrBack())); + AstNode* newp = new AstCReturn( + m_scopetopp->fileline(), + new AstLogOr(m_scopetopp->fileline(), callp, returnp->lhsp()->unlinkFrBack())); returnp->replaceWith(newp); VL_DO_DANGLING(returnp->deleteTree(), returnp); } @@ -106,57 +106,57 @@ public: class ChangedInsertVisitor : public AstNVisitor { private: // STATE - ChangedState* m_statep; // Shared state across visitors - AstVarScope* m_vscp; // Original (non-change) variable we're change-detecting - AstVarScope* m_newvscp; // New (change detect) variable we're change-detecting - AstNode* m_varEqnp; // Original var's equation to get var value - AstNode* m_newLvEqnp; // New var's equation to read value - AstNode* m_newRvEqnp; // New var's equation to set value - uint32_t m_detects; // # detects created + ChangedState* m_statep; // Shared state across visitors + AstVarScope* m_vscp; // Original (non-change) variable we're change-detecting + AstVarScope* m_newvscp; // New (change detect) variable we're change-detecting + AstNode* m_varEqnp; // Original var's equation to get var value + AstNode* m_newLvEqnp; // New var's equation to read value + AstNode* m_newRvEqnp; // New var's equation to set value + uint32_t m_detects; // # detects created // CONSTANTS enum MiscConsts { - DETECTARRAY_MAX_INDEXES = 256 // How many indexes before error + DETECTARRAY_MAX_INDEXES = 256 // How many indexes before error // Ok to increase this, but may result in much slower model }; void newChangeDet() { if (++m_detects > DETECTARRAY_MAX_INDEXES) { - m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect more than " - <prettyName()<warnMore() - <<"... Could recompile with DETECTARRAY_MAX_INDEXES increased"<v3warn(E_DETECTARRAY, + "Unsupported: Can't detect more than " + << cvtToStr(DETECTARRAY_MAX_INDEXES) + << " array indexes (probably with UNOPTFLAT warning suppressed): " + << m_vscp->prettyName() << endl + << m_vscp->warnMore() + << "... Could recompile with DETECTARRAY_MAX_INDEXES increased" + << endl); return; } m_statep->maybeCreateChgFuncp(); - AstChangeDet* changep = new AstChangeDet(m_vscp->fileline(), - m_varEqnp->cloneTree(true), + AstChangeDet* changep = new AstChangeDet(m_vscp->fileline(), m_varEqnp->cloneTree(true), m_newRvEqnp->cloneTree(true), false); m_statep->m_chgFuncp->addStmtsp(changep); - AstAssign* initp = new AstAssign(m_vscp->fileline(), - m_newLvEqnp->cloneTree(true), + AstAssign* initp = new AstAssign(m_vscp->fileline(), m_newLvEqnp->cloneTree(true), m_varEqnp->cloneTree(true)); m_statep->m_chgFuncp->addFinalsp(initp); EmitCBaseCounterVisitor visitor(initp); m_statep->m_numStmts += visitor.count(); } - virtual void visit(AstBasicDType* nodep) VL_OVERRIDE { + virtual void visit(AstBasicDType* nodep) VL_OVERRIDE { // newChangeDet(); } - virtual void visit(AstPackArrayDType* nodep) VL_OVERRIDE { + virtual void visit(AstPackArrayDType* nodep) VL_OVERRIDE { // newChangeDet(); } virtual void visit(AstUnpackArrayDType* nodep) VL_OVERRIDE { - for (int index=0; index < nodep->elementsConst(); ++index) { + for (int index = 0; index < nodep->elementsConst(); ++index) { AstNode* origVEp = m_varEqnp; AstNode* origNLEp = m_newLvEqnp; AstNode* origNREp = m_newRvEqnp; - m_varEqnp = new AstArraySel(nodep->fileline(), m_varEqnp->cloneTree(true), index); + m_varEqnp = new AstArraySel(nodep->fileline(), m_varEqnp->cloneTree(true), index); m_newLvEqnp = new AstArraySel(nodep->fileline(), m_newLvEqnp->cloneTree(true), index); m_newRvEqnp = new AstArraySel(nodep->fileline(), m_newRvEqnp->cloneTree(true), index); @@ -166,7 +166,7 @@ private: m_newLvEqnp->deleteTree(); m_newRvEqnp->deleteTree(); - m_varEqnp = origVEp; + m_varEqnp = origVEp; m_newLvEqnp = origNLEp; m_newRvEqnp = origNREp; } @@ -177,17 +177,18 @@ private: } else { if (debug()) nodep->dumpTree(cout, "-DETECTARRAY-class-"); m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable" - " (probably with UNOPTFLAT warning suppressed): " - <varp()->prettyNameQ()); + " (probably with UNOPTFLAT warning suppressed): " + << m_vscp->varp()->prettyNameQ()); } } virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); if (debug()) nodep->dumpTree(cout, "-DETECTARRAY-general-"); m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable" - " (probably with UNOPTFLAT warning suppressed): " - <varp()->prettyNameQ()); + " (probably with UNOPTFLAT warning suppressed): " + << m_vscp->varp()->prettyNameQ()); } + public: // CONSTRUCTORS ChangedInsertVisitor(AstVarScope* vscp, ChangedState* statep) { @@ -196,19 +197,19 @@ public: m_detects = 0; { AstVar* varp = m_vscp->varp(); - string newvarname = ("__Vchglast__"+m_vscp->scopep()->nameDotless() - +"__"+varp->shortName()); + string newvarname + = ("__Vchglast__" + m_vscp->scopep()->nameDotless() + "__" + varp->shortName()); // Create: VARREF(_last) // ASSIGN(VARREF(_last), VARREF(var)) // ... // CHANGEDET(VARREF(_last), VARREF(var)) - AstVar* newvarp = new AstVar(varp->fileline(), AstVarType::MODULETEMP, - newvarname, varp); + AstVar* newvarp + = new AstVar(varp->fileline(), AstVarType::MODULETEMP, newvarname, varp); m_statep->m_topModp->addStmtp(newvarp); m_newvscp = new AstVarScope(m_vscp->fileline(), m_statep->m_scopetopp, newvarp); m_statep->m_scopetopp->addVarp(m_newvscp); - m_varEqnp = new AstVarRef(m_vscp->fileline(), m_vscp, false); + m_varEqnp = new AstVarRef(m_vscp->fileline(), m_vscp, false); m_newLvEqnp = new AstVarRef(m_vscp->fileline(), m_newvscp, true); m_newRvEqnp = new AstVarRef(m_vscp->fileline(), m_newvscp, false); } @@ -229,41 +230,38 @@ private: // NODE STATE // Entire netlist: // AstVarScope::user1() -> bool. True indicates processed - AstUser1InUse m_inuser1; + AstUser1InUse m_inuser1; // STATE - ChangedState* m_statep; // Shared state across visitors + ChangedState* m_statep; // Shared state across visitors // METHODS VL_DEBUG_FUNC; // Declare debug() void genChangeDet(AstVarScope* vscp) { - vscp->v3warn(IMPERFECTSCH, "Imperfect scheduling of variable: "<prettyNameQ()); - ChangedInsertVisitor visitor (vscp, m_statep); + vscp->v3warn(IMPERFECTSCH, "Imperfect scheduling of variable: " << vscp->prettyNameQ()); + ChangedInsertVisitor visitor(vscp, m_statep); } // VISITORS virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { - UINFO(4," MOD "<isTop()) { - m_statep->m_topModp = nodep; - } + UINFO(4, " MOD " << nodep << endl); + if (nodep->isTop()) m_statep->m_topModp = nodep; iterateChildren(nodep); } virtual void visit(AstTopScope* nodep) VL_OVERRIDE { - UINFO(4," TS "<scopep(); - UASSERT_OBJ(scopep, nodep, - "No scope found on top level, perhaps you have no statements?"); + UASSERT_OBJ(scopep, nodep, "No scope found on top level, perhaps you have no statements?"); m_statep->m_scopetopp = scopep; // Create a wrapper change detection function that calls each change detection function - m_statep->m_tlChgFuncp = new AstCFunc(nodep->fileline(), - "_change_request", scopep, "QData"); + m_statep->m_tlChgFuncp + = new AstCFunc(nodep->fileline(), "_change_request", scopep, "QData"); m_statep->m_tlChgFuncp->argTypes(EmitCBaseVisitor::symClassVar()); m_statep->m_tlChgFuncp->symProlog(true); m_statep->m_tlChgFuncp->declPrivate(true); @@ -277,10 +275,8 @@ private: } virtual void visit(AstVarScope* nodep) VL_OVERRIDE { if (nodep->isCircular()) { - UINFO(8," CIRC "<user1SetOnce()) { - genChangeDet(nodep); - } + UINFO(8, " CIRC " << nodep << endl); + if (!nodep->user1SetOnce()) genChangeDet(nodep); } } //-------------------- @@ -300,10 +296,10 @@ public: // Changed class functions void V3Changed::changedAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp index 9ee147aed..164463364 100644 --- a/src/V3Clean.cpp +++ b/src/V3Clean.cpp @@ -43,9 +43,9 @@ private: // AstNode::user() -> CleanState. For this node, 0==UNKNOWN // AstNode::user2() -> bool. True indicates widthMin has been propagated // AstNodeDType::user3() -> AstNodeDType*. Alternative node with C size - AstUser1InUse m_inuser1; - AstUser2InUse m_inuser2; - AstUser3InUse m_inuser3; + AstUser1InUse m_inuser1; + AstUser2InUse m_inuser2; + AstUser3InUse m_inuser3; // TYPES enum CleanState { CS_UNKNOWN, CS_CLEAN, CS_DIRTY }; @@ -57,10 +57,14 @@ private: VL_DEBUG_FUNC; // Declare debug() // Width resetting - int cppWidth(AstNode* nodep) { - if (nodep->width() <= VL_IDATASIZE) return VL_IDATASIZE; - else if (nodep->width() <= VL_QUADSIZE) return VL_QUADSIZE; - else return nodep->widthWords() * VL_EDATASIZE; + int cppWidth(AstNode* nodep) { + if (nodep->width() <= VL_IDATASIZE) { + return VL_IDATASIZE; + } else if (nodep->width() <= VL_QUADSIZE) { + return VL_QUADSIZE; + } else { + return nodep->widthWords() * VL_EDATASIZE; + } } void setCppWidth(AstNode* nodep) { nodep->user2(true); // Don't resize it again @@ -82,7 +86,8 @@ private: } void computeCppWidth(AstNode* nodep) { if (!nodep->user2() && nodep->hasDType()) { - if (VN_IS(nodep, Var) || VN_IS(nodep, NodeDType) // Don't want to change variable widths! + if (VN_IS(nodep, Var) + || VN_IS(nodep, NodeDType) // Don't want to change variable widths! || VN_IS(nodep->dtypep()->skipRefp(), AssocArrayDType) // Or arrays || VN_IS(nodep->dtypep()->skipRefp(), DynArrayDType) || VN_IS(nodep->dtypep()->skipRefp(), ClassRefDType) @@ -96,39 +101,33 @@ private: } // Store the clean state in the userp on each node - void setCleanState(AstNode* nodep, CleanState clean) { - nodep->user1(clean); - } - CleanState getCleanState(AstNode* nodep) { - return static_cast(nodep->user1()); - } + void setCleanState(AstNode* nodep, CleanState clean) { nodep->user1(clean); } + CleanState getCleanState(AstNode* nodep) { return static_cast(nodep->user1()); } bool isClean(AstNode* nodep) { CleanState clstate = getCleanState(nodep); - if (clstate==CS_CLEAN) return true; - if (clstate==CS_DIRTY) return false; - nodep->v3fatalSrc("Unknown clean state on node: "+nodep->prettyTypeName()); + if (clstate == CS_CLEAN) return true; + if (clstate == CS_DIRTY) return false; + nodep->v3fatalSrc("Unknown clean state on node: " + nodep->prettyTypeName()); return false; } void setClean(AstNode* nodep, bool isClean) { computeCppWidth(nodep); // Just to be sure it's in widthMin - bool wholeUint = (nodep->widthMin() == VL_IDATASIZE - || nodep->widthMin() == VL_QUADSIZE + bool wholeUint = (nodep->widthMin() == VL_IDATASIZE || nodep->widthMin() == VL_QUADSIZE || (nodep->widthMin() % VL_EDATASIZE) == 0); setCleanState(nodep, ((isClean || wholeUint) ? CS_CLEAN : CS_DIRTY)); } // Operate on nodes void insertClean(AstNode* nodep) { // We'll insert ABOVE passed node - UINFO(4," NeedClean "<unlinkFrBack(&relinkHandle); // computeCppWidth(nodep); - V3Number mask (nodep, cppWidth(nodep)); + V3Number mask(nodep, cppWidth(nodep)); mask.setMask(nodep->widthMin()); - AstNode* cleanp = new AstAnd(nodep->fileline(), - new AstConst(nodep->fileline(), mask), - nodep); + AstNode* cleanp + = new AstAnd(nodep->fileline(), new AstConst(nodep->fileline(), mask), nodep); cleanp->dtypeFrom(nodep); // Otherwise the AND normally picks LHS relinkHandle.relink(cleanp); } @@ -138,7 +137,7 @@ private: } void ensureCleanAndNext(AstNode* nodep) { // Editing list, careful looping! - for (AstNode* exprp = nodep; exprp; ) { + for (AstNode* exprp = nodep; exprp;) { AstNode* nextp = exprp->nextp(); ensureClean(exprp); exprp = nextp; @@ -149,27 +148,17 @@ private: void operandBiop(AstNodeBiop* nodep) { iterateChildren(nodep); computeCppWidth(nodep); - if (nodep->cleanLhs()) { - ensureClean(nodep->lhsp()); - } - if (nodep->cleanRhs()) { - ensureClean(nodep->rhsp()); - } - //no setClean.. must do it in each user routine. + if (nodep->cleanLhs()) ensureClean(nodep->lhsp()); + if (nodep->cleanRhs()) ensureClean(nodep->rhsp()); + // no setClean.. must do it in each user routine. } void operandTriop(AstNodeTriop* nodep) { iterateChildren(nodep); computeCppWidth(nodep); - if (nodep->cleanLhs()) { - ensureClean(nodep->lhsp()); - } - if (nodep->cleanRhs()) { - ensureClean(nodep->rhsp()); - } - if (nodep->cleanThs()) { - ensureClean(nodep->thsp()); - } - //no setClean.. must do it in each user routine. + if (nodep->cleanLhs()) ensureClean(nodep->lhsp()); + if (nodep->cleanRhs()) ensureClean(nodep->rhsp()); + if (nodep->cleanThs()) ensureClean(nodep->thsp()); + // no setClean.. must do it in each user routine. } // VISITORS @@ -184,9 +173,7 @@ private: virtual void visit(AstNodeUniop* nodep) VL_OVERRIDE { iterateChildren(nodep); computeCppWidth(nodep); - if (nodep->cleanLhs()) { - ensureClean(nodep->lhsp()); - } + if (nodep->cleanLhs()) ensureClean(nodep->lhsp()); setClean(nodep, nodep->cleanOut()); } virtual void visit(AstNodeBiop* nodep) VL_OVERRIDE { @@ -213,14 +200,12 @@ private: virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { iterateChildren(nodep); computeCppWidth(nodep); - if (nodep->cleanRhs()) { - ensureClean(nodep->rhsp()); - } + if (nodep->cleanRhs()) ensureClean(nodep->rhsp()); } - virtual void visit(AstText* nodep) VL_OVERRIDE { + virtual void visit(AstText* nodep) VL_OVERRIDE { // setClean(nodep, true); } - virtual void visit(AstScopeName* nodep) VL_OVERRIDE { + virtual void visit(AstScopeName* nodep) VL_OVERRIDE { // setClean(nodep, true); } virtual void visit(AstCNew* nodep) VL_OVERRIDE { @@ -236,9 +221,7 @@ private: computeCppWidth(nodep); setClean(nodep, false); // We always clean, as we don't trust those pesky users. - if (!VN_IS(nodep->backp(), And)) { - insertClean(nodep); - } + if (!VN_IS(nodep->backp(), And)) insertClean(nodep); ensureCleanAndNext(nodep->bodysp()); } virtual void visit(AstTraceDecl* nodep) VL_OVERRIDE { @@ -316,9 +299,7 @@ public: // Clean class functions void V3Clean::cleanAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index bbb184244..5e89b0e72 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -46,22 +46,22 @@ private: // NODE STATE // Cleared each Module: // AstVarScope::user1p() -> AstVarScope*. Temporary signal that was created. - AstUser1InUse m_inuser1; + AstUser1InUse m_inuser1; // TYPES enum { DOUBLE_OR_RATE = 10 }; // How many | per ||, Determined experimentally as best // STATE - AstNodeModule* m_modp; // Current module - AstTopScope* m_topScopep; // Current top scope - AstScope* m_scopep; // Current scope - AstCFunc* m_evalFuncp; // Top eval function we are creating - AstCFunc* m_initFuncp; // Top initial function we are creating - AstCFunc* m_finalFuncp; // Top final function we are creating - AstCFunc* m_settleFuncp; // Top settlement function we are creating - AstSenTree* m_lastSenp; // Last sensitivity match, so we can detect duplicates. - AstIf* m_lastIfp; // Last sensitivity if active to add more under - AstMTaskBody* m_mtaskBodyp; // Current mtask body + AstNodeModule* m_modp; // Current module + AstTopScope* m_topScopep; // Current top scope + AstScope* m_scopep; // Current scope + AstCFunc* m_evalFuncp; // Top eval function we are creating + AstCFunc* m_initFuncp; // Top initial function we are creating + AstCFunc* m_finalFuncp; // Top final function we are creating + AstCFunc* m_settleFuncp; // Top settlement function we are creating + AstSenTree* m_lastSenp; // Last sensitivity match, so we can detect duplicates. + AstIf* m_lastIfp; // Last sensitivity if active to add more under + AstMTaskBody* m_mtaskBodyp; // Current mtask body // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -69,12 +69,14 @@ private: AstVarScope* getCreateLastClk(AstVarScope* vscp) { if (vscp->user1p()) return static_cast(vscp->user1p()); AstVar* varp = vscp->varp(); - if (!varp->width1()) varp->v3error("Unsupported: Clock edge on non-single bit signal: " - <prettyNameQ()); - string newvarname = (string("__Vclklast__") - +vscp->scopep()->nameDotless()+"__"+varp->name()); - AstVar* newvarp = new AstVar(vscp->fileline(), - AstVarType::MODULETEMP, newvarname, VFlagLogicPacked(), 1); + if (!varp->width1()) { + varp->v3error( + "Unsupported: Clock edge on non-single bit signal: " << varp->prettyNameQ()); + } + string newvarname + = (string("__Vclklast__") + vscp->scopep()->nameDotless() + "__" + varp->name()); + AstVar* newvarp = new AstVar(vscp->fileline(), AstVarType::MODULETEMP, newvarname, + VFlagLogicPacked(), 1); newvarp->noReset(true); // Reset by below assign m_modp->addStmtp(newvarp); AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp); @@ -83,18 +85,16 @@ private: // Add init AstNode* fromp = new AstVarRef(newvarp->fileline(), vscp, false); if (v3Global.opt.xInitialEdge()) fromp = new AstNot(fromp->fileline(), fromp); - AstNode* newinitp = new AstAssign(vscp->fileline(), - new AstVarRef(newvarp->fileline(), newvscp, true), - fromp); + AstNode* newinitp = new AstAssign( + vscp->fileline(), new AstVarRef(newvarp->fileline(), newvscp, true), fromp); addToInitial(newinitp); // At bottom, assign them AstAssign* finalp - = new AstAssign(vscp->fileline(), - new AstVarRef(vscp->fileline(), newvscp, true), + = new AstAssign(vscp->fileline(), new AstVarRef(vscp->fileline(), newvscp, true), new AstVarRef(vscp->fileline(), vscp, false)); m_evalFuncp->addFinalsp(finalp); // - UINFO(4,"New Last: "<edgeType()==VEdgeType::ET_ILLEGAL) { + if (nodep->edgeType() == VEdgeType::ET_ILLEGAL) { if (!v3Global.opt.bboxUnsup()) { - nodep->v3error("Unsupported: Complicated event expression in sensitive activity list"); + nodep->v3error( + "Unsupported: Complicated event expression in sensitive activity list"); } return NULL; } AstVarScope* clkvscp = nodep->varrefp()->varScopep(); if (nodep->edgeType() == VEdgeType::ET_POSEDGE) { AstVarScope* lastVscp = getCreateLastClk(clkvscp); - newp = new AstAnd(nodep->fileline(), - new AstVarRef(nodep->fileline(), - nodep->varrefp()->varScopep(), false), - new AstNot(nodep->fileline(), - new AstVarRef(nodep->fileline(), - lastVscp, false))); + newp = new AstAnd( + nodep->fileline(), + new AstVarRef(nodep->fileline(), nodep->varrefp()->varScopep(), false), + new AstNot(nodep->fileline(), new AstVarRef(nodep->fileline(), lastVscp, false))); } else if (nodep->edgeType() == VEdgeType::ET_NEGEDGE) { AstVarScope* lastVscp = getCreateLastClk(clkvscp); - newp = new AstAnd(nodep->fileline(), - new AstNot(nodep->fileline(), - new AstVarRef(nodep->fileline(), - nodep->varrefp()->varScopep(), false)), - new AstVarRef(nodep->fileline(), lastVscp, false)); + newp = new AstAnd( + nodep->fileline(), + new AstNot(nodep->fileline(), + new AstVarRef(nodep->fileline(), nodep->varrefp()->varScopep(), false)), + new AstVarRef(nodep->fileline(), lastVscp, false)); } else if (nodep->edgeType() == VEdgeType::ET_BOTHEDGE) { AstVarScope* lastVscp = getCreateLastClk(clkvscp); - newp = new AstXor(nodep->fileline(), - new AstVarRef(nodep->fileline(), - nodep->varrefp()->varScopep(), false), - new AstVarRef(nodep->fileline(), lastVscp, false)); + newp = new AstXor( + nodep->fileline(), + new AstVarRef(nodep->fileline(), nodep->varrefp()->varScopep(), false), + new AstVarRef(nodep->fileline(), lastVscp, false)); } else if (nodep->edgeType() == VEdgeType::ET_HIGHEDGE) { - newp = new AstVarRef(nodep->fileline(), - clkvscp, false); + newp = new AstVarRef(nodep->fileline(), clkvscp, false); } else if (nodep->edgeType() == VEdgeType::ET_LOWEDGE) { - newp = new AstNot(nodep->fileline(), - new AstVarRef(nodep->fileline(), - clkvscp, false)); + newp = new AstNot(nodep->fileline(), new AstVarRef(nodep->fileline(), clkvscp, false)); } else { nodep->v3fatalSrc("Bad edge type"); } return newp; } AstNode* createSenGateEquation(AstSenGate* nodep) { - AstNode* newp = new AstAnd(nodep->fileline(), - createSenseEquation(nodep->sensesp()), + AstNode* newp = new AstAnd(nodep->fileline(), createSenseEquation(nodep->sensesp()), nodep->rhsp()->cloneTree(true)); return newp; } @@ -186,12 +181,12 @@ private: // VISITORS virtual void visit(AstTopScope* nodep) VL_OVERRIDE { - UINFO(4," TOPSCOPE "<scopep(); UASSERT_OBJ(m_scopep, nodep, "No scope found on top level, perhaps you have no statements?"); - //VV***** We reset all user1p() + // VV***** We reset all user1p() AstNode::user1ClearTree(); // Make top functions { @@ -223,11 +218,10 @@ private: funcp->isStatic(false); funcp->entryPoint(true); funcp->protect(false); - funcp->addInitsp(new AstCStmt - (nodep->fileline(), - EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp;\n")); - funcp->addInitsp(new AstCStmt(nodep->fileline(), - EmitCBaseVisitor::symTopAssign()+"\n")); + funcp->addInitsp(new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symClassVar() + + " = this->__VlSymsp;\n")); + funcp->addInitsp( + new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign() + "\n")); m_scopep->addActivep(funcp); m_finalFuncp = funcp; } @@ -245,13 +239,13 @@ private: // Process the activates iterateChildren(nodep); // Done, clear so we can detect errors - UINFO(4," TOPSCOPEDONE "<finalClksp()) { @@ -289,24 +283,21 @@ private: VL_DO_DANGLING(nodep->deleteTree(), nodep); } virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE { - //nodep->dumpTree(cout, "ct:"); - //COVERTOGGLE(INC, ORIG, CHANGE) -> + // nodep->dumpTree(cout, "ct:"); + // COVERTOGGLE(INC, ORIG, CHANGE) -> // IF(ORIG ^ CHANGE) { INC; CHANGE = ORIG; } AstNode* incp = nodep->incp()->unlinkFrBack(); AstNode* origp = nodep->origp()->unlinkFrBack(); AstNode* changep = nodep->changep()->unlinkFrBack(); - AstIf* newp = new AstIf(nodep->fileline(), - new AstXor(nodep->fileline(), - origp, - changep), + AstIf* newp = new AstIf(nodep->fileline(), new AstXor(nodep->fileline(), origp, changep), incp, NULL); // We could add another IF to detect posedges, and only increment if so. // It's another whole branch though versus a potential memory miss. // We'll go with the miss. - newp->addIfsp(new AstAssign(nodep->fileline(), - changep->cloneTree(false), - origp->cloneTree(false))); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + newp->addIfsp( + new AstAssign(nodep->fileline(), changep->cloneTree(false), origp->cloneTree(false))); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } virtual void visit(AstInitial* nodep) VL_OVERRIDE { AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true); @@ -321,7 +312,7 @@ private: iterateChildren(nodep); // Link to global function if (nodep->formCallTree()) { - UINFO(4, " formCallTree "<fileline(), nodep); callp->argTypes("vlSymsp"); m_finalFuncp->addStmtsp(callp); @@ -333,13 +324,13 @@ private: pushDeletep(nodep); } void addToEvalLoop(AstNode* stmtsp) { - m_evalFuncp->addStmtsp(stmtsp); // add to top level function + m_evalFuncp->addStmtsp(stmtsp); // add to top level function } void addToSettleLoop(AstNode* stmtsp) { - m_settleFuncp->addStmtsp(stmtsp); // add to top level function + m_settleFuncp->addStmtsp(stmtsp); // add to top level function } void addToInitial(AstNode* stmtsp) { - m_initFuncp->addStmtsp(stmtsp); // add to top level function + m_initFuncp->addStmtsp(stmtsp); // add to top level function } virtual void visit(AstActive* nodep) VL_OVERRIDE { // Careful if adding variables here, ACTIVES can be under other ACTIVES @@ -350,13 +341,13 @@ private: UASSERT_OBJ(!nodep->stmtsp(), nodep, "Non-empty lower active"); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } else if (m_mtaskBodyp) { - UINFO(4," TR ACTIVE "<stmtsp()->unlinkFrBackWithNext(); if (nodep->hasClocked()) { UASSERT_OBJ(!nodep->hasInitial(), nodep, "Initial block should not have clock sensitivity"); if (m_lastSenp && nodep->sensesp()->sameTree(m_lastSenp)) { - UINFO(4," sameSenseTree\n"); + UINFO(4, " sameSenseTree\n"); } else { clearLastSen(); m_lastSenp = nodep->sensesp(); @@ -375,14 +366,14 @@ private: } VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } else { - UINFO(4," ACTIVE "<stmtsp()->unlinkFrBackWithNext(); if (nodep->hasClocked()) { // Remember the latest sensitivity so we can compare it next time UASSERT_OBJ(!nodep->hasInitial(), nodep, "Initial block should not have clock sensitivity"); if (m_lastSenp && nodep->sensesp()->sameTree(m_lastSenp)) { - UINFO(4," sameSenseTree\n"); + UINFO(4, " sameSenseTree\n"); } else { clearLastSen(); m_lastSenp = nodep->sensesp(); @@ -410,8 +401,7 @@ private: } } virtual void visit(AstExecGraph* nodep) VL_OVERRIDE { - for (m_mtaskBodyp = VN_CAST(nodep->op1p(), MTaskBody); - m_mtaskBodyp; + for (m_mtaskBodyp = VN_CAST(nodep->op1p(), MTaskBody); m_mtaskBodyp; m_mtaskBodyp = VN_CAST(m_mtaskBodyp->nextp(), MTaskBody)) { clearLastSen(); iterate(m_mtaskBodyp); @@ -453,9 +443,7 @@ public: // Clock class functions void V3Clock::clockAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Combine.cpp b/src/V3Combine.cpp index c9f2303f2..9224e0576 100644 --- a/src/V3Combine.cpp +++ b/src/V3Combine.cpp @@ -75,22 +75,24 @@ class CombCallVisitor : CombBaseVisitor { // Find all CCALLS of each CFUNC, so that we can later rename them private: // NODE STATE - typedef std::multimap CallMmap; - CallMmap m_callMmap; // Associative array of {function}{call} + typedef std::multimap CallMmap; + CallMmap m_callMmap; // Associative array of {function}{call} // METHODS public: void replaceFunc(AstCFunc* oldfuncp, AstCFunc* newfuncp) { - if (oldfuncp==newfuncp) return; + if (oldfuncp == newfuncp) return; if (newfuncp) { - UINFO(4, " Replace "< "< eqrange + UINFO(4, " Replace " << oldfuncp << " -WITH-> " << newfuncp << endl); + } else { + UINFO(4, " Remove " << oldfuncp << endl); + } + std::pair eqrange = m_callMmap.equal_range(oldfuncp); for (CallMmap::iterator nextit = eqrange.first; nextit != eqrange.second;) { CallMmap::iterator eqit = nextit++; AstCCall* callp = eqit->second; if (!callp->user3()) { // !already done - UINFO(4, " Called "<funcp() == oldfuncp, callp, "Call list broken, points to call w/different func"); if (newfuncp) { @@ -108,27 +110,24 @@ public: } } // METHODS - void addCall(AstCCall* nodep) { - m_callMmap.insert(make_pair(nodep->funcp(), nodep)); - } + void addCall(AstCCall* nodep) { m_callMmap.insert(make_pair(nodep->funcp(), nodep)); } void deleteCall(AstCCall* nodep) { - std::pair eqrange + std::pair eqrange = m_callMmap.equal_range(nodep->funcp()); for (CallMmap::iterator nextit = eqrange.first; nextit != eqrange.second;) { CallMmap::iterator eqit = nextit++; AstCCall* callp = eqit->second; - if (callp==nodep) { + if (callp == nodep) { m_callMmap.erase(eqit); return; } } nodep->v3fatalSrc("deleteCall node not found in table"); } + private: // VISITORS - virtual void visit(AstCCall* nodep) VL_OVERRIDE { - addCall(nodep); - } + virtual void visit(AstCCall* nodep) VL_OVERRIDE { addCall(nodep); } // Speed things up virtual void visit(AstNodeAssign*) VL_OVERRIDE {} virtual void visit(AstNodeMath*) VL_OVERRIDE {} @@ -154,11 +153,10 @@ private: nodep->user3(true); iterateChildren(nodep); } + public: // CONSTRUCTORS - explicit CombMarkVisitor(AstNode* nodep) { - iterate(nodep); - } + explicit CombMarkVisitor(AstNode* nodep) { iterate(nodep); } virtual ~CombMarkVisitor() {} }; @@ -172,29 +170,30 @@ private: // AstNodeStmt::user() -> bool. True if iterated already // AstCFunc::user3p() -> AstCFunc*, If set, replace ccalls to this func with new func // AstNodeStmt::user3() -> AstNode*. True if to ignore this cell - // AstNodeStmt::user4() -> V3Hashed::V3Hash. Hash value of this node (hash of 0 is illegal) - AstUser1InUse m_inuser1; - AstUser3InUse m_inuser3; - //AstUser4InUse part of V3Hashed + // AstNodeStmt::user4() -> V3Hashed::V3Hash. Hash value of this node (hash of 0 is + // illegal) + AstUser1InUse m_inuser1; + AstUser3InUse m_inuser3; + // AstUser4InUse part of V3Hashed // STATE - typedef enum {STATE_IDLE, STATE_HASH, STATE_DUP} CombineState; - VDouble0 m_statCombs; // Statistic tracking - CombineState m_state; // Major state - AstNodeModule* m_modp; // Current module - AstCFunc* m_funcp; // Current function - V3Hash m_lowerHash; // Hash of the statement we're building - CombCallVisitor m_call; // Tracking of function call users - int m_modNFuncs; // Number of functions made - AstNode* m_walkLast1p; // Final node that is the same in duplicate list - AstNode* m_walkLast2p; // Final node that is the same in duplicate list - V3Hashed m_hashed; // Hash for every node in module + typedef enum { STATE_IDLE, STATE_HASH, STATE_DUP } CombineState; + VDouble0 m_statCombs; // Statistic tracking + CombineState m_state; // Major state + AstNodeModule* m_modp; // Current module + AstCFunc* m_funcp; // Current function + V3Hash m_lowerHash; // Hash of the statement we're building + CombCallVisitor m_call; // Tracking of function call users + int m_modNFuncs; // Number of functions made + AstNode* m_walkLast1p; // Final node that is the same in duplicate list + AstNode* m_walkLast2p; // Final node that is the same in duplicate list + V3Hashed m_hashed; // Hash for every node in module // METHODS void hashStatement(AstNode* nodep) { // Compute hash on entire tree of this statement m_hashed.hashAndInsert(nodep); - //UINFO(9," stmthash "<user4()<<" "<user4() << " " << nodep << endl); } void hashFunctions(AstCFunc* nodep) { // Compute hash of all statement trees in the function @@ -209,11 +208,9 @@ private: for (V3Hashed::iterator it = m_hashed.begin(); it != m_hashed.end(); ++it) { AstNode* node1p = it->second; AstCFunc* oldfuncp = VN_CAST(node1p, CFunc); - if (oldfuncp - && oldfuncp->emptyBody() - && !oldfuncp->dontCombine()) { - UINFO(5," EmptyFunc "<user4p()) - <<" "<emptyBody() && !oldfuncp->dontCombine()) { + UINFO(5, " EmptyFunc " << std::hex << V3Hash(oldfuncp->user4p()) << " " + << oldfuncp << endl); // Mark user3p on entire old tree, so we don't process it more CombMarkVisitor visitor(oldfuncp); m_call.replaceFunc(oldfuncp, NULL); @@ -231,7 +228,7 @@ private: for (V3Hashed::iterator eqit = it; eqit != m_hashed.end(); ++eqit) { AstNode* node2p = eqit->second; if (!(eqit->first == hashval)) break; - if (node1p==node2p) continue; // Identical iterator + if (node1p == node2p) continue; // Identical iterator if (node1p->user3p() || node2p->user3p()) continue; // Already merged if (node1p->sameTree(node2p)) { // walk of tree has same comparison // Replace AstCCall's that point here @@ -243,8 +240,10 @@ private: } } void replaceFuncWFunc(AstCFunc* oldfuncp, AstCFunc* newfuncp) { - UINFO(5," DupFunc "<user4p())<<" "<user4p())<<" "<user4p()) << " " << newfuncp + << endl); + UINFO(5, " and " << std::hex << V3Hash(oldfuncp->user4p()) << " " << oldfuncp + << endl); // Mark user3p on entire old tree, so we don't process it more ++m_statCombs; CombMarkVisitor visitor(oldfuncp); @@ -254,12 +253,10 @@ private: } void replaceOnlyCallFunc(AstCCall* nodep) { if (AstCFunc* oldfuncp = VN_CAST(nodep->backp(), CFunc)) { - //oldfuncp->dumpTree(cout, "MAYDEL: "); - if (nodep->nextp()==NULL - && oldfuncp->initsp()==NULL - && oldfuncp->stmtsp()==nodep - && oldfuncp->finalsp()==NULL) { - UINFO(9," Function only has call "<dumpTree(cout, "MAYDEL: "); + if (nodep->nextp() == NULL && oldfuncp->initsp() == NULL && oldfuncp->stmtsp() == nodep + && oldfuncp->finalsp() == NULL) { + UINFO(9, " Function only has call " << oldfuncp << endl); m_call.deleteCall(nodep); CombMarkVisitor visitor(oldfuncp); VL_DO_DANGLING(replaceFuncWFunc(oldfuncp, nodep->funcp()), nodep); @@ -269,18 +266,18 @@ private: void walkDupCodeStart(AstNode* node1p) { V3Hash hashval(node1p->user4p()); - //UINFO(4," STMT "< eqrange + std::pair eqrange = m_hashed.mmap().equal_range(hashval); for (V3Hashed::iterator eqit = eqrange.first; eqit != eqrange.second; ++eqit) { AstNode* node2p = eqit->second; - if (node1p==node2p) continue; + if (node1p == node2p) continue; // // We need to mark iteration to prevent matching code inside // code (abab matching in ababab) @@ -288,8 +285,7 @@ private: m_walkLast1p = NULL; m_walkLast2p = NULL; int depth = walkDupCodeNext(node1p, node2p, 1); - if (depth>COMBINE_MIN_STATEMENTS - && depth>bestDepth) { + if (depth > COMBINE_MIN_STATEMENTS && depth > bestDepth) { bestDepth = depth; bestNode2p = node2p; bestLast1p = m_walkLast1p; @@ -298,11 +294,15 @@ private: } if (bestDepth) { // Found a replacement - UINFO(5," Duplicate of depth "<user3p() || node2p->user3p()) return 0; // Already merged if (!m_hashed.sameNodes(node1p, node2p)) return 0; // walk of tree has same comparison V3Hash hashval(node1p->user4p()); - //UINFO(9," wdup1 "<user4p())<<" "<user4p())<<" "<user4p())<<" "<user4p())<<" "<user1(true); node2p->user1(true); if (node1p->nextp() && node2p->nextp()) { - return hashval.depth()+walkDupCodeNext(node1p->nextp(), node2p->nextp(), level+1); + return hashval.depth() + walkDupCodeNext(node1p->nextp(), node2p->nextp(), level + 1); } return hashval.depth(); } - void walkReplace(AstNode* node1p, AstNode* node2p, - AstNode* last1p, AstNode* last2p) { // Final node in linked list, maybe null if all statements to be grabbed + void walkReplace(AstNode* node1p, AstNode* node2p, AstNode* last1p, + AstNode* last2p) { // Final node in linked list, maybe null if all statements + // to be grabbed // Make new function string oldname = m_funcp->name(); string::size_type pos; - if ((pos = oldname.find("_common")) != string::npos) { - oldname.erase(pos); - } - if ((pos = oldname.find("__")) != string::npos) { - oldname.erase(pos); - } + if ((pos = oldname.find("_common")) != string::npos) oldname.erase(pos); + if ((pos = oldname.find("__")) != string::npos) oldname.erase(pos); AstCFunc* newfuncp = new AstCFunc(node1p->fileline(), - oldname+"_common"+cvtToStr(++m_modNFuncs), - NULL); + oldname + "_common" + cvtToStr(++m_modNFuncs), NULL); m_modp->addStmtp(newfuncp); // Create calls AstCCall* call1p = new AstCCall(node1p->fileline(), newfuncp); @@ -347,21 +343,29 @@ private: // Grab statement bodies AstNRelinker relink1Handle; AstNRelinker relink2Handle; - for (AstNode* nextp, *walkp = node1p; 1; walkp = nextp) { + for (AstNode *nextp, *walkp = node1p; 1; walkp = nextp) { nextp = walkp->nextp(); - if (walkp==node1p) walkp->unlinkFrBack(&relink1Handle); - else { walkp->unlinkFrBack(); node1p->addNext(walkp); } - if (walkp==last1p) break; + if (walkp == node1p) { + walkp->unlinkFrBack(&relink1Handle); + } else { + walkp->unlinkFrBack(); + node1p->addNext(walkp); + } + if (walkp == last1p) break; } - for (AstNode* nextp, *walkp = node2p; 1; walkp = nextp) { + for (AstNode *nextp, *walkp = node2p; 1; walkp = nextp) { nextp = walkp->nextp(); - if (walkp==node2p) walkp->unlinkFrBack(&relink2Handle); - else { walkp->unlinkFrBack(); node2p->addNext(walkp); } - if (walkp==last2p) break; + if (walkp == node2p) { + walkp->unlinkFrBack(&relink2Handle); + } else { + walkp->unlinkFrBack(); + node2p->addNext(walkp); + } + if (walkp == last2p) break; } // Move node1 statements to new function newfuncp->addStmtsp(node1p); - //newfuncp->dumpTree(cout, " newfunctree: "); + // newfuncp->dumpTree(cout, " newfunctree: "); // Mark node2 statements as dead CombMarkVisitor visitor(node2p); pushDeletep(node2p); // Delete later @@ -383,13 +387,13 @@ private: // Track all callers of each function m_call.main(nodep); // - //In V3Hashed AstNode::user4ClearTree(); // user4p() used on entire tree + // In V3Hashed AstNode::user4ClearTree(); // user4p() used on entire tree // Iterate modules backwards, in bottom-up order. // Required so that a module instantiating another can benefit from collapsing. iterateChildrenBackwards(nodep); } virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { - UINFO(4," MOD "<=9) { - m_hashed.dumpFilePrefixed("combine"); - } + if (debug() >= 9) m_hashed.dumpFilePrefixed("combine"); // Walk the hashes removing empty functions - if (emptyFunctionDeletion()) { - walkEmptyFuncs(); - } + if (emptyFunctionDeletion()) walkEmptyFuncs(); // Walk the hashes looking for duplicate functions - if (duplicateFunctionCombine()) { - walkDupFuncs(); - } + if (duplicateFunctionCombine()) walkDupFuncs(); // Walk the statements looking for large replicated code sections if (statementCombine()) { m_state = STATE_DUP; @@ -435,8 +433,7 @@ private: } if (m_state == STATE_HASH && m_funcp) { hashStatement(nodep); - } - else if (m_state == STATE_DUP && m_funcp) { + } else if (m_state == STATE_DUP && m_funcp) { walkDupCodeStart(nodep); } } @@ -459,7 +456,7 @@ public: m_walkLast2p = NULL; iterate(nodep); } - virtual ~CombineVisitor() { + virtual ~CombineVisitor() { // V3Stats::addStat("Optimizations, Combined CFuncs", m_statCombs); } }; @@ -468,9 +465,7 @@ public: // Combine class functions void V3Combine::combineAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Config.cpp b/src/V3Config.cpp index 46b491e90..7b89b4df7 100644 --- a/src/V3Config.cpp +++ b/src/V3Config.cpp @@ -327,12 +327,12 @@ public: inline void applyIgnores(FileLine* filelinep) { // HOT routine, called each parsed token line of this filename if (m_lastIgnore.lineno != filelinep->lineno()) { - // UINFO(9," ApplyIgnores for "<ascii()<ascii() << endl); // Process all on/offs for lines up to and including the current line int curlineno = filelinep->lastLineno(); for (; m_lastIgnore.it != m_ignLines.end(); ++m_lastIgnore.it) { if (m_lastIgnore.it->m_lineno > curlineno) break; - // UINFO(9," Hit "<<*m_lastIt<warnOn(m_lastIgnore.it->m_code, m_lastIgnore.it->m_on); } if (0 && debug() >= 9) { diff --git a/src/V3Const.cpp b/src/V3Const.cpp index c99d1950b..f0f173c84 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -61,6 +61,7 @@ class ConstVarFindVisitor : public AstNVisitor { // AstVar::user4p -> bool, input from ConstVarMarkVisitor // MEMBERS bool m_found; + private: // VISITORS virtual void visit(AstVarRef* nodep) VL_OVERRIDE { @@ -92,27 +93,25 @@ private: // AstEnum::user4 -> bool. Recursing. // STATE - bool m_params; // If true, propagate parameterized and true numbers only - bool m_required; // If true, must become a constant - bool m_wremove; // Inside scope, no assignw removal - bool m_warn; // Output warnings - bool m_doExpensive; // Enable computationally expensive optimizations - bool m_doNConst; // Enable non-constant-child simplifications - bool m_doShort; // Remove expressions that short circuit - bool m_doV; // Verilog, not C++ conversion - bool m_doGenerate; // Postpone width checking inside generate - bool m_hasJumpGo; // JumpGo under this while - AstNodeModule* m_modp; // Current module - AstArraySel* m_selp; // Current select - AstNode* m_scopep; // Current scope - AstAttrOf* m_attrp; // Current attribute + bool m_params; // If true, propagate parameterized and true numbers only + bool m_required; // If true, must become a constant + bool m_wremove; // Inside scope, no assignw removal + bool m_warn; // Output warnings + bool m_doExpensive; // Enable computationally expensive optimizations + bool m_doNConst; // Enable non-constant-child simplifications + bool m_doShort; // Remove expressions that short circuit + bool m_doV; // Verilog, not C++ conversion + bool m_doGenerate; // Postpone width checking inside generate + bool m_hasJumpGo; // JumpGo under this while + AstNodeModule* m_modp; // Current module + AstArraySel* m_selp; // Current select + AstNode* m_scopep; // Current scope + AstAttrOf* m_attrp; // Current attribute // METHODS VL_DEBUG_FUNC; // Declare debug() - bool operandConst(AstNode* nodep) { - return VN_IS(nodep, Const); - } + bool operandConst(AstNode* nodep) { return VN_IS(nodep, Const); } bool operandAsvConst(const AstNode* nodep) { // BIASV(CONST, BIASV(CONST,...)) -> BIASV( BIASV_CONSTED(a,b), ...) const AstNodeBiComAsv* bnodep = VN_CAST_CONST(nodep, NodeBiComAsv); @@ -169,10 +168,8 @@ private: // SUB( ADD(CONSTx,y), CONSTz) -> ADD(SUB(CONSTx,CONSTz), y) const AstNodeBiop* np = VN_CAST_CONST(nodep, NodeBiop); const AstNodeBiop* lp = VN_CAST_CONST(np->lhsp(), NodeBiop); - return (lp - && VN_IS(lp->lhsp(), Const) - && VN_IS(np->rhsp(), Const) - && lp->width()==np->width()); + return (lp && VN_IS(lp->lhsp(), Const) && VN_IS(np->rhsp(), Const) + && lp->width() == np->width()); } static bool operandAndOrSame(const AstNode* nodep) { @@ -181,11 +178,8 @@ private: const AstNodeBiop* np = VN_CAST_CONST(nodep, NodeBiop); const AstNodeBiop* lp = VN_CAST_CONST(np->lhsp(), NodeBiop); const AstNodeBiop* rp = VN_CAST_CONST(np->rhsp(), NodeBiop); - return (lp && rp - && lp->width()==rp->width() - && lp->type()==rp->type() - && (operandsSame(lp->lhsp(), rp->lhsp()) - || operandsSame(lp->rhsp(), rp->rhsp()))); + return (lp && rp && lp->width() == rp->width() && lp->type() == rp->type() + && (operandsSame(lp->lhsp(), rp->lhsp()) || operandsSame(lp->rhsp(), rp->rhsp()))); } static bool matchOrAndNot(AstNodeBiop* nodep) { // AstOr{$a, AstAnd{AstNot{$b}, $c}} if $a.width1, $a==$b => AstOr{$a,$c} @@ -194,22 +188,36 @@ private: // if (rst) ... else if (enable)... -> OR(rst,AND(!rst,enable)) AstNode* ap; AstNodeBiop* andp; - if (VN_IS(nodep->lhsp(), And)) { andp = VN_CAST(nodep->lhsp(), And); ap = nodep->rhsp(); } - else if (VN_IS(nodep->rhsp(), And)) { andp = VN_CAST(nodep->rhsp(), And); ap = nodep->lhsp(); } - else return false; + if (VN_IS(nodep->lhsp(), And)) { + andp = VN_CAST(nodep->lhsp(), And); + ap = nodep->rhsp(); + } else if (VN_IS(nodep->rhsp(), And)) { + andp = VN_CAST(nodep->rhsp(), And); + ap = nodep->lhsp(); + } else + return false; AstNodeUniop* notp; AstNode* cp; - if (VN_IS(andp->lhsp(), Not)) { notp = VN_CAST(andp->lhsp(), Not); cp=andp->rhsp(); } - else if (VN_IS(andp->rhsp(), Not)) { notp = VN_CAST(andp->rhsp(), Not); cp=andp->lhsp(); } - else return false; + if (VN_IS(andp->lhsp(), Not)) { + notp = VN_CAST(andp->lhsp(), Not); + cp = andp->rhsp(); + } else if (VN_IS(andp->rhsp(), Not)) { + notp = VN_CAST(andp->rhsp(), Not); + cp = andp->lhsp(); + } else + return false; AstNode* bp = notp->lhsp(); if (!operandsSame(ap, bp)) return false; // Do it cp->unlinkFrBack(); - VL_DO_DANGLING(andp->unlinkFrBack()->deleteTree(), andp); VL_DANGLING(notp); + VL_DO_DANGLING(andp->unlinkFrBack()->deleteTree(), andp); + VL_DANGLING(notp); // Replace whichever branch is now dangling - if (nodep->rhsp()) nodep->lhsp(cp); - else nodep->rhsp(cp); + if (nodep->rhsp()) { + nodep->lhsp(cp); + } else { + nodep->rhsp(cp); + } return true; } bool matchAndCond(AstAnd* nodep) { @@ -222,19 +230,19 @@ private: if (!VN_IS(condp->expr1p(), Const) && !VN_IS(condp->expr2p(), Const)) return false; AstConst* maskp = VN_CAST(nodep->lhsp(), Const); if (!maskp) return false; - UINFO(4, "AND(CONSTm, CONDcond(c, i, e))->CONDcond(c, AND(m,i), AND(m, e)) "<CONDcond(c, AND(m,i), AND(m, e)) " << nodep + << endl); AstNodeCond* newp = static_cast( condp->cloneType(condp->condp()->unlinkFrBack(), - new AstAnd(nodep->fileline(), - maskp->cloneTree(false), + new AstAnd(nodep->fileline(), maskp->cloneTree(false), condp->expr1p()->unlinkFrBack()), - new AstAnd(nodep->fileline(), - maskp->cloneTree(false), + new AstAnd(nodep->fileline(), maskp->cloneTree(false), condp->expr2p()->unlinkFrBack()))); newp->dtypeFrom(nodep); newp->expr1p()->dtypeFrom(nodep); // As And might have been to change widths newp->expr2p()->dtypeFrom(nodep); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); return true; } static bool operandShiftSame(const AstNode* nodep) { @@ -243,8 +251,7 @@ private: const AstShiftL* lp = VN_CAST_CONST(np->lhsp(), ShiftL); const AstShiftL* rp = VN_CAST_CONST(np->rhsp(), ShiftL); if (lp && rp) { - return (lp->width() == rp->width() - && lp->lhsp()->width() == rp->lhsp()->width() + return (lp->width() == rp->width() && lp->lhsp()->width() == rp->lhsp()->width() && operandsSame(lp->rhsp(), rp->rhsp())); } } @@ -252,8 +259,7 @@ private: const AstShiftR* lp = VN_CAST_CONST(np->lhsp(), ShiftR); const AstShiftR* rp = VN_CAST_CONST(np->rhsp(), ShiftR); if (lp && rp) { - return (lp->width() == rp->width() - && lp->lhsp()->width() == rp->lhsp()->width() + return (lp->width() == rp->width() && lp->lhsp()->width() == rp->lhsp()->width() && operandsSame(lp->rhsp(), rp->rhsp())); } } @@ -274,26 +280,23 @@ private: && isTPure(nodep->lhsp())); } bool operandIsTwo(const AstNode* nodep) { - return (VN_IS(nodep, Const) - && !VN_CAST_CONST(nodep, Const)->num().isFourState() - && nodep->width() <= VL_QUADSIZE - && VN_CAST_CONST(nodep, Const)->toUQuad()==2); + return (VN_IS(nodep, Const) && !VN_CAST_CONST(nodep, Const)->num().isFourState() + && nodep->width() <= VL_QUADSIZE && VN_CAST_CONST(nodep, Const)->toUQuad() == 2); } bool operandIsTwostate(const AstNode* nodep) { - return (VN_IS(nodep, Const) - && !VN_CAST_CONST(nodep, Const)->num().isFourState()); + return (VN_IS(nodep, Const) && !VN_CAST_CONST(nodep, Const)->num().isFourState()); } bool operandIsPowTwo(const AstNode* nodep) { if (!operandIsTwostate(nodep)) return false; - return (1==VN_CAST_CONST(nodep, Const)->num().countOnes()); + return (1 == VN_CAST_CONST(nodep, Const)->num().countOnes()); } bool operandShiftOp(const AstNodeBiop* nodep) { if (!VN_IS(nodep->rhsp(), Const)) return false; const AstNodeBiop* lhsp = VN_CAST(nodep->lhsp(), NodeBiop); if (!lhsp || !(VN_IS(lhsp, And) || VN_IS(lhsp, Or) || VN_IS(lhsp, Xor))) return false; - if (nodep->width()!=lhsp->width()) return false; - if (nodep->width()!=lhsp->lhsp()->width()) return false; - if (nodep->width()!=lhsp->rhsp()->width()) return false; + if (nodep->width() != lhsp->width()) return false; + if (nodep->width() != lhsp->lhsp()->width()) return false; + if (nodep->width() != lhsp->rhsp()->width()) return false; return true; } bool operandShiftShift(const AstNodeBiop* nodep) { @@ -304,25 +307,24 @@ private: // because bits may be masked in that process, or (b+c) may exceed the word width. if (!(VN_IS(nodep->rhsp(), Const) && VN_IS(lhsp->rhsp(), Const))) return false; if (VN_CAST_CONST(nodep->rhsp(), Const)->num().isFourState() - || VN_CAST_CONST(lhsp->rhsp(), Const)->num().isFourState()) return false; - if (nodep->width()!=lhsp->width()) return false; - if (nodep->width()!=lhsp->lhsp()->width()) return false; + || VN_CAST_CONST(lhsp->rhsp(), Const)->num().isFourState()) + return false; + if (nodep->width() != lhsp->width()) return false; + if (nodep->width() != lhsp->lhsp()->width()) return false; return true; } bool operandWordOOB(const AstWordSel* nodep) { // V3Expand may make a arraysel that exceeds the bounds of the array // It was an expression, then got constified. In reality, the WordSel // must be wrapped in a Cond, that will be false. - return (VN_IS(nodep->rhsp(), Const) - && VN_IS(nodep->fromp(), NodeVarRef) + return (VN_IS(nodep->rhsp(), Const) && VN_IS(nodep->fromp(), NodeVarRef) && !VN_CAST_CONST(nodep->fromp(), NodeVarRef)->lvalue() && (static_cast(VN_CAST_CONST(nodep->rhsp(), Const)->toUInt()) >= VN_CAST(nodep->fromp(), NodeVarRef)->varp()->widthWords())); } bool operandSelFull(const AstSel* nodep) { - return (VN_IS(nodep->lsbp(), Const) - && VN_IS(nodep->widthp(), Const) - && nodep->lsbConst()==0 + return (VN_IS(nodep->lsbp(), Const) && VN_IS(nodep->widthp(), Const) + && nodep->lsbConst() == 0 && static_cast(nodep->widthConst()) == nodep->fromp()->width()); } bool operandSelExtend(AstSel* nodep) { @@ -330,13 +332,10 @@ private: // SEL(EXTEND(any,width,...),(width-1),0) -> ... // Since select's return unsigned, this is always an extend AstExtend* extendp = VN_CAST(nodep->fromp(), Extend); - if (!(m_doV - && extendp - && VN_IS(nodep->lsbp(), Const) - && VN_IS(nodep->widthp(), Const) - && nodep->lsbConst()==0 - && static_cast(nodep->widthConst()) == extendp->lhsp()->width() - )) return false; + if (!(m_doV && extendp && VN_IS(nodep->lsbp(), Const) && VN_IS(nodep->widthp(), Const) + && nodep->lsbConst() == 0 + && static_cast(nodep->widthConst()) == extendp->lhsp()->width())) + return false; VL_DO_DANGLING(replaceWChild(nodep, extendp->lhsp()), nodep); return true; } @@ -344,18 +343,15 @@ private: // SEL(ADD(a,b),(width-1),0) -> ADD(SEL(a),SEL(b)) // Add or any operation which doesn't care if we discard top bits AstNodeBiop* bip = VN_CAST(nodep->fromp(), NodeBiop); - if (!(m_doV - && bip - && VN_IS(nodep->lsbp(), Const) - && VN_IS(nodep->widthp(), Const) - && nodep->lsbConst()==0 - )) return false; - if (debug()>=9) nodep->dumpTree(cout, "SEL(BI)-in:"); + if (!(m_doV && bip && VN_IS(nodep->lsbp(), Const) && VN_IS(nodep->widthp(), Const) + && nodep->lsbConst() == 0)) + return false; + if (debug() >= 9) nodep->dumpTree(cout, "SEL(BI)-in:"); AstNode* bilhsp = bip->lhsp()->unlinkFrBack(); AstNode* birhsp = bip->rhsp()->unlinkFrBack(); bip->lhsp(new AstSel(nodep->fileline(), bilhsp, 0, nodep->widthConst())); bip->rhsp(new AstSel(nodep->fileline(), birhsp, 0, nodep->widthConst())); - if (debug()>=9) bip->dumpTree(cout, "SEL(BI)-ou:"); + if (debug() >= 9) bip->dumpTree(cout, "SEL(BI)-ou:"); VL_DO_DANGLING(replaceWChild(nodep, bip), nodep); return true; } @@ -364,26 +360,26 @@ private: // becomes thought other optimizations // SEL(SHIFTR({a},{b}),{lsb},{width}) -> SEL({a},{lsb+b},{width}) AstShiftR* shiftp = VN_CAST(nodep->fromp(), ShiftR); - if (!(m_doV - && shiftp - && VN_IS(shiftp->rhsp(), Const) - && VN_IS(nodep->lsbp(), Const) - && VN_IS(nodep->widthp(), Const) - )) return false; + if (!(m_doV && shiftp && VN_IS(shiftp->rhsp(), Const) && VN_IS(nodep->lsbp(), Const) + && VN_IS(nodep->widthp(), Const))) { + return false; + } AstNode* ap = shiftp->lhsp(); AstConst* bp = VN_CAST(shiftp->rhsp(), Const); AstConst* lp = VN_CAST(nodep->lsbp(), Const); - if (bp->isWide() || bp->num().isFourState() || bp->num().isNegative() - || lp->isWide() || lp->num().isFourState() || lp->num().isNegative()) return false; + if (bp->isWide() || bp->num().isFourState() || bp->num().isNegative() || lp->isWide() + || lp->num().isFourState() || lp->num().isNegative()) { + return false; + } int newLsb = lp->toSInt() + bp->toSInt(); if (newLsb + nodep->widthConst() > ap->width()) return false; // UINFO(9, "SEL(SHIFTR(a,b),l,w) -> SEL(a,l+b,w)\n"); - if (debug()>=9) nodep->dumpTree(cout, "SEL(SH)-in:"); - AstSel* newp = new AstSel(nodep->fileline(), ap->unlinkFrBack(), - newLsb, nodep->widthConst()); + if (debug() >= 9) nodep->dumpTree(cout, "SEL(SH)-in:"); + AstSel* newp + = new AstSel(nodep->fileline(), ap->unlinkFrBack(), newLsb, nodep->widthConst()); newp->dtypeFrom(nodep); - if (debug()>=9) newp->dumpTree(cout, "SEL(SH)-ou:"); + if (debug() >= 9) newp->dumpTree(cout, "SEL(SH)-ou:"); VL_DO_DANGLING(nodep->replaceWith(newp), nodep); return true; } @@ -399,19 +395,19 @@ private: int subsize = smallerp->width(); AstConst* constp = VN_CAST(nodep->lhsp(), Const); if (!constp) return false; - if (!constp->num().isBitsZero(constp->width()-1, subsize)) return false; + if (!constp->num().isBitsZero(constp->width() - 1, subsize)) return false; // - if (debug()>=9) nodep->dumpTree(cout, "BI(EXTEND)-in:"); + if (debug() >= 9) nodep->dumpTree(cout, "BI(EXTEND)-in:"); smallerp->unlinkFrBack(); VL_DO_DANGLING(extendp->unlinkFrBack()->deleteTree(), extendp); // aka nodep->lhsp. nodep->rhsp(smallerp); constp->unlinkFrBack(); - V3Number num (constp, subsize); + V3Number num(constp, subsize); num.opAssign(constp->num()); nodep->lhsp(new AstConst(constp->fileline(), num)); VL_DO_DANGLING(constp->deleteTree(), constp); - if (debug()>=9) nodep->dumpTree(cout, "BI(EXTEND)-ou:"); + if (debug() >= 9) nodep->dumpTree(cout, "BI(EXTEND)-ou:"); return true; } bool operandBiExtendConstOver(const AstNodeBiop* nodep) { @@ -424,7 +420,7 @@ private: int subsize = smallerp->width(); const AstConst* constp = VN_CAST_CONST(nodep->lhsp(), Const); if (!constp) return false; - if (constp->num().isBitsZero(constp->width()-1, subsize)) return false; + if (constp->num().isBitsZero(constp->width() - 1, subsize)) return false; return true; } @@ -453,33 +449,31 @@ private: // Find range of dtype we are selecting from // Similar code in V3Unknown::AstSel bool doit = true; - if (m_warn - && VN_IS(nodep->lsbp(), Const) - && VN_IS(nodep->widthp(), Const) - && doit) { - int maxDeclBit = nodep->declRange().hiMaxSelect()*nodep->declElWidth() - + (nodep->declElWidth()-1); + if (m_warn && VN_IS(nodep->lsbp(), Const) && VN_IS(nodep->widthp(), Const) && doit) { + int maxDeclBit = nodep->declRange().hiMaxSelect() * nodep->declElWidth() + + (nodep->declElWidth() - 1); if (VN_CAST(nodep->lsbp(), Const)->num().isFourState() || VN_CAST(nodep->widthp(), Const)->num().isFourState()) { nodep->v3error("Selection index is constantly unknown or tristated: " - "lsb="<lsbp()->name()<<" width="<widthp()->name()); + "lsb=" + << nodep->lsbp()->name() << " width=" << nodep->widthp()->name()); // Replacing nodep will make a mess above, so we replace the offender replaceZero(nodep->lsbp()); - } - else if (nodep->declRange().ranged() - && (nodep->msbConst() > maxDeclBit - || nodep->lsbConst() > maxDeclBit)) { + } else if (nodep->declRange().ranged() + && (nodep->msbConst() > maxDeclBit || nodep->lsbConst() > maxDeclBit)) { // See also warning in V3Width // Must adjust by element width as declRange() is in number of elements - nodep->v3warn(SELRANGE, "Selection index out of range: " - <<(nodep->msbConst()/nodep->declElWidth()) - <<":"<<(nodep->lsbConst()/nodep->declElWidth()) - <<" outside "<declRange().hiMaxSelect()<<":0" - <<(nodep->declRange().lo()>=0 ? "" - :(" (adjusted +"+cvtToStr(-nodep->declRange().lo()) - +" to account for negative lsb)"))); - UINFO(1," Related Raw index is "<msbConst() - <<":"<lsbConst()<v3warn(SELRANGE, + "Selection index out of range: " + << (nodep->msbConst() / nodep->declElWidth()) << ":" + << (nodep->lsbConst() / nodep->declElWidth()) << " outside " + << nodep->declRange().hiMaxSelect() << ":0" + << (nodep->declRange().lo() >= 0 + ? "" + : (" (adjusted +" + cvtToStr(-nodep->declRange().lo()) + + " to account for negative lsb)"))); + UINFO(1, " Related Raw index is " << nodep->msbConst() << ":" + << nodep->lsbConst() << endl); // Don't replace with zero, we'll do it later } } @@ -490,11 +484,10 @@ private: // For now we just detect constants & simple vars, though it could be more generic if (VN_IS(node1p, Const) && VN_IS(node2p, Const)) { return node1p->sameGateTree(node2p); - } - else if (VN_IS(node1p, VarRef) && VN_IS(node2p, VarRef)) { + } else if (VN_IS(node1p, VarRef) && VN_IS(node2p, VarRef)) { // Avoid comparing widthMin's, which results in lost optimization attempts // If cleanup sameGateTree to be smarter, this can be restored. - //return node1p->sameGateTree(node2p); + // return node1p->sameGateTree(node2p); return node1p->same(node2p); } else { return false; @@ -503,7 +496,7 @@ private: bool ifSameAssign(const AstNodeIf* nodep) { const AstNodeAssign* ifp = VN_CAST_CONST(nodep->ifsp(), NodeAssign); const AstNodeAssign* elsep = VN_CAST_CONST(nodep->elsesp(), NodeAssign); - if (!ifp || ifp->nextp()) return false; // Must be SINGLE statement + if (!ifp || ifp->nextp()) return false; // Must be SINGLE statement if (!elsep || elsep->nextp()) return false; if (ifp->type() != elsep->type()) return false; // Can't mix an assigndly and an assign if (!ifp->lhsp()->sameGateTree(elsep->lhsp())) return false; @@ -520,10 +513,7 @@ private: return true; } bool ifConcatMergeableBiop(const AstNode* nodep) { - return (VN_IS(nodep, And) - || VN_IS(nodep, Or) - || VN_IS(nodep, Xor) - || VN_IS(nodep, Xnor)); + return (VN_IS(nodep, And) || VN_IS(nodep, Or) || VN_IS(nodep, Xor) || VN_IS(nodep, Xnor)); } bool ifAdjacentSel(const AstSel* lhsp, const AstSel* rhsp) { if (!v3Global.opt.oAssemble()) return false; // opt disabled @@ -594,8 +584,9 @@ private: // {a[]&b[] & c[], a[]&b[] & c[]} if (rad && concatMergeable(lp->lhsp(), rp->lhsp())) return true; // {(a[]&b[])&(c[]&d[]), (a[]&b[])&(c[]&d[])} - if (concatMergeable(lp->lhsp(), rp->lhsp()) - && concatMergeable(lp->rhsp(), rp->rhsp())) return true; + if (concatMergeable(lp->lhsp(), rp->lhsp()) && concatMergeable(lp->rhsp(), rp->rhsp())) { + return true; + } return false; } @@ -606,17 +597,17 @@ private: void replaceNum(AstNode* oldp, const V3Number& num) { // Replace oldp node with a constant set to specified value UASSERT(oldp, "Null old"); - UASSERT_OBJ(!(VN_IS(oldp, Const) && !VN_CAST(oldp, Const)->num().isFourState()), - oldp, "Already constant??"); + UASSERT_OBJ(!(VN_IS(oldp, Const) && !VN_CAST(oldp, Const)->num().isFourState()), oldp, + "Already constant??"); AstNode* newp = new AstConst(oldp->fileline(), num); newp->dtypeFrom(oldp); - if (debug()>5) oldp->dumpTree(cout, " const_old: "); - if (debug()>5) newp->dumpTree(cout, " _new: "); + if (debug() > 5) oldp->dumpTree(cout, " const_old: "); + if (debug() > 5) newp->dumpTree(cout, " _new: "); oldp->replaceWith(newp); VL_DO_DANGLING(oldp->deleteTree(), oldp); } void replaceNum(AstNode* nodep, uint32_t val) { - V3Number num (nodep, nodep->width(), val); + V3Number num(nodep, nodep->width(), val); VL_DO_DANGLING(replaceNum(nodep, num), nodep); } void replaceNumSigned(AstNodeBiop* nodep, uint32_t val) { @@ -632,9 +623,7 @@ private: if (m_warn) nodep->v3warn(CMPCONST, "Comparison is constant due to limited range"); VL_DO_DANGLING(replaceNum(nodep, val), nodep); } - void replaceZero(AstNode* nodep) { - VL_DO_DANGLING(replaceNum(nodep, 0), nodep); - } + void replaceZero(AstNode* nodep) { VL_DO_DANGLING(replaceNum(nodep, 0), nodep); } void replaceZeroChkPure(AstNode* nodep, AstNode* checkp) { // For example, "0 * n" -> 0 if n has no side effects // Else strength reduce it to 0 & n. @@ -642,8 +631,7 @@ private: if (isTPure(checkp)) { VL_DO_DANGLING(replaceNum(nodep, 0), nodep); } else { - AstNode* newp = new AstAnd(nodep->fileline(), - new AstConst(nodep->fileline(), 0), + AstNode* newp = new AstAnd(nodep->fileline(), new AstConst(nodep->fileline(), 0), checkp->unlinkFrBack()); newp->dtypeFrom(nodep); nodep->replaceWith(newp); @@ -651,29 +639,29 @@ private: } } void replaceAllOnes(AstNode* nodep) { - V3Number ones (nodep, nodep->width(), 0); + V3Number ones(nodep, nodep->width(), 0); ones.setMask(nodep->width()); VL_DO_DANGLING(replaceNum(nodep, ones), nodep); } void replaceConst(AstNodeUniop* nodep) { - V3Number num (nodep, nodep->width()); + V3Number num(nodep, nodep->width()); nodep->numberOperate(num, VN_CAST(nodep->lhsp(), Const)->num()); - UINFO(4,"UNICONST -> "< " << num << endl); VL_DO_DANGLING(replaceNum(nodep, num), nodep); } void replaceConst(AstNodeBiop* nodep) { - V3Number num (nodep, nodep->width()); + V3Number num(nodep, nodep->width()); nodep->numberOperate(num, VN_CAST(nodep->lhsp(), Const)->num(), VN_CAST(nodep->rhsp(), Const)->num()); - UINFO(4,"BICONST -> "< " << num << endl); VL_DO_DANGLING(replaceNum(nodep, num), nodep); } void replaceConst(AstNodeTriop* nodep) { - V3Number num (nodep, nodep->width()); + V3Number num(nodep, nodep->width()); nodep->numberOperate(num, VN_CAST(nodep->lhsp(), Const)->num(), VN_CAST(nodep->rhsp(), Const)->num(), VN_CAST(nodep->thsp(), Const)->num()); - UINFO(4,"TRICONST -> "< " << num << endl); VL_DO_DANGLING(replaceNum(nodep, num), nodep); } @@ -681,8 +669,8 @@ private: // Replace oldp node with a constant set to specified value UASSERT(oldp, "Null old"); AstNode* newp = new AstConst(oldp->fileline(), AstConst::String(), num); - if (debug()>5) oldp->dumpTree(cout, " const_old: "); - if (debug()>5) newp->dumpTree(cout, " _new: "); + if (debug() > 5) oldp->dumpTree(cout, " const_old: "); + if (debug() > 5) newp->dumpTree(cout, " _new: "); oldp->replaceWith(newp); VL_DO_DANGLING(oldp->deleteTree(), oldp); } @@ -728,7 +716,7 @@ private: void replaceAsv(AstNodeBiop* nodep) { // BIASV(CONSTa, BIASV(CONSTb, c)) -> BIASV( BIASV_CONSTED(a,b), c) // BIASV(SAMEa, BIASV(SAMEb, c)) -> BIASV( BIASV(SAMEa,SAMEb), c) - //nodep->dumpTree(cout, " repAsvConst_old: "); + // nodep->dumpTree(cout, " repAsvConst_old: "); AstNode* ap = nodep->lhsp(); AstNodeBiop* rp = VN_CAST(nodep->rhsp(), NodeBiop); AstNode* bp = rp->lhsp(); @@ -742,23 +730,23 @@ private: rp->lhsp(ap); rp->rhsp(bp); if (VN_IS(rp->lhsp(), Const) && VN_IS(rp->rhsp(), Const)) replaceConst(rp); - //nodep->dumpTree(cout, " repAsvConst_new: "); + // nodep->dumpTree(cout, " repAsvConst_new: "); } void replaceAsvLUp(AstNodeBiop* nodep) { // BIASV(BIASV(CONSTll,lr),r) -> BIASV(CONSTll,BIASV(lr,r)) AstNodeBiop* lp = VN_CAST(nodep->lhsp()->unlinkFrBack(), NodeBiop); AstNode* llp = lp->lhsp()->unlinkFrBack(); AstNode* lrp = lp->rhsp()->unlinkFrBack(); - AstNode* rp = nodep->rhsp()->unlinkFrBack(); + AstNode* rp = nodep->rhsp()->unlinkFrBack(); nodep->lhsp(llp); nodep->rhsp(lp); lp->lhsp(lrp); lp->rhsp(rp); - //nodep->dumpTree(cout, " repAsvLUp_new: "); + // nodep->dumpTree(cout, " repAsvLUp_new: "); } void replaceAsvRUp(AstNodeBiop* nodep) { // BIASV(l,BIASV(CONSTrl,rr)) -> BIASV(CONSTrl,BIASV(l,rr)) - AstNode* lp = nodep->lhsp()->unlinkFrBack(); + AstNode* lp = nodep->lhsp()->unlinkFrBack(); AstNodeBiop* rp = VN_CAST(nodep->rhsp()->unlinkFrBack(), NodeBiop); AstNode* rlp = rp->lhsp()->unlinkFrBack(); AstNode* rrp = rp->rhsp()->unlinkFrBack(); @@ -766,7 +754,7 @@ private: nodep->rhsp(rp); rp->lhsp(lp); rp->rhsp(rrp); - //nodep->dumpTree(cout, " repAsvRUp_new: "); + // nodep->dumpTree(cout, " repAsvRUp_new: "); } void replaceAndOr(AstNodeBiop* nodep) { // OR (AND (CONSTll,lr), AND(CONSTrl==ll,rr)) -> AND (CONSTll, OR(lr,rr)) @@ -797,7 +785,7 @@ private: } else { nodep->v3fatalSrc("replaceAndOr on something operandAndOrSame shouldn't have matched"); } - //nodep->dumpTree(cout, " repAndOr_new: "); + // nodep->dumpTree(cout, " repAndOr_new: "); } void replaceShiftSame(AstNodeBiop* nodep) { // Or(Shift(ll,CONSTlr),Shift(rl,CONSTrr==lr)) -> Shift(Or(ll,rl),CONSTlr) @@ -815,7 +803,7 @@ private: nodep->rhsp(rlp); VL_DO_DANGLING(rp->deleteTree(), rp); VL_DO_DANGLING(rrp->deleteTree(), rrp); - //nodep->dumpTree(cout, " repShiftSame_new: "); + // nodep->dumpTree(cout, " repShiftSame_new: "); } void replaceConcatSel(AstConcat* nodep) { // {a[1], a[0]} -> a[1:0] @@ -828,9 +816,10 @@ private: UASSERT_OBJ((rstart + rwidth) == lstart, nodep, "tried to merge two selects which are not adjacent"); - AstSel* newselp = new AstSel(lselp->fromp()->fileline(), - rselp->fromp()->cloneTree(false), rstart, lwidth+rwidth); - UINFO(5, "merged two adjacent sel "<fromp()->fileline(), rselp->fromp()->cloneTree(false), + rstart, lwidth + rwidth); + UINFO(5, "merged two adjacent sel " << lselp << " and " << rselp << " to one " << newselp + << endl); nodep->replaceWith(newselp); VL_DO_DANGLING(lselp->deleteTree(), lselp); @@ -851,92 +840,103 @@ private: lp->lhsp()->replaceWith(newlp); lp->rhsp()->replaceWith(newrp); lp->dtypeChgWidthSigned(newlp->width(), newlp->width(), AstNumeric::UNSIGNED); - UINFO(5, "merged "<< nodep <unlinkFrBack()->deleteTree(), rp); - nodep->replaceWith(lp->unlinkFrBack()); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(lp->unlinkFrBack()); + VL_DO_DANGLING(nodep->deleteTree(), nodep); iterate(lp->lhsp()); iterate(lp->rhsp()); - } else nodep->v3fatalSrc("tried to merge two Concat which are not adjacent"); + } else { + nodep->v3fatalSrc("tried to merge two Concat which are not adjacent"); + } } void replaceExtend(AstNode* nodep, AstNode* arg0p) { // -> EXTEND(nodep) // like a AstExtend{$rhsp}, but we need to set the width correctly from base node arg0p->unlinkFrBack(); AstNode* newp = (VN_IS(nodep, ExtendS) - ? static_cast(new AstExtendS(nodep->fileline(), arg0p)) - : static_cast(new AstExtend (nodep->fileline(), arg0p))); + ? static_cast(new AstExtendS(nodep->fileline(), arg0p)) + : static_cast(new AstExtend(nodep->fileline(), arg0p))); newp->dtypeFrom(nodep); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } void replacePowShift(AstNodeBiop* nodep) { // Pow or PowS - UINFO(5,"POW(2,b)->SHIFTL(1,b) "<SHIFTL(1,b) " << nodep << endl); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); - AstShiftL* newp = new AstShiftL(nodep->fileline(), - new AstConst(nodep->fileline(), 1), - rhsp); + AstShiftL* newp + = new AstShiftL(nodep->fileline(), new AstConst(nodep->fileline(), 1), rhsp); newp->dtypeFrom(nodep); newp->lhsp()->dtypeFrom(nodep); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } void replaceMulShift(AstMul* nodep) { // Mul, but not MulS as not simple shift - UINFO(5,"MUL(2^n,b)->SHIFTL(b,n) "<lhsp(), Const)->num().mostSetBitP1()-1; // 2^n->n+1 + UINFO(5, "MUL(2^n,b)->SHIFTL(b,n) " << nodep << endl); + int amount = VN_CAST(nodep->lhsp(), Const)->num().mostSetBitP1() - 1; // 2^n->n+1 AstNode* opp = nodep->rhsp()->unlinkFrBack(); - AstShiftL* newp = new AstShiftL(nodep->fileline(), - opp, new AstConst(nodep->fileline(), amount)); + AstShiftL* newp + = new AstShiftL(nodep->fileline(), opp, new AstConst(nodep->fileline(), amount)); newp->dtypeFrom(nodep); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } void replaceDivShift(AstDiv* nodep) { // Mul, but not MulS as not simple shift - UINFO(5,"DIV(b,2^n)->SHIFTR(b,n) "<rhsp(), Const)->num().mostSetBitP1()-1; // 2^n->n+1 + UINFO(5, "DIV(b,2^n)->SHIFTR(b,n) " << nodep << endl); + int amount = VN_CAST(nodep->rhsp(), Const)->num().mostSetBitP1() - 1; // 2^n->n+1 AstNode* opp = nodep->lhsp()->unlinkFrBack(); - AstShiftR* newp = new AstShiftR(nodep->fileline(), - opp, new AstConst(nodep->fileline(), amount)); + AstShiftR* newp + = new AstShiftR(nodep->fileline(), opp, new AstConst(nodep->fileline(), amount)); newp->dtypeFrom(nodep); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } void replaceModAnd(AstModDiv* nodep) { // Mod, but not ModS as not simple shift - UINFO(5,"MOD(b,2^n)->AND(b,2^n-1) "<rhsp(), Const)->num().mostSetBitP1()-1; // 2^n->n+1 + UINFO(5, "MOD(b,2^n)->AND(b,2^n-1) " << nodep << endl); + int amount = VN_CAST(nodep->rhsp(), Const)->num().mostSetBitP1() - 1; // 2^n->n+1 V3Number mask(nodep, nodep->width()); mask.setMask(amount); AstNode* opp = nodep->lhsp()->unlinkFrBack(); - AstAnd* newp = new AstAnd(nodep->fileline(), - opp, new AstConst(nodep->fileline(), mask)); + AstAnd* newp = new AstAnd(nodep->fileline(), opp, new AstConst(nodep->fileline(), mask)); newp->dtypeFrom(nodep); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } void replaceShiftOp(AstNodeBiop* nodep) { - UINFO(5,"SHIFT(AND(a,b),CONST)->AND(SHIFT(a,CONST),SHIFT(b,CONST)) "<AND(SHIFT(a,CONST),SHIFT(b,CONST)) " << nodep << endl); AstNRelinker handle; nodep->unlinkFrBack(&handle); - AstNodeBiop* lhsp = VN_CAST(nodep->lhsp(), NodeBiop); lhsp->unlinkFrBack(); + AstNodeBiop* lhsp = VN_CAST(nodep->lhsp(), NodeBiop); + lhsp->unlinkFrBack(); AstNode* shiftp = nodep->rhsp()->unlinkFrBack(); AstNode* ap = lhsp->lhsp()->unlinkFrBack(); AstNode* bp = lhsp->rhsp()->unlinkFrBack(); AstNodeBiop* shift1p = nodep; AstNodeBiop* shift2p = nodep->cloneTree(true); - shift1p->lhsp(ap); shift1p->rhsp(shiftp->cloneTree(true)); - shift2p->lhsp(bp); shift2p->rhsp(shiftp); + shift1p->lhsp(ap); + shift1p->rhsp(shiftp->cloneTree(true)); + shift2p->lhsp(bp); + shift2p->rhsp(shiftp); AstNodeBiop* newp = lhsp; - newp->lhsp(shift1p); newp->rhsp(shift2p); + newp->lhsp(shift1p); + newp->rhsp(shift2p); handle.relink(newp); iterate(newp); // Further reduce, either node may have more reductions. } void replaceShiftShift(AstNodeBiop* nodep) { - UINFO(4,"SHIFT(SHIFT(a,s1),s2)->SHIFT(a,ADD(s1,s2)) "<=9) nodep->dumpTree(cout, " repShiftShift_old: "); - AstNodeBiop* lhsp = VN_CAST(nodep->lhsp(), NodeBiop); lhsp->unlinkFrBack(); + UINFO(4, "SHIFT(SHIFT(a,s1),s2)->SHIFT(a,ADD(s1,s2)) " << nodep << endl); + if (debug() >= 9) nodep->dumpTree(cout, " repShiftShift_old: "); + AstNodeBiop* lhsp = VN_CAST(nodep->lhsp(), NodeBiop); + lhsp->unlinkFrBack(); AstNode* ap = lhsp->lhsp()->unlinkFrBack(); AstNode* shift1p = lhsp->rhsp()->unlinkFrBack(); AstNode* shift2p = nodep->rhsp()->unlinkFrBack(); // Shift1p and shift2p may have different sizes, both are // self-determined so sum with infinite width - if (nodep->type()==lhsp->type()) { + if (nodep->type() == lhsp->type()) { int shift1 = VN_CAST(shift1p, Const)->toUInt(); int shift2 = VN_CAST(shift2p, Const)->toUInt(); - int newshift = shift1+shift2; + int newshift = shift1 + shift2; VL_DO_DANGLING(shift1p->deleteTree(), shift1p); VL_DO_DANGLING(shift2p->deleteTree(), shift2p); nodep->lhsp(ap); @@ -945,28 +945,28 @@ private: } else { // We know shift amounts are constant, but might be a mixed left/right shift int shift1 = VN_CAST(shift1p, Const)->toUInt(); - if (VN_IS(lhsp, ShiftR)) shift1=-shift1; + if (VN_IS(lhsp, ShiftR)) shift1 = -shift1; int shift2 = VN_CAST(shift2p, Const)->toUInt(); - if (VN_IS(nodep, ShiftR)) shift2=-shift2; - int newshift = shift1+shift2; + if (VN_IS(nodep, ShiftR)) shift2 = -shift2; + int newshift = shift1 + shift2; VL_DO_DANGLING(shift1p->deleteTree(), shift1p); VL_DO_DANGLING(shift2p->deleteTree(), shift2p); AstNode* newp; - V3Number mask1 (nodep, nodep->width()); - V3Number ones (nodep, nodep->width()); + V3Number mask1(nodep, nodep->width()); + V3Number ones(nodep, nodep->width()); ones.setMask(nodep->width()); - if (shift1<0) { + if (shift1 < 0) { mask1.opShiftR(ones, V3Number(nodep, VL_IDATASIZE, -shift1)); } else { mask1.opShiftL(ones, V3Number(nodep, VL_IDATASIZE, shift1)); } - V3Number mask (nodep, nodep->width()); - if (shift2<0) { + V3Number mask(nodep, nodep->width()); + if (shift2 < 0) { mask.opShiftR(mask1, V3Number(nodep, VL_IDATASIZE, -shift2)); } else { mask.opShiftL(mask1, V3Number(nodep, VL_IDATASIZE, shift2)); } - if (newshift<0) { + if (newshift < 0) { newp = new AstShiftR(nodep->fileline(), ap, new AstConst(nodep->fileline(), -newshift)); } else { @@ -974,12 +974,11 @@ private: new AstConst(nodep->fileline(), newshift)); } newp->dtypeFrom(nodep); - newp = new AstAnd(nodep->fileline(), - newp, - new AstConst(nodep->fileline(), mask)); + newp = new AstAnd(nodep->fileline(), newp, new AstConst(nodep->fileline(), mask)); newp->dtypeFrom(nodep); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); - //newp->dumpTree(cout, " repShiftShift_new: "); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); + // newp->dumpTree(cout, " repShiftShift_new: "); iterate(newp); // Further reduce, either node may have more reductions. } VL_DO_DANGLING(lhsp->deleteTree(), lhsp); @@ -989,28 +988,39 @@ private: // Multiple assignments to sequential bits can be concated // ASSIGN(SEL(a),aq), ASSIGN(SEL(a+1),bq) -> ASSIGN(SEL(a:b),CONCAT(aq,bq) // ie. assign var[2]=a, assign var[3]=b -> assign var[3:2]={b,a} - if (!m_modp) return false; // Skip if we're not const'ing an entire module (IE doing only one assign, etc) - AstSel* sel1p = VN_CAST(nodep->lhsp(), Sel); if (!sel1p) return false; - AstNodeAssign* nextp = VN_CAST(nodep->nextp(), NodeAssign); if (!nextp) return false; + + // Skip if we're not const'ing an entire module (IE doing only one assign, etc) + if (!m_modp) return false; + AstSel* sel1p = VN_CAST(nodep->lhsp(), Sel); + if (!sel1p) return false; + AstNodeAssign* nextp = VN_CAST(nodep->nextp(), NodeAssign); + if (!nextp) return false; if (nodep->type() != nextp->type()) return false; - AstSel* sel2p = VN_CAST(nextp->lhsp(), Sel); if (!sel2p) return false; - AstVarRef* varref1p = VN_CAST(sel1p->fromp(), VarRef); if (!varref1p) return false; - AstVarRef* varref2p = VN_CAST(sel2p->fromp(), VarRef); if (!varref2p) return false; + AstSel* sel2p = VN_CAST(nextp->lhsp(), Sel); + if (!sel2p) return false; + AstVarRef* varref1p = VN_CAST(sel1p->fromp(), VarRef); + if (!varref1p) return false; + AstVarRef* varref2p = VN_CAST(sel2p->fromp(), VarRef); + if (!varref2p) return false; if (!varref1p->sameGateTree(varref2p)) return false; - AstConst* con1p = VN_CAST(sel1p->lsbp(), Const); if (!con1p) return false; - AstConst* con2p = VN_CAST(sel2p->lsbp(), Const); if (!con2p) return false; + AstConst* con1p = VN_CAST(sel1p->lsbp(), Const); + if (!con1p) return false; + AstConst* con2p = VN_CAST(sel2p->lsbp(), Const); + if (!con2p) return false; // We need to make sure there's no self-references involved in either // assignment. For speed, we only look 3 deep, then give up. if (!varNotReferenced(nodep->rhsp(), varref1p->varp())) return false; if (!varNotReferenced(nextp->rhsp(), varref2p->varp())) return false; // Swap? - if (( con1p->toSInt() != con2p->toSInt() + sel2p->width()) - &&(con2p->toSInt() != con1p->toSInt() + sel1p->width())) return false; + if ((con1p->toSInt() != con2p->toSInt() + sel2p->width()) + && (con2p->toSInt() != con1p->toSInt() + sel1p->width())) { + return false; + } bool lsbFirstAssign = (con1p->toUInt() < con2p->toUInt()); - UINFO(4,"replaceAssignMultiSel "<dumpTree(cout, "comb1: "); - //nextp->dumpTree(cout, "comb2: "); + UINFO(4, "replaceAssignMultiSel " << nodep << endl); + UINFO(4, " && " << nextp << endl); + // nodep->dumpTree(cout, "comb1: "); + // nextp->dumpTree(cout, "comb2: "); AstNode* rhs1p = nodep->rhsp()->unlinkFrBack(); AstNode* rhs2p = nextp->rhsp()->unlinkFrBack(); AstNode* newp; @@ -1023,30 +1033,29 @@ private: sel2p->lsbConst(), sel1p->width() + sel2p->width()), new AstConcat(rhs1p->fileline(), rhs1p, rhs2p)); } - //pnewp->dumpTree(cout, "conew: "); + // pnewp->dumpTree(cout, "conew: "); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); VL_DO_DANGLING(nextp->unlinkFrBack()->deleteTree(), nextp); return true; } - bool varNotReferenced(AstNode* nodep, AstVar* varp, int level=0) { + bool varNotReferenced(AstNode* nodep, AstVar* varp, int level = 0) { // Return true if varp never referenced under node. // Return false if referenced, or tree too deep to be worth it, or side effects if (!nodep) return true; - if (level>2) return false; + if (level > 2) return false; if (nodep->isPure()) return false; // For example a $fgetc can't be reordered - if (VN_IS(nodep, NodeVarRef) && VN_CAST(nodep, NodeVarRef)->varp()==varp) return false; - return (varNotReferenced(nodep->nextp(), varp, level+1) - && varNotReferenced(nodep->op1p(), varp, level+1) - && varNotReferenced(nodep->op2p(), varp, level+1) - && varNotReferenced(nodep->op3p(), varp, level+1) - && varNotReferenced(nodep->op4p(), varp, level+1)); + if (VN_IS(nodep, NodeVarRef) && VN_CAST(nodep, NodeVarRef)->varp() == varp) return false; + return (varNotReferenced(nodep->nextp(), varp, level + 1) + && varNotReferenced(nodep->op1p(), varp, level + 1) + && varNotReferenced(nodep->op2p(), varp, level + 1) + && varNotReferenced(nodep->op3p(), varp, level + 1) + && varNotReferenced(nodep->op4p(), varp, level + 1)); } bool replaceNodeAssign(AstNodeAssign* nodep) { - if (VN_IS(nodep->lhsp(), VarRef) - && VN_IS(nodep->rhsp(), VarRef) + if (VN_IS(nodep->lhsp(), VarRef) && VN_IS(nodep->rhsp(), VarRef) && VN_CAST(nodep->lhsp(), VarRef)->sameNoLvalue(VN_CAST(nodep->rhsp(), VarRef)) && !VN_IS(nodep, AssignDly)) { // X = X. Quite pointless, though X <= X may override another earlier assignment @@ -1057,13 +1066,12 @@ private: VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); return true; } - } - else if (m_doV && VN_IS(nodep->lhsp(), Concat)) { + } else if (m_doV && VN_IS(nodep->lhsp(), Concat)) { bool need_temp = false; if (m_warn && !VN_IS(nodep, AssignDly)) { // Is same var on LHS and RHS? // Note only do this (need user4) when m_warn, which is // done as unique visitor - AstUser4InUse m_inuser4; + AstUser4InUse m_inuser4; ConstVarMarkVisitor mark(nodep->lhsp()); ConstVarFindVisitor find(nodep->rhsp()); if (find.found()) need_temp = true; @@ -1071,32 +1079,32 @@ private: if (need_temp) { // The first time we constify, there may be the same variable on the LHS // and RHS. In that case, we must use temporaries, or {a,b}={b,a} will break. - UINFO(4," ASSITEMP "< ASSIGN(temp1,SEL(rhs,{size})), // ASSIGN(temp2,SEL(newrhs,{size})) // ASSIGN(lc1,temp1), // ASSIGN(lc2,temp2) } else { - UINFO(4," ASSI "< ASSIGN(lc1,SEL(rhs,{size})), // ASSIGN(lc2,SEL(newrhs,{size})) } - if (debug()>=9) nodep->dumpTree(cout, " Ass_old: "); + if (debug() >= 9) nodep->dumpTree(cout, " Ass_old: "); // Unlink the stuff AstNode* lc1p = VN_CAST(nodep->lhsp(), Concat)->lhsp()->unlinkFrBack(); AstNode* lc2p = VN_CAST(nodep->lhsp(), Concat)->rhsp()->unlinkFrBack(); AstNode* conp = VN_CAST(nodep->lhsp(), Concat)->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); - AstNode* rhs2p = rhsp->cloneTree(false); + AstNode* rhs2p = rhsp->cloneTree(false); // Calc widths int lsb2 = 0; - int msb2 = lsb2+lc2p->width()-1; - int lsb1 = msb2+1; - int msb1 = lsb1+lc1p->width()-1; - UASSERT_OBJ(msb1 == (conp->width()-1), nodep, "Width calc mismatch"); + int msb2 = lsb2 + lc2p->width() - 1; + int lsb1 = msb2 + 1; + int msb1 = lsb1 + lc1p->width() - 1; + UASSERT_OBJ(msb1 == (conp->width() - 1), nodep, "Width calc mismatch"); // Form ranges - AstSel* sel1p = new AstSel(conp->fileline(), rhsp, lsb1, msb1-lsb1+1); - AstSel* sel2p = new AstSel(conp->fileline(), rhs2p, lsb2, msb2-lsb2+1); + AstSel* sel1p = new AstSel(conp->fileline(), rhsp, lsb1, msb1 - lsb1 + 1); + AstSel* sel2p = new AstSel(conp->fileline(), rhs2p, lsb2, msb2 - lsb2 + 1); // Make new assigns of same flavor as old one //*** Not cloneTree; just one node. AstNode* newp = NULL; @@ -1111,30 +1119,26 @@ private: UASSERT_OBJ(m_modp, nodep, "Not under module"); // We could create just one temp variable, but we'll get better optimization // if we make one per term. - string name1 = (string("__Vconcswap")+cvtToStr(m_modp->varNumGetInc())); - string name2 = (string("__Vconcswap")+cvtToStr(m_modp->varNumGetInc())); + string name1 = (string("__Vconcswap") + cvtToStr(m_modp->varNumGetInc())); + string name2 = (string("__Vconcswap") + cvtToStr(m_modp->varNumGetInc())); AstVar* temp1p = new AstVar(sel1p->fileline(), AstVarType::BLOCKTEMP, name1, - VFlagLogicPacked(), msb1-lsb1+1); + VFlagLogicPacked(), msb1 - lsb1 + 1); AstVar* temp2p = new AstVar(sel2p->fileline(), AstVarType::BLOCKTEMP, name2, - VFlagLogicPacked(), msb2-lsb2+1); + VFlagLogicPacked(), msb2 - lsb2 + 1); m_modp->addStmtp(temp1p); m_modp->addStmtp(temp2p); - AstNodeAssign* asn1ap - = VN_CAST(nodep->cloneType - (new AstVarRef(sel1p->fileline(), temp1p, true), - sel1p), NodeAssign); - AstNodeAssign* asn2ap - = VN_CAST(nodep->cloneType - (new AstVarRef(sel2p->fileline(), temp2p, true), - sel2p), NodeAssign); - AstNodeAssign* asn1bp - = VN_CAST(nodep->cloneType - (lc1p, new AstVarRef(sel1p->fileline(), temp1p, false)), - NodeAssign); - AstNodeAssign* asn2bp - = VN_CAST(nodep->cloneType - (lc2p, new AstVarRef(sel2p->fileline(), temp2p, false)), - NodeAssign); + AstNodeAssign* asn1ap = VN_CAST( + nodep->cloneType(new AstVarRef(sel1p->fileline(), temp1p, true), sel1p), + NodeAssign); + AstNodeAssign* asn2ap = VN_CAST( + nodep->cloneType(new AstVarRef(sel2p->fileline(), temp2p, true), sel2p), + NodeAssign); + AstNodeAssign* asn1bp = VN_CAST( + nodep->cloneType(lc1p, new AstVarRef(sel1p->fileline(), temp1p, false)), + NodeAssign); + AstNodeAssign* asn2bp = VN_CAST( + nodep->cloneType(lc2p, new AstVarRef(sel2p->fileline(), temp2p, false)), + NodeAssign); asn1ap->dtypeFrom(temp1p); asn1bp->dtypeFrom(temp1p); asn2ap->dtypeFrom(temp2p); @@ -1145,20 +1149,19 @@ private: newp = AstNode::addNext(newp, asn1bp); newp = AstNode::addNext(newp, asn2bp); } - if (debug()>=9 && newp) newp->dumpTreeAndNext(cout, " _new: "); + if (debug() >= 9 && newp) newp->dumpTreeAndNext(cout, " _new: "); nodep->addNextHere(newp); // Cleanup VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); VL_DO_DANGLING(conp->deleteTree(), conp); // Further reduce, either node may have more reductions. return true; - } - else if (m_doV && VN_IS(nodep->rhsp(), StreamR)) { + } else if (m_doV && VN_IS(nodep->rhsp(), StreamR)) { // The right-streaming operator on rhs of assignment does not // change the order of bits. Eliminate stream but keep its lhsp // Unlink the stuff - AstNode* srcp = VN_CAST(nodep->rhsp(), StreamR)->lhsp()->unlinkFrBack(); - AstNode* sizep = VN_CAST(nodep->rhsp(), StreamR)->rhsp()->unlinkFrBack(); + AstNode* srcp = VN_CAST(nodep->rhsp(), StreamR)->lhsp()->unlinkFrBack(); + AstNode* sizep = VN_CAST(nodep->rhsp(), StreamR)->rhsp()->unlinkFrBack(); AstNode* streamp = VN_CAST(nodep->rhsp(), StreamR)->unlinkFrBack(); nodep->rhsp(srcp); // Cleanup @@ -1166,41 +1169,38 @@ private: VL_DO_DANGLING(streamp->deleteTree(), streamp); // Further reduce, any of the nodes may have more reductions. return true; - } - else if (m_doV && VN_IS(nodep->lhsp(), StreamL)) { + } else if (m_doV && VN_IS(nodep->lhsp(), StreamL)) { // Push the stream operator to the rhs of the assignment statement int dWidth = VN_CAST(nodep->lhsp(), StreamL)->lhsp()->width(); int sWidth = nodep->rhsp()->width(); // Unlink the stuff - AstNode* dstp = VN_CAST(nodep->lhsp(), StreamL)->lhsp()->unlinkFrBack(); + AstNode* dstp = VN_CAST(nodep->lhsp(), StreamL)->lhsp()->unlinkFrBack(); AstNode* streamp = VN_CAST(nodep->lhsp(), StreamL)->unlinkFrBack(); - AstNode* srcp = nodep->rhsp()->unlinkFrBack(); + AstNode* srcp = nodep->rhsp()->unlinkFrBack(); // Connect the rhs to the stream operator and update its width VN_CAST(streamp, StreamL)->lhsp(srcp); - streamp->dtypeSetLogicUnsized(srcp->width(), srcp->widthMin(), - AstNumeric::UNSIGNED); + streamp->dtypeSetLogicUnsized(srcp->width(), srcp->widthMin(), AstNumeric::UNSIGNED); // Shrink the RHS if necessary if (sWidth > dWidth) { - streamp = new AstSel(streamp->fileline(), streamp, sWidth-dWidth, dWidth); + streamp = new AstSel(streamp->fileline(), streamp, sWidth - dWidth, dWidth); } // Link the nodes back in nodep->lhsp(dstp); nodep->rhsp(streamp); return true; - } - else if (m_doV && VN_IS(nodep->lhsp(), StreamR)) { + } else if (m_doV && VN_IS(nodep->lhsp(), StreamR)) { // The right stream operator on lhs of assignment statement does // not reorder bits. However, if the rhs is wider than the lhs, // then we select bits from the left-most, not the right-most. int dWidth = VN_CAST(nodep->lhsp(), StreamR)->lhsp()->width(); int sWidth = nodep->rhsp()->width(); // Unlink the stuff - AstNode* dstp = VN_CAST(nodep->lhsp(), StreamR)->lhsp()->unlinkFrBack(); - AstNode* sizep = VN_CAST(nodep->lhsp(), StreamR)->rhsp()->unlinkFrBack(); + AstNode* dstp = VN_CAST(nodep->lhsp(), StreamR)->lhsp()->unlinkFrBack(); + AstNode* sizep = VN_CAST(nodep->lhsp(), StreamR)->rhsp()->unlinkFrBack(); AstNode* streamp = VN_CAST(nodep->lhsp(), StreamR)->unlinkFrBack(); - AstNode* srcp = nodep->rhsp()->unlinkFrBack(); + AstNode* srcp = nodep->rhsp()->unlinkFrBack(); if (sWidth > dWidth) { - srcp = new AstSel(streamp->fileline(), srcp, sWidth-dWidth, dWidth); + srcp = new AstSel(streamp->fileline(), srcp, sWidth - dWidth, dWidth); } nodep->lhsp(dstp); nodep->rhsp(srcp); @@ -1209,8 +1209,7 @@ private: VL_DO_DANGLING(streamp->deleteTree(), streamp); // Further reduce, any of the nodes may have more reductions. return true; - } - else if (replaceAssignMultiSel(nodep)) { + } else if (replaceAssignMultiSel(nodep)) { return true; } return false; @@ -1225,25 +1224,25 @@ private: const AstShiftR* shiftp = VN_CAST(VN_CAST_CONST(nodep, And)->rhsp(), ShiftR); if (!VN_IS(shiftp->rhsp(), Const)) return false; if (static_cast(nodep->width()) - <= VN_CAST_CONST(shiftp->rhsp(), Const)->toUInt()) return false; + <= VN_CAST_CONST(shiftp->rhsp(), Const)->toUInt()) { + return false; + } return true; } void replaceBoolShift(AstNode* nodep) { - if (debug()>=9) nodep->dumpTree(cout, " bshft_old: "); + if (debug() >= 9) nodep->dumpTree(cout, " bshft_old: "); AstConst* andConstp = VN_CAST(VN_CAST(nodep, And)->lhsp(), Const); AstNode* fromp = VN_CAST(VN_CAST(nodep, And)->rhsp(), ShiftR)->lhsp()->unlinkFrBack(); - AstConst* shiftConstp = VN_CAST(VN_CAST(VN_CAST(nodep, And)->rhsp(), ShiftR)->rhsp(), - Const); - V3Number val (andConstp, andConstp->width()); + AstConst* shiftConstp + = VN_CAST(VN_CAST(VN_CAST(nodep, And)->rhsp(), ShiftR)->rhsp(), Const); + V3Number val(andConstp, andConstp->width()); val.opShiftL(andConstp->num(), shiftConstp->num()); - AstAnd* newp = new AstAnd(nodep->fileline(), - new AstConst(nodep->fileline(), val), - fromp); + AstAnd* newp = new AstAnd(nodep->fileline(), new AstConst(nodep->fileline(), val), fromp); // widthMin no longer applicable if different C-expanded width newp->dtypeSetLogicSized(nodep->width(), AstNumeric::UNSIGNED); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); - if (debug()>=9) newp->dumpTree(cout, " _new: "); + if (debug() >= 9) newp->dumpTree(cout, " _new: "); } void replaceWithSimulation(AstNode* nodep) { @@ -1251,11 +1250,12 @@ private: // Run it - may be unoptimizable due to large for loop, etc simvis.mainParamEmulate(nodep); if (!simvis.optimizable()) { - AstNode* errorp = simvis.whyNotNodep(); if (!errorp) errorp = nodep; + AstNode* errorp = simvis.whyNotNodep(); + if (!errorp) errorp = nodep; nodep->v3error("Expecting expression to be constant, but can't determine constant for " - <prettyTypeName()<warnOther()<<"... Location of non-constant " - <prettyTypeName()<<": "<prettyTypeName() << endl + << errorp->warnOther() << "... Location of non-constant " + << errorp->prettyTypeName() << ": " << simvis.whyNotMessage()); VL_DO_DANGLING(replaceZero(nodep), nodep); } else { // Fetch the result @@ -1265,8 +1265,9 @@ private: AstNode* newp = valuep->cloneTree(false); newp->dtypeFrom(nodep); newp->fileline(nodep->fileline()); - UINFO(4, "Simulate->"<replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + UINFO(4, "Simulate->" << newp << endl); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } } @@ -1321,11 +1322,10 @@ private: AstNode* ap = nodep->lhsp(); AstNode* bp = bcConcp->lhsp(); // If a+b == 32,64,96 etc, then we want to have a+b together on LHS - if (VL_BITBIT_I(ap->width()+bp->width())==0) return 2; // Transform 2: to abConc - } - else { // abConcp + if (VL_BITBIT_I(ap->width() + bp->width()) == 0) return 2; // Transform 2: to abConc + } else { // abConcp // Unless lhs is already 32 bits due to above, reorder it - if (VL_BITBIT_I(nodep->lhsp()->width())!=0) return 1; // Transform 1: to bcConc + if (VL_BITBIT_I(nodep->lhsp()->width()) != 0) return 1; // Transform 1: to bcConc } return 0; // ok } @@ -1336,14 +1336,14 @@ private: // putting additional CONCATs on the RHS leads to fewer assembler operations. // However, we'll end up with lots of wide moves if we make huge trees // like that, so on 32 bit boundaries, we'll do the opposite form. - UINFO(4,"Move concat: "<1) { + UINFO(4, "Move concat: " << nodep << endl); + if (operandConcatMove(nodep) > 1) { AstNode* ap = nodep->lhsp()->unlinkFrBack(); - AstConcat* bcConcp = VN_CAST(nodep->rhsp(), Concat); bcConcp->unlinkFrBack(); + AstConcat* bcConcp = VN_CAST(nodep->rhsp(), Concat); + bcConcp->unlinkFrBack(); AstNode* bp = bcConcp->lhsp()->unlinkFrBack(); AstNode* cp = bcConcp->rhsp()->unlinkFrBack(); - AstConcat* abConcp = new AstConcat(bcConcp->fileline(), - ap, bp); + AstConcat* abConcp = new AstConcat(bcConcp->fileline(), ap, bp); nodep->lhsp(abConcp); nodep->rhsp(cp); // If bp was a concat, then we have this exact same form again! @@ -1351,12 +1351,12 @@ private: if (operandConcatMove(abConcp)) moveConcat(abConcp); VL_DO_DANGLING(bcConcp->deleteTree(), bcConcp); } else { - AstConcat* abConcp = VN_CAST(nodep->lhsp(), Concat); abConcp->unlinkFrBack(); + AstConcat* abConcp = VN_CAST(nodep->lhsp(), Concat); + abConcp->unlinkFrBack(); AstNode* ap = abConcp->lhsp()->unlinkFrBack(); AstNode* bp = abConcp->rhsp()->unlinkFrBack(); AstNode* cp = nodep->rhsp()->unlinkFrBack(); - AstConcat* bcConcp = new AstConcat(abConcp->fileline(), - bp, cp); + AstConcat* bcConcp = new AstConcat(abConcp->fileline(), bp, cp); nodep->lhsp(ap); nodep->rhsp(bcConcp); if (operandConcatMove(bcConcp)) moveConcat(bcConcp); @@ -1374,25 +1374,22 @@ private: iterateChildren(nodep); } } - virtual void visit(AstPin* nodep) VL_OVERRIDE { - iterateChildren(nodep); - } + virtual void visit(AstPin* nodep) VL_OVERRIDE { iterateChildren(nodep); } void replaceLogEq(AstLogEq* nodep) { // LOGEQ(a,b) => AstLogAnd{AstLogOr{AstLogNot{a},b},AstLogOr{AstLogNot{b},a}} AstNode* lhsp = nodep->lhsp()->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); // Do exactly as IEEE says, might result in extra terms, so in future may do differently - AstLogAnd* newp = new AstLogAnd(nodep->fileline(), - new AstLogOr(nodep->fileline(), - new AstLogNot(nodep->fileline(), lhsp), - rhsp), - new AstLogOr(nodep->fileline(), - new AstLogNot(nodep->fileline(), - rhsp->cloneTree(false)), - lhsp->cloneTree(false))); + AstLogAnd* newp = new AstLogAnd( + nodep->fileline(), + new AstLogOr(nodep->fileline(), new AstLogNot(nodep->fileline(), lhsp), rhsp), + new AstLogOr(nodep->fileline(), + new AstLogNot(nodep->fileline(), rhsp->cloneTree(false)), + lhsp->cloneTree(false))); newp->dtypeFrom(nodep); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } void replaceSelSel(AstSel* nodep) { @@ -1403,26 +1400,22 @@ private: AstNode* lsb1p = nodep->lsbp()->unlinkFrBack(); AstNode* lsb2p = belowp->lsbp()->unlinkFrBack(); // Eliminate lower range - UINFO(4,"Elim Lower range: "<fileline(), - VN_CAST(lsb1p, Const)->toUInt() - + VN_CAST(lsb2p, Const)->toUInt()); + newlsbp = new AstConst(lsb1p->fileline(), VN_CAST(lsb1p, Const)->toUInt() + + VN_CAST(lsb2p, Const)->toUInt()); VL_DO_DANGLING(lsb1p->deleteTree(), lsb1p); VL_DO_DANGLING(lsb2p->deleteTree(), lsb2p); } else { // Width is important, we need the width of the fromp's // expression, not the potentially smaller lsb1p's width - newlsbp = new AstAdd(lsb1p->fileline(), - lsb2p, new AstExtend(lsb1p->fileline(), lsb1p)); + newlsbp + = new AstAdd(lsb1p->fileline(), lsb2p, new AstExtend(lsb1p->fileline(), lsb1p)); newlsbp->dtypeFrom(lsb2p); // Unsigned VN_CAST(newlsbp, Add)->rhsp()->dtypeFrom(lsb2p); } - AstSel* newp = new AstSel(nodep->fileline(), - fromp, - newlsbp, - widthp); + AstSel* newp = new AstSel(nodep->fileline(), fromp, newlsbp, widthp); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } @@ -1434,34 +1427,24 @@ private: AstNode* conRhsp = conp->rhsp(); if (static_cast(nodep->lsbConst()) >= conRhsp->width()) { conLhsp->unlinkFrBack(); - AstSel* newp = new AstSel(nodep->fileline(), - conLhsp, - nodep->lsbConst() - conRhsp->width(), - nodep->widthConst()); + AstSel* newp = new AstSel(nodep->fileline(), conLhsp, + nodep->lsbConst() - conRhsp->width(), nodep->widthConst()); nodep->replaceWith(newp); - } - else if (static_cast(nodep->msbConst()) < conRhsp->width()) { + } else if (static_cast(nodep->msbConst()) < conRhsp->width()) { conRhsp->unlinkFrBack(); - AstSel* newp = new AstSel(nodep->fileline(), - conRhsp, - nodep->lsbConst(), - nodep->widthConst()); + AstSel* newp + = new AstSel(nodep->fileline(), conRhsp, nodep->lsbConst(), nodep->widthConst()); nodep->replaceWith(newp); - } - else { + } else { // Yuk, split between the two conRhsp->unlinkFrBack(); conLhsp->unlinkFrBack(); - AstConcat* newp = new AstConcat - (nodep->fileline(), - new AstSel(nodep->fileline(), - conLhsp, - 0, - nodep->msbConst() - conRhsp->width() + 1), - new AstSel(nodep->fileline(), - conRhsp, - nodep->lsbConst(), - conRhsp->width()-nodep->lsbConst())); + AstConcat* newp + = new AstConcat(nodep->fileline(), + new AstSel(nodep->fileline(), conLhsp, 0, + nodep->msbConst() - conRhsp->width() + 1), + new AstSel(nodep->fileline(), conRhsp, nodep->lsbConst(), + conRhsp->width() - nodep->lsbConst())); nodep->replaceWith(newp); } VL_DO_DANGLING(nodep->deleteTree(), nodep); @@ -1471,36 +1454,43 @@ private: // as SEL's width <= b's width AstReplicate* repp = VN_CAST(nodep->fromp(), Replicate); AstNode* fromp = repp->lhsp(); - AstConst* lsbp = VN_CAST(nodep->lsbp(), Const); if (!lsbp) return false; - AstNode* widthp = nodep->widthp(); if (!VN_IS(widthp, Const)) return false; + AstConst* lsbp = VN_CAST(nodep->lsbp(), Const); + if (!lsbp) return false; + AstNode* widthp = nodep->widthp(); + if (!VN_IS(widthp, Const)) return false; UASSERT_OBJ(fromp->width(), nodep, "Not widthed"); if ((lsbp->toUInt() / fromp->width()) - != ((lsbp->toUInt()+nodep->width()-1) / fromp->width())) return false; + != ((lsbp->toUInt() + nodep->width() - 1) / fromp->width())) { + return false; + } // fromp->unlinkFrBack(); widthp->unlinkFrBack(); - AstSel* newp = new AstSel(nodep->fileline(), - fromp, - new AstConst(lsbp->fileline(), lsbp->toUInt() % fromp->width()), - widthp); + AstSel* newp + = new AstSel(nodep->fileline(), fromp, + new AstConst(lsbp->fileline(), lsbp->toUInt() % fromp->width()), widthp); newp->dtypeFrom(nodep); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); return true; } bool operandRepRep(AstReplicate* nodep) { // REPLICATE(REPLICATE2(from2,cnt2),cnt1) => REPLICATE(from2,(cnt1+cnt2)) AstReplicate* rep2p = VN_CAST(nodep->lhsp(), Replicate); AstNode* from2p = rep2p->lhsp(); - AstConst* cnt1p = VN_CAST(nodep->rhsp(), Const); if (!cnt1p) return false; - AstConst* cnt2p = VN_CAST(rep2p->rhsp(), Const); if (!cnt2p) return false; + AstConst* cnt1p = VN_CAST(nodep->rhsp(), Const); + if (!cnt1p) return false; + AstConst* cnt2p = VN_CAST(rep2p->rhsp(), Const); + if (!cnt2p) return false; // from2p->unlinkFrBack(); cnt1p->unlinkFrBack(); cnt2p->unlinkFrBack(); - AstReplicate* newp = new AstReplicate(nodep->fileline(), - from2p, cnt1p->toUInt()*cnt2p->toUInt()); + AstReplicate* newp + = new AstReplicate(nodep->fileline(), from2p, cnt1p->toUInt() * cnt2p->toUInt()); newp->dtypeFrom(nodep); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); return true; } bool operandConcatSame(AstConcat* nodep) { @@ -1508,8 +1498,10 @@ private: // CONCAT(REP(fromp,cnt1),fromp) -> REPLICATE(fromp,cnt1+1) // CONCAT(fromp,REP(fromp,cnt1)) -> REPLICATE(fromp,1+cnt1) // CONCAT(REP(fromp,cnt1),REP(fromp,cnt2)) -> REPLICATE(fromp,cnt1+cnt2) - AstNode* from1p = nodep->lhsp(); uint32_t cnt1 = 1; - AstNode* from2p = nodep->rhsp(); uint32_t cnt2 = 1; + AstNode* from1p = nodep->lhsp(); + uint32_t cnt1 = 1; + AstNode* from2p = nodep->rhsp(); + uint32_t cnt2 = 1; if (VN_IS(from1p, Replicate)) { AstConst* cnt1p = VN_CAST(VN_CAST(from1p, Replicate)->rhsp(), Const); if (!cnt1p) return false; @@ -1525,9 +1517,10 @@ private: if (!operandsSame(from1p, from2p)) return false; // from1p->unlinkFrBack(); - AstReplicate* newp = new AstReplicate(nodep->fileline(), from1p, cnt1+cnt2); + AstReplicate* newp = new AstReplicate(nodep->fileline(), from1p, cnt1 + cnt2); newp->dtypeFrom(nodep); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); return true; } void replaceSelIntoBiop(AstSel* nodep) { @@ -1540,12 +1533,12 @@ private: AstNode* bilhsp = fromp->lhsp()->unlinkFrBack(); AstNode* birhsp = fromp->rhsp()->unlinkFrBack(); // - fromp->lhsp(new AstSel(nodep->fileline(), - bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true))); - fromp->rhsp(new AstSel(nodep->fileline(), - birhsp, lsbp, widthp)); + fromp->lhsp( + new AstSel(nodep->fileline(), bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true))); + fromp->rhsp(new AstSel(nodep->fileline(), birhsp, lsbp, widthp)); fromp->dtypeFrom(nodep); - nodep->replaceWith(fromp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(fromp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } void replaceSelIntoUniop(AstSel* nodep) { // SEL(NOT(a),1,bit) => NOT(SEL(a,bit)) @@ -1556,10 +1549,10 @@ private: // AstNode* bilhsp = fromp->lhsp()->unlinkFrBack(); // - fromp->lhsp(new AstSel(nodep->fileline(), - bilhsp, lsbp, widthp)); + fromp->lhsp(new AstSel(nodep->fileline(), bilhsp, lsbp, widthp)); fromp->dtypeFrom(nodep); - nodep->replaceWith(fromp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(fromp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } virtual void visit(AstAttrOf* nodep) VL_OVERRIDE { @@ -1587,8 +1580,8 @@ private: nodep->replaceWith(fromp); if (VN_IS(fromp->dtypep()->skipRefp(), NodeArrayDType)) { // Strip off array to find what array references - fromp->dtypeFrom(VN_CAST(fromp->dtypep()->skipRefp(), - NodeArrayDType)->subDTypep()); + fromp->dtypeFrom( + VN_CAST(fromp->dtypep()->skipRefp(), NodeArrayDType)->subDTypep()); } VL_DO_DANGLING(nodep->deleteTree(), nodep); } @@ -1600,7 +1593,7 @@ private: UASSERT_OBJ(nodep->varp(), nodep, "Not linked"); bool did = false; if (m_doV && nodep->varp()->valuep() && !m_attrp) { - //if (debug()) valuep->dumpTree(cout, " visitvaref: "); + // if (debug()) valuep->dumpTree(cout, " visitvaref: "); iterateAndNextNull(nodep->varp()->valuep()); // May change nodep->varp()->valuep() AstNode* valuep = nodep->varp()->valuep(); if (!nodep->lvalue() @@ -1609,42 +1602,39 @@ private: && v3Global.opt.oConst() // Default value, not a "known" constant for this usage && !nodep->varp()->isClassMember() - && !(nodep->varp()->isFuncLocal() - && nodep->varp()->isNonOutput()) - && !nodep->varp()->noSubst() - && !nodep->varp()->isSigPublic()) + && !(nodep->varp()->isFuncLocal() && nodep->varp()->isNonOutput()) + && !nodep->varp()->noSubst() && !nodep->varp()->isSigPublic()) || nodep->varp()->isParam())) { if (operandConst(valuep)) { const V3Number& num = VN_CAST(valuep, Const)->num(); - //UINFO(2,"constVisit "<bitConst(); AstNode* itemp = initarp->getIndexDefaultedValuep(bit); if (VN_IS(itemp, Const)) { const V3Number& num = VN_CAST(itemp, Const)->num(); - //UINFO(2,"constVisit "<backp(), Pin)) { + } else if (m_params && VN_IS(valuep, InitArray) && VN_IS(nodep->backp(), Pin)) { // Allow parameters to pass arrays // Earlier recursion of InitArray made sure each array value is constant // This exception is fairly fragile, i.e. doesn't // support arrays of arrays or other stuff AstNode* newp = valuep->cloneTree(false); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); did = true; } } } if (!did && m_required) { nodep->v3error("Expecting expression to be constant, but variable isn't const: " - <varp()->prettyNameQ()); + << nodep->varp()->prettyNameQ()); } } virtual void visit(AstEnumItemRef* nodep) VL_OVERRIDE { @@ -1652,9 +1642,9 @@ private: UASSERT_OBJ(nodep->itemp(), nodep, "Not linked"); bool did = false; if (nodep->itemp()->valuep()) { - //if (debug()) nodep->itemp()->valuep()->dumpTree(cout, " visitvaref: "); + // if (debug()) nodep->itemp()->valuep()->dumpTree(cout, " visitvaref: "); if (nodep->itemp()->user4()) { - nodep->v3error("Recursive enum value: "<itemp()->prettyNameQ()); + nodep->v3error("Recursive enum value: " << nodep->itemp()->prettyNameQ()); } else { nodep->itemp()->user4(true); iterateAndNextNull(nodep->itemp()->valuep()); @@ -1668,7 +1658,7 @@ private: } if (!did && m_required) { nodep->v3error("Expecting expression to be constant, but variable isn't const: " - <itemp()->prettyNameQ()); + << nodep->itemp()->prettyNameQ()); } } @@ -1683,8 +1673,7 @@ private: virtual void visit(AstSenItem* nodep) VL_OVERRIDE { iterateChildren(nodep); if (m_doNConst - && (VN_IS(nodep->sensp(), Const) - || VN_IS(nodep->sensp(), EnumItemRef) + && (VN_IS(nodep->sensp(), Const) || VN_IS(nodep->sensp(), EnumItemRef) || (nodep->varrefp() && nodep->varrefp()->varp()->isParam()))) { // Constants in sensitivity lists may be removed (we'll simplify later) if (nodep->isClocked()) { // A constant can never get a pos/negedge @@ -1707,15 +1696,14 @@ private: lastSensp = VN_CAST(lastSensp, Not)->lhsp(); invert = !invert; } - UINFO(8,"senItem(NOT...) "<edgeType( nodep->edgeType().invert() ); + UINFO(8, "senItem(NOT...) " << nodep << " " << invert << endl); + if (invert) nodep->edgeType(nodep->edgeType().invert()); AstNodeVarRef* senvarp = VN_CAST(lastSensp->unlinkFrBack(), NodeVarRef); UASSERT_OBJ(senvarp, sensp, "Non-varref sensitivity variable"); sensp->replaceWith(senvarp); VL_DO_DANGLING(sensp->deleteTree(), sensp); } else if (!m_doNConst // Deal with later when doNConst missing - && (VN_IS(nodep->sensp(), EnumItemRef) - || VN_IS(nodep->sensp(), Const))) { + && (VN_IS(nodep->sensp(), EnumItemRef) || VN_IS(nodep->sensp(), Const))) { } else if (nodep->isIllegal()) { // Deal with later } else { UASSERT_OBJ(!(nodep->hasVar() && !nodep->varrefp()), nodep, @@ -1726,7 +1714,7 @@ private: iterateChildren(nodep); if (AstConst* constp = VN_CAST(nodep->rhsp(), Const)) { if (constp->isZero()) { - UINFO(4,"SENGATE(...,0)->NEVER"<NEVER" << endl); if (onlySenItemInSenTree(nodep)) { nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Never())); VL_DO_DANGLING(nodep->deleteTree(), nodep); @@ -1734,7 +1722,7 @@ private: VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } } else { - UINFO(4,"SENGATE(SENITEM,0)->ALWAYS SENITEM"<ALWAYS SENITEM" << endl); AstNode* senitemp = nodep->sensesp()->unlinkFrBack(); nodep->replaceWith(senitemp); VL_DO_DANGLING(nodep->deleteTree(), nodep); @@ -1743,23 +1731,25 @@ private: } struct SenItemCmp { - inline bool operator() (AstNodeSenItem* lhsp, AstNodeSenItem* rhsp) const { + inline bool operator()(AstNodeSenItem* lhsp, AstNodeSenItem* rhsp) const { if (lhsp->type() < rhsp->type()) return true; if (lhsp->type() > rhsp->type()) return false; const AstSenItem* litemp = VN_CAST_CONST(lhsp, SenItem); const AstSenItem* ritemp = VN_CAST_CONST(rhsp, SenItem); if (litemp && ritemp) { // Looks visually better if we keep sorted by name - if (!litemp->varrefp() && ritemp->varrefp()) return true; - if ( litemp->varrefp() && !ritemp->varrefp()) return false; + if (!litemp->varrefp() && ritemp->varrefp()) return true; + if (litemp->varrefp() && !ritemp->varrefp()) return false; if (litemp->varrefp() && ritemp->varrefp()) { if (litemp->varrefp()->name() < ritemp->varrefp()->name()) return true; if (litemp->varrefp()->name() > ritemp->varrefp()->name()) return false; // But might be same name with different scopes - if (litemp->varrefp()->varScopep() - < ritemp->varrefp()->varScopep()) return true; - if (litemp->varrefp()->varScopep() - > ritemp->varrefp()->varScopep()) return false; + if (litemp->varrefp()->varScopep() < ritemp->varrefp()->varScopep()) { + return true; + } + if (litemp->varrefp()->varScopep() > ritemp->varrefp()->varScopep()) { + return false; + } // Or rarely, different data types if (litemp->varrefp()->dtypep() < ritemp->varrefp()->dtypep()) return true; if (litemp->varrefp()->dtypep() > ritemp->varrefp()->dtypep()) return false; @@ -1777,7 +1767,7 @@ private: virtual void visit(AstSenTree* nodep) VL_OVERRIDE { iterateChildren(nodep); if (m_doExpensive) { - //cout<dumpTree(cout, "ssin: "); + // cout<dumpTree(cout, "ssin: "); // Optimize ideas for the future: // SENTREE(... SENGATE(x,a), SENGATE(SENITEM(x),b) ...) => SENGATE(x,OR(a,b)) @@ -1788,10 +1778,10 @@ private: // SENGATE(SENITEM(x)) -> SENITEM(x), then let it collapse with the // other SENITEM(x). { - AstUser4InUse m_inuse4; + AstUser4InUse m_inuse4; // Mark x in SENITEM(x) - for (AstNodeSenItem* senp = VN_CAST(nodep->sensesp(), NodeSenItem); - senp; senp = VN_CAST(senp->nextp(), NodeSenItem)) { + for (AstNodeSenItem* senp = VN_CAST(nodep->sensesp(), NodeSenItem); senp; + senp = VN_CAST(senp->nextp(), NodeSenItem)) { if (AstSenItem* itemp = VN_CAST(senp, SenItem)) { if (itemp->varrefp() && itemp->varrefp()->varScopep()) { itemp->varrefp()->varScopep()->user4(1); @@ -1799,8 +1789,8 @@ private: } } // Find x in SENTREE(SENITEM(x)) - for (AstNodeSenItem* nextp, * senp = VN_CAST(nodep->sensesp(), NodeSenItem); - senp; senp = nextp) { + for (AstNodeSenItem *nextp, *senp = VN_CAST(nodep->sensesp(), NodeSenItem); senp; + senp = nextp) { nextp = VN_CAST(senp->nextp(), NodeSenItem); if (AstSenGate* gatep = VN_CAST(senp, SenGate)) { if (AstSenItem* itemp = VN_CAST(gatep->sensesp(), SenItem)) { @@ -1821,8 +1811,8 @@ private: // Sort the sensitivity names so "posedge a or b" and "posedge b or a" end up together. // Also, remove duplicate assignments, and fold POS&NEGs into ANYEDGEs // Make things a little faster; check first if we need a sort - for (AstNodeSenItem* nextp, * senp = VN_CAST(nodep->sensesp(), NodeSenItem); - senp; senp = nextp) { + for (AstNodeSenItem *nextp, *senp = VN_CAST(nodep->sensesp(), NodeSenItem); senp; + senp = nextp) { nextp = VN_CAST(senp->nextp(), NodeSenItem); // cppcheck-suppress unassignedVariable // cppcheck bug SenItemCmp cmp; @@ -1830,17 +1820,17 @@ private: // Something's out of order, sort it senp = NULL; std::vector vec; - for (AstNodeSenItem* senp = VN_CAST(nodep->sensesp(), NodeSenItem); - senp; senp = VN_CAST(senp->nextp(), NodeSenItem)) { + for (AstNodeSenItem* senp = VN_CAST(nodep->sensesp(), NodeSenItem); senp; + senp = VN_CAST(senp->nextp(), NodeSenItem)) { vec.push_back(senp); } stable_sort(vec.begin(), vec.end(), SenItemCmp()); - for (std::vector::iterator it=vec.begin(); - it!=vec.end(); ++it) { + for (std::vector::iterator it = vec.begin(); it != vec.end(); + ++it) { (*it)->unlinkFrBack(); } - for (std::vector::iterator it=vec.begin(); - it!=vec.end(); ++it) { + for (std::vector::iterator it = vec.begin(); it != vec.end(); + ++it) { nodep->addSensesp(*it); } break; @@ -1848,8 +1838,8 @@ private: } // Pass2, remove dup edges - for (AstNodeSenItem* nextp, * senp = VN_CAST(nodep->sensesp(), NodeSenItem); - senp; senp = nextp) { + for (AstNodeSenItem *nextp, *senp = VN_CAST(nodep->sensesp(), NodeSenItem); senp; + senp = nextp) { nextp = VN_CAST(senp->nextp(), NodeSenItem); AstNodeSenItem* cmpp = nextp; AstSenItem* litemp = VN_CAST(senp, SenItem); @@ -1860,12 +1850,14 @@ private: || (!litemp->varrefp() && !ritemp->varrefp())) { // We've sorted in the order ANY, BOTH, POS, NEG, // so we don't need to try opposite orders - if (( litemp->edgeType() == VEdgeType::ET_ANYEDGE) // ANY or {BOTH|POS|NEG} -> ANY - || (litemp->edgeType() == VEdgeType::ET_BOTHEDGE) // BOTH or {POS|NEG} -> BOTH + if ((litemp->edgeType() + == VEdgeType::ET_ANYEDGE) // ANY or {BOTH|POS|NEG} -> ANY + || (litemp->edgeType() + == VEdgeType::ET_BOTHEDGE) // BOTH or {POS|NEG} -> BOTH || (litemp->edgeType() == VEdgeType::ET_POSEDGE // POS or NEG -> BOTH && ritemp->edgeType() == VEdgeType::ET_NEGEDGE) || (litemp->edgeType() == ritemp->edgeType()) // Identical edges - ) { + ) { // Fix edge of old node if (litemp->edgeType() == VEdgeType::ET_POSEDGE && ritemp->edgeType() == VEdgeType::ET_NEGEDGE) @@ -1879,7 +1871,7 @@ private: } } } - //nodep->dumpTree(cout, "ssou: "); + // nodep->dumpTree(cout, "ssou: "); } } @@ -1898,22 +1890,22 @@ private: virtual void visit(AstAssignW* nodep) VL_OVERRIDE { iterateChildren(nodep); if (m_doNConst && replaceNodeAssign(nodep)) return; - AstNodeVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef); // Not VarXRef, as different refs may set different values to each hierarchy - if (m_wremove && !m_params && m_doNConst - && m_modp && operandConst(nodep->rhsp()) + AstNodeVarRef* varrefp = VN_CAST( + nodep->lhsp(), + VarRef); // Not VarXRef, as different refs may set different values to each hierarchy + if (m_wremove && !m_params && m_doNConst && m_modp && operandConst(nodep->rhsp()) && !VN_CAST(nodep->rhsp(), Const)->num().isFourState() && varrefp // Don't do messes with BITREFs/ARRAYREFs && !varrefp->varp()->valuep() // Not already constified - && !varrefp->varScopep()) { // Not scoped (or each scope may have different initial value) + && !varrefp->varScopep()) { // Not scoped (or each scope may have different initial + // value) // ASSIGNW (VARREF, const) -> INITIAL ( ASSIGN (VARREF, const) ) - UINFO(4,"constAssignW "<rhsp()->unlinkFrBack(); varrefp->unlinkFrBack(); - AstInitial* newinitp - = new AstInitial(nodep->fileline(), - new AstAssign(nodep->fileline(), - varrefp, exprp)); + AstInitial* newinitp = new AstInitial( + nodep->fileline(), new AstAssign(nodep->fileline(), varrefp, exprp)); m_modp->addStmtp(newinitp); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); // Set the initial value right in the variable so we can constant propagate @@ -1928,10 +1920,10 @@ private: if (const AstConst* constp = VN_CAST(nodep->condp(), Const)) { AstNode* keepp = NULL; if (constp->isZero()) { - UINFO(4,"IF(0,{any},{x}) => {x}: "< {x}: " << nodep << endl); keepp = nodep->elsesp(); } else { - UINFO(4,"IF(!0,{x},{any}) => {x}: "< {x}: " << nodep << endl); keepp = nodep->ifsp(); } if (keepp) { @@ -1941,27 +1933,27 @@ private: nodep->unlinkFrBack(); } VL_DO_DANGLING(nodep->deleteTree(), nodep); - } - else if (!afterComment(nodep->ifsp()) && !afterComment(nodep->elsesp())) { + } else if (!afterComment(nodep->ifsp()) && !afterComment(nodep->elsesp())) { // Empty block, remove it // Note if we support more C++ then there might be side // effects in the condition itself VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } - else if (!afterComment(nodep->ifsp())) { - UINFO(4,"IF({x}) NULL {...} => IF(NOT{x}}: "<ifsp())) { + UINFO(4, "IF({x}) NULL {...} => IF(NOT{x}}: " << nodep << endl); AstNode* condp = nodep->condp(); AstNode* elsesp = nodep->elsesp(); condp->unlinkFrBackWithNext(); elsesp->unlinkFrBackWithNext(); - if (nodep->ifsp()) { nodep->ifsp()->unlinkFrBackWithNext()->deleteTree(); } // Must have been comment - nodep->condp(new AstLogNot(condp->fileline(), condp)); // LogNot, as C++ optimization also possible + if (nodep->ifsp()) { // Must have been comment + nodep->ifsp()->unlinkFrBackWithNext()->deleteTree(); + } + nodep->condp(new AstLogNot(condp->fileline(), + condp)); // LogNot, as C++ optimization also possible nodep->addIfsp(elsesp); - } - else if (((VN_IS(nodep->condp(), Not) && nodep->condp()->width()==1) - || VN_IS(nodep->condp(), LogNot)) - && nodep->ifsp() && nodep->elsesp()) { - UINFO(4,"IF(NOT {x}) => IF(x) swapped if/else"<condp(), Not) && nodep->condp()->width() == 1) + || VN_IS(nodep->condp(), LogNot)) + && nodep->ifsp() && nodep->elsesp()) { + UINFO(4, "IF(NOT {x}) => IF(x) swapped if/else" << nodep << endl); AstNode* condp = VN_CAST(nodep->condp(), Not)->lhsp()->unlinkFrBackWithNext(); AstNode* ifsp = nodep->ifsp()->unlinkFrBackWithNext(); AstNode* elsesp = nodep->elsesp()->unlinkFrBackWithNext(); @@ -1969,33 +1961,29 @@ private: ifp->branchPred(nodep->branchPred().invert()); nodep->replaceWith(ifp); VL_DO_DANGLING(nodep->deleteTree(), nodep); - } - else if (ifSameAssign(nodep)) { - UINFO(4,"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})"<ifsp(), NodeAssign); + } else if (ifSameAssign(nodep)) { + UINFO(4, "IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})" + << endl); + AstNodeAssign* ifp = VN_CAST(nodep->ifsp(), NodeAssign); AstNodeAssign* elsep = VN_CAST(nodep->elsesp(), NodeAssign); ifp->unlinkFrBack(); AstNode* condp = nodep->condp()->unlinkFrBack(); AstNode* truep = ifp->rhsp()->unlinkFrBack(); AstNode* falsep = elsep->rhsp()->unlinkFrBack(); - ifp->rhsp(new AstCond(truep->fileline(), - condp, truep, falsep)); + ifp->rhsp(new AstCond(truep->fileline(), condp, truep, falsep)); nodep->replaceWith(ifp); VL_DO_DANGLING(nodep->deleteTree(), nodep); - } - else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting - && operandIfIf(nodep)) { - UINFO(9,"IF({a}) IF({b}) => IF({a} && {b})"< IF({a} && {b})" << endl); AstNodeIf* lowerIfp = VN_CAST(nodep->ifsp(), NodeIf); AstNode* condp = nodep->condp()->unlinkFrBack(); AstNode* lowerIfsp = lowerIfp->ifsp()->unlinkFrBackWithNext(); AstNode* lowerCondp = lowerIfp->condp()->unlinkFrBackWithNext(); - nodep->condp(new AstLogAnd(lowerIfp->fileline(), - condp, lowerCondp)); + nodep->condp(new AstLogAnd(lowerIfp->fileline(), condp, lowerCondp)); lowerIfp->replaceWith(lowerIfsp); VL_DO_DANGLING(lowerIfp->deleteTree(), lowerIfp); - } - else if (operandBoolShift(nodep->condp())) { + } else if (operandBoolShift(nodep->condp())) { replaceBoolShift(nodep->condp()); } } @@ -2018,11 +2006,11 @@ private: || (prevp->displayType() == AstDisplayType::DT_DISPLAY && nodep->displayType() == AstDisplayType::DT_WRITE))) return false; - if ((prevp->filep() && !nodep->filep()) - || (!prevp->filep() && nodep->filep()) - || !prevp->filep()->sameTree(nodep->filep())) return false; - if (!prevp->fmtp() || prevp->fmtp()->nextp() - || !nodep->fmtp() || nodep->fmtp()->nextp()) return false; + if ((prevp->filep() && !nodep->filep()) || (!prevp->filep() && nodep->filep()) + || !prevp->filep()->sameTree(nodep->filep())) + return false; + if (!prevp->fmtp() || prevp->fmtp()->nextp() || !nodep->fmtp() || nodep->fmtp()->nextp()) + return false; // We don't merge scopeNames as might be different scopes (late in process) // We don't merge arguments as might need to later print warnings with right line numbers AstSFormatF* pformatp = prevp->fmtp(); @@ -2030,18 +2018,18 @@ private: AstSFormatF* nformatp = nodep->fmtp(); if (!nformatp || nformatp->exprsp() || nformatp->scopeNamep()) return false; // - UINFO(9,"DISPLAY(SF({a})) DISPLAY(SF({b})) -> DISPLAY(SF({a}+{b}))"< DISPLAY(SF({a}+{b}))" << endl); // Convert DT_DISPLAY to DT_WRITE as may allow later optimizations if (prevp->displayType() == AstDisplayType::DT_DISPLAY) { prevp->displayType(AstDisplayType::DT_WRITE); - pformatp->text(pformatp->text()+"\n"); + pformatp->text(pformatp->text() + "\n"); } // We can't replace prev() as the edit tracking iterators will get confused. // So instead we edit the prev note itself. - if (prevp->addNewline()) pformatp->text(pformatp->text()+"\n"); - pformatp->text(pformatp->text()+nformatp->text()); + if (prevp->addNewline()) pformatp->text(pformatp->text() + "\n"); + pformatp->text(pformatp->text() + nformatp->text()); if (!prevp->addNewline() && nodep->addNewline()) { - pformatp->text(pformatp->text()+"\n"); + pformatp->text(pformatp->text() + "\n"); } VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); return true; @@ -2052,22 +2040,25 @@ private: // This eliminates a pile of wide temps, and makes the C a whole lot more readable. iterateChildren(nodep); bool anyconst = false; - for (AstNode* argp = nodep->exprsp(); argp; argp=argp->nextp()) { - if (VN_IS(argp, Const)) { anyconst = true; break; } + for (AstNode* argp = nodep->exprsp(); argp; argp = argp->nextp()) { + if (VN_IS(argp, Const)) { + anyconst = true; + break; + } } if (m_doNConst && anyconst) { - //UINFO(9," Display in "<text()<text()<exprsp(); string text = nodep->text(); - for (string::const_iterator it = text.begin(); it!=text.end(); ++it) { + for (string::const_iterator it = text.begin(); it != text.end(); ++it) { char ch = *it; - if (!inPct && ch=='%') { + if (!inPct && ch == '%') { inPct = true; fmt = ch; - } else if (inPct && (isdigit(ch) || ch=='.' || ch=='-')) { + } else if (inPct && (isdigit(ch) || ch == '.' || ch == '-')) { fmt += ch; } else if (inPct) { inPct = false; @@ -2081,8 +2072,8 @@ private: AstNode* nextp = argp->nextp(); if (VN_IS(argp, Const)) { // Convert it string out = VN_CAST(argp, Const)->num().displayed(nodep, fmt); - UINFO(9," DispConst: "< "< " << out << " for " + << argp << endl); // fmt = out w/ replace % with %% as it must be literal. fmt = VString::quotePercent(out); VL_DO_DANGLING(argp->unlinkFrBack()->deleteTree(), argp); @@ -2098,12 +2089,10 @@ private: } if (newFormat != nodep->text()) { nodep->text(newFormat); - UINFO(9," Display out "<exprsp() - && nodep->name().find('%') == string::npos - && !nodep->hidden()) { + if (!nodep->exprsp() && nodep->name().find('%') == string::npos && !nodep->hidden()) { // Just a simple constant string - the formatting is pointless VL_DO_DANGLING(replaceConstString(nodep, nodep->name()), nodep); } @@ -2122,35 +2111,31 @@ private: virtual void visit(AstWhile* nodep) VL_OVERRIDE { bool oldHasJumpGo = m_hasJumpGo; m_hasJumpGo = false; - { - iterateChildren(nodep); - } + { iterateChildren(nodep); } bool thisWhileHasJumpGo = m_hasJumpGo; m_hasJumpGo = thisWhileHasJumpGo || oldHasJumpGo; if (m_doNConst) { if (nodep->condp()->isZero()) { - UINFO(4,"WHILE(0) => nop "<precondsp()) nodep->replaceWith(nodep->precondsp()); - else nodep->unlinkFrBack(); + UINFO(4, "WHILE(0) => nop " << nodep << endl); + if (nodep->precondsp()) { + nodep->replaceWith(nodep->precondsp()); + } else { + nodep->unlinkFrBack(); + } VL_DO_DANGLING(nodep->deleteTree(), nodep); - } - else if (nodep->condp()->isNeqZero()) { + } else if (nodep->condp()->isNeqZero()) { if (!thisWhileHasJumpGo) { nodep->v3warn(INFINITELOOP, "Infinite loop (condition always true)"); - nodep->fileline()->modifyWarnOff(V3ErrorCode::INFINITELOOP, true); // Complain just once + nodep->fileline()->modifyWarnOff(V3ErrorCode::INFINITELOOP, + true); // Complain just once } - } - else if (operandBoolShift(nodep->condp())) { + } else if (operandBoolShift(nodep->condp())) { replaceBoolShift(nodep->condp()); } } } - virtual void visit(AstInitArray* nodep) VL_OVERRIDE { - iterateChildren(nodep); - } - virtual void visit(AstInitItem* nodep) VL_OVERRIDE { - iterateChildren(nodep); - } + virtual void visit(AstInitArray* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstInitItem* nodep) VL_OVERRIDE { iterateChildren(nodep); } // These are converted by V3Param. Don't constify as we don't want the // from() VARREF to disappear, if any. // If output of a presel didn't get consted, chances are V3Param didn't visit properly @@ -2159,9 +2144,7 @@ private: // Ignored, can eliminate early virtual void visit(AstSysIgnore* nodep) VL_OVERRIDE { iterateChildren(nodep); - if (m_doNConst) { - VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } + if (m_doNConst) { VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } } // Simplify @@ -2182,7 +2165,7 @@ private: if (!nodep->nextp()) { if (AstJumpLabel* aboveLabelp = VN_CAST(nodep->abovep(), JumpLabel)) { if (aboveLabelp == nodep->labelp()) { - UINFO(4, "JUMPGO => last remove "< last remove " << nodep << endl); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); return; } @@ -2199,11 +2182,14 @@ private: iterateChildren(nodep); // AstJumpGo's below here that point to this node will set user4 if (m_doExpensive && !nodep->user4()) { - UINFO(4,"JUMPLABEL => unused "< unused " << nodep << endl); AstNode* underp = NULL; if (nodep->stmtsp()) underp = nodep->stmtsp()->unlinkFrBackWithNext(); - if (underp) nodep->replaceWith(underp); - else nodep->unlinkFrBack(); + if (underp) { + nodep->replaceWith(underp); + } else { + nodep->unlinkFrBack(); + } VL_DO_DANGLING(nodep->deleteTree(), nodep); } } @@ -2212,7 +2198,7 @@ private: // Below lines are magic expressions processed by astgen // TREE_SKIP_VISIT("AstNODETYPE") # Rename normal visit to visitGen and don't iterate //----- - + // clang-format off TREE_SKIP_VISIT("ArraySel"); //----- @@ -2527,7 +2513,7 @@ private: TREEOPC("AstPutcN{$lhsp.castConst, $rhsp.castConst, $thsp.castConst}", "replaceConst(nodep)"); TREEOPC("AstSubstrN{$lhsp.castConst, $rhsp.castConst, $thsp.castConst}", "replaceConst(nodep)"); TREEOPC("AstCvtPackString{$lhsp.castConst}", "replaceConstString(nodep, VN_CAST(nodep->lhsp(), Const)->num().toString())"); - + // clang-format on // Possible futures: // (a?(b?y:x):y) -> (a&&!b)?x:y @@ -2545,13 +2531,11 @@ private: // Ignore dtypes for parameter type pins } else { nodep->v3error("Expecting expression to be constant, but can't convert a " - <prettyTypeName()<<" to constant."); + << nodep->prettyTypeName() << " to constant."); } } else { // Calculate the width of this operation - if (m_params && !nodep->width()) { - nodep = V3Width::widthParamsEdit(nodep); - } + if (m_params && !nodep->width()) nodep = V3Width::widthParamsEdit(nodep); iterateChildren(nodep); } } @@ -2585,6 +2569,7 @@ public: m_scopep = NULL; m_attrp = NULL; // + // clang-format off switch (pmode) { case PROC_PARAMS: m_doV = true; m_doNConst = true; m_params = true; m_required = true; break; @@ -2597,6 +2582,7 @@ public: case PROC_CPP: m_doV = false; m_doNConst = true; break; default: v3fatalSrc("Bad case"); break; } + // clang-format on } virtual ~ConstVisitor() {} AstNode* mainAcceptEdit(AstNode* nodep) { @@ -2611,7 +2597,7 @@ public: //! Force this cell node's parameter list to become a constant //! @return Pointer to the edited node. AstNode* V3Const::constifyParamsEdit(AstNode* nodep) { - //if (debug()>0) nodep->dumpTree(cout, " forceConPRE : "); + // if (debug() > 0) nodep->dumpTree(cout, " forceConPRE : "); // Resize even if the node already has a width, because buried in the tree // we may have a node we just created with signing, etc, that isn't sized yet. @@ -2627,7 +2613,7 @@ AstNode* V3Const::constifyParamsEdit(AstNode* nodep) { nodep = visitor.mainAcceptEdit(nodep); } // Because we do edits, nodep links may get trashed and core dump this. - //if (debug()>0) nodep->dumpTree(cout, " forceConDONE: "); + // if (debug() > 0) nodep->dumpTree(cout, " forceConDONE: "); return nodep; } @@ -2640,7 +2626,7 @@ AstNode* V3Const::constifyParamsEdit(AstNode* nodep) { //! width check. //! @return Pointer to the edited node. AstNode* V3Const::constifyGenerateParamsEdit(AstNode* nodep) { - //if (debug()>0) nodep->dumpTree(cout, " forceConPRE : "); + // if (debug() > 0) nodep->dumpTree(cout, " forceConPRE : "); // Resize even if the node already has a width, because buried in the tree // we may have a node we just created with signing, etc, that isn't sized // yet. @@ -2657,31 +2643,31 @@ AstNode* V3Const::constifyGenerateParamsEdit(AstNode* nodep) { nodep = visitor.mainAcceptEdit(nodep); } // Because we do edits, nodep links may get trashed and core dump this. - //if (debug()>0) nodep->dumpTree(cout, " forceConDONE: "); + // if (debug() > 0) nodep->dumpTree(cout, " forceConDONE: "); return nodep; } void V3Const::constifyAllLint(AstNetlist* nodep) { // Only call from Verilator.cpp, as it uses user#'s - UINFO(2,__FUNCTION__<<": "<= 3); } void V3Const::constifyCpp(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } AstNode* V3Const::constifyEdit(AstNode* nodep) { - ConstVisitor visitor (ConstVisitor::PROC_V_NOWARN); + ConstVisitor visitor(ConstVisitor::PROC_V_NOWARN); nodep = visitor.mainAcceptEdit(nodep); return nodep; } @@ -2690,9 +2676,9 @@ void V3Const::constifyAllLive(AstNetlist* nodep) { // Only call from Verilator.cpp, as it uses user#'s // This only pushes constants up, doesn't make any other edits // IE doesn't prune dead statements, as we need to do some usability checks after this - UINFO(2,__FUNCTION__<<": "<= 3); @@ -2700,16 +2686,16 @@ void V3Const::constifyAllLive(AstNetlist* nodep) { void V3Const::constifyAll(AstNetlist* nodep) { // Only call from Verilator.cpp, as it uses user#'s - UINFO(2,__FUNCTION__<<": "<= 3); } AstNode* V3Const::constifyExpensiveEdit(AstNode* nodep) { - ConstVisitor visitor (ConstVisitor::PROC_V_EXPENSIVE); + ConstVisitor visitor(ConstVisitor::PROC_V_EXPENSIVE); nodep = visitor.mainAcceptEdit(nodep); return nodep; } diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp index c90249700..0cf64c20a 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -63,9 +63,7 @@ private: public: // CONSTRUCTORS - explicit DeadModVisitor(AstNodeModule* nodep) { - iterate(nodep); - } + explicit DeadModVisitor(AstNodeModule* nodep) { iterate(nodep); } virtual ~DeadModVisitor() {} }; @@ -80,52 +78,46 @@ private: // AstVar::user1() -> int. Count of number of references // AstVarScope::user1() -> int. Count of number of references // AstNodeDType::user1() -> int. Count of number of references - AstUser1InUse m_inuser1; + AstUser1InUse m_inuser1; // TYPES - typedef std::multimap AssignMap; + typedef std::multimap AssignMap; // STATE - AstNodeModule* m_modp; // Current module - std::vector m_varsp; // List of all encountered to avoid another loop through tree - std::vector m_dtypesp; // List of all encountered to avoid another loop through tree - std::vector m_vscsp; // List of all encountered to avoid another loop through tree - std::vector m_scopesp; // List of all encountered to avoid another loop through tree - std::vector m_cellsp; // List of all encountered to avoid another loop through tree - std::vector m_classesp; // List of all encountered to avoid another loop through tree - AssignMap m_assignMap; // List of all simple assignments for each variable - bool m_elimUserVars; // Allow removal of user's vars - bool m_elimDTypes; // Allow removal of DTypes - bool m_elimScopes; // Allow removal of Scopes - bool m_elimCells; // Allow removal of Cells - bool m_sideEffect; // Side effects discovered in assign RHS + AstNodeModule* m_modp; // Current module + // List of all encountered to avoid another loop through tree + std::vector m_varsp; + std::vector m_dtypesp; + std::vector m_vscsp; + std::vector m_scopesp; + std::vector m_cellsp; + std::vector m_classesp; + + AssignMap m_assignMap; // List of all simple assignments for each variable + bool m_elimUserVars; // Allow removal of user's vars + bool m_elimDTypes; // Allow removal of DTypes + bool m_elimScopes; // Allow removal of Scopes + bool m_elimCells; // Allow removal of Cells + bool m_sideEffect; // Side effects discovered in assign RHS // METHODS VL_DEBUG_FUNC; // Declare debug() void checkAll(AstNode* nodep) { if (nodep != nodep->dtypep()) { // NodeDTypes reference themselves - if (AstNode* subnodep = nodep->dtypep()) { - subnodep->user1Inc(); - } - } - if (AstNode* subnodep = nodep->getChildDTypep()) { - subnodep->user1Inc(); + if (AstNode* subnodep = nodep->dtypep()) subnodep->user1Inc(); } + if (AstNode* subnodep = nodep->getChildDTypep()) subnodep->user1Inc(); } void checkDType(AstNodeDType* nodep) { if (!nodep->generic() // Don't remove generic types && m_elimDTypes // dtypes stick around until post-widthing && !VN_IS(nodep, MemberDType) // Keep member names iff upper type exists - ) { + ) { m_dtypesp.push_back(nodep); } - if (AstNode* subnodep = nodep->virtRefDTypep()) { - subnodep->user1Inc(); - } - if (AstNode* subnodep = nodep->virtRefDType2p()) { - subnodep->user1Inc(); - } + if (AstNode* subnodep = nodep->virtRefDTypep()) subnodep->user1Inc(); + if (AstNode* subnodep = nodep->virtRefDType2p()) subnodep->user1Inc(); } // VISITORS @@ -177,20 +169,24 @@ private: nodep->varScopep()->user1Inc(); nodep->varScopep()->varp()->user1Inc(); } - if (nodep->varp()) { - nodep->varp()->user1Inc(); - } + if (nodep->varp()) nodep->varp()->user1Inc(); if (nodep->packagep()) { - if (m_elimCells) nodep->packagep(NULL); - else nodep->packagep()->user1Inc(); + if (m_elimCells) { + nodep->packagep(NULL); + } else { + nodep->packagep()->user1Inc(); + } } } virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { iterateChildren(nodep); checkAll(nodep); if (nodep->packagep()) { - if (m_elimCells) nodep->packagep(NULL); - else nodep->packagep()->user1Inc(); + if (m_elimCells) { + nodep->packagep(NULL); + } else { + nodep->packagep()->user1Inc(); + } } } virtual void visit(AstMethodCall* nodep) VL_OVERRIDE { @@ -202,8 +198,11 @@ private: checkDType(nodep); checkAll(nodep); if (nodep->packagep()) { - if (m_elimCells) nodep->packagep(NULL); - else nodep->packagep()->user1Inc(); + if (m_elimCells) { + nodep->packagep(NULL); + } else { + nodep->packagep()->user1Inc(); + } } } virtual void visit(AstClassRefDType* nodep) VL_OVERRIDE { @@ -211,12 +210,13 @@ private: checkDType(nodep); checkAll(nodep); if (nodep->packagep()) { - if (m_elimCells) nodep->packagep(NULL); - else nodep->packagep()->user1Inc(); - } - if (nodep->classp()) { - nodep->classp()->user1Inc(); + if (m_elimCells) { + nodep->packagep(NULL); + } else { + nodep->packagep()->user1Inc(); + } } + if (nodep->classp()) nodep->classp()->user1Inc(); } virtual void visit(AstNodeDType* nodep) VL_OVERRIDE { iterateChildren(nodep); @@ -227,8 +227,11 @@ private: iterateChildren(nodep); checkAll(nodep); if (nodep->packagep()) { - if (m_elimCells) nodep->packagep(NULL); - else nodep->packagep()->user1Inc(); + if (m_elimCells) { + nodep->packagep(NULL); + } else { + nodep->packagep()->user1Inc(); + } } checkAll(nodep); } @@ -263,17 +266,13 @@ private: iterateChildren(nodep); checkAll(nodep); if (nodep->scopep()) nodep->scopep()->user1Inc(); - if (mightElimVar(nodep->varp())) { - m_vscsp.push_back(nodep); - } + if (mightElimVar(nodep->varp())) m_vscsp.push_back(nodep); } virtual void visit(AstVar* nodep) VL_OVERRIDE { iterateChildren(nodep); checkAll(nodep); if (nodep->isSigPublic() && m_modp && VN_IS(m_modp, Package)) m_modp->user1Inc(); - if (mightElimVar(nodep)) { - m_varsp.push_back(nodep); - } + if (mightElimVar(nodep)) m_varsp.push_back(nodep); } virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { // See if simple assignments to variables may be eliminated because @@ -306,14 +305,15 @@ private: // Kill any unused modules // V3LinkCells has a graph that is capable of this too, but we need to do it // after we've done all the generate blocks - for (bool retry=true; retry; ) { + for (bool retry = true; retry;) { retry = false; AstNodeModule* nextmodp; - for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=nextmodp) { + for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp = nextmodp) { nextmodp = VN_CAST(modp->nextp(), NodeModule); - if (modp->dead() || (modp->level()>2 && modp->user1()==0 && !modp->internal())) { + if (modp->dead() + || (modp->level() > 2 && modp->user1() == 0 && !modp->internal())) { // > 2 because L1 is the wrapper, L2 is the top user module - UINFO(4," Dead module "<dead()) { // If was dead didn't increment user1's @@ -327,27 +327,23 @@ private: } bool mightElimVar(AstVar* nodep) { return (!nodep->isSigPublic() // Can't elim publics! - && !nodep->isIO() - && !nodep->isClassMember() + && !nodep->isIO() && !nodep->isClassMember() && ((nodep->isTemp() && !nodep->isTrace()) || (nodep->isParam() && !nodep->isTrace() && !v3Global.opt.xmlOnly()) || m_elimUserVars)); // Post-Trace can kill most anything } void deadCheckScope() { - for (bool retry=true; retry; ) { + for (bool retry = true; retry;) { retry = false; - for (std::vector::iterator it = m_scopesp.begin(); - it != m_scopesp.end();++it) { + for (std::vector::iterator it = m_scopesp.begin(); it != m_scopesp.end(); + ++it) { AstScope* scp = *it; - if (!scp) - continue; + if (!scp) continue; if (scp->user1() == 0) { UINFO(4, " Dead AstScope " << scp << endl); scp->aboveScopep()->user1Inc(-1); - if (scp->dtypep()) { - scp->dtypep()->user1Inc(-1); - } + if (scp->dtypep()) scp->dtypep()->user1Inc(-1); VL_DO_DANGLING(scp->unlinkFrBack()->deleteTree(), scp); *it = NULL; retry = true; @@ -357,7 +353,7 @@ private: } void deadCheckCells() { - for (std::vector::iterator it = m_cellsp.begin(); it!=m_cellsp.end(); ++it) { + for (std::vector::iterator it = m_cellsp.begin(); it != m_cellsp.end(); ++it) { AstCell* cellp = *it; if (cellp->user1() == 0 && !cellp->modp()->stmtsp()) { cellp->modp()->user1Inc(-1); @@ -385,15 +381,15 @@ private: void deadCheckVar() { // Delete any unused varscopes - for (std::vector::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) { + for (std::vector::iterator it = m_vscsp.begin(); it != m_vscsp.end(); ++it) { AstVarScope* vscp = *it; if (vscp->user1() == 0) { - UINFO(4," Dead "< eqrange + UINFO(4, " Dead " << vscp << endl); + std::pair eqrange = m_assignMap.equal_range(vscp); for (AssignMap::iterator itr = eqrange.first; itr != eqrange.second; ++itr) { AstNodeAssign* assp = itr->second; - UINFO(4," Dead assign "<dtypep()->user1Inc(-1); VL_DO_DANGLING(assp->unlinkFrBack()->deleteTree(), assp); } @@ -402,40 +398,36 @@ private: VL_DO_DANGLING(vscp->unlinkFrBack()->deleteTree(), vscp); } } - for (bool retry=true; retry; ) { + for (bool retry = true; retry;) { retry = false; - for (std::vector::iterator it = m_varsp.begin(); it != m_varsp.end();++it) { + for (std::vector::iterator it = m_varsp.begin(); it != m_varsp.end(); ++it) { AstVar* varp = *it; - if (!varp) - continue; + if (!varp) continue; if (varp->user1() == 0) { UINFO(4, " Dead " << varp << endl); - if (varp->dtypep()) { - varp->dtypep()->user1Inc(-1); - } + if (varp->dtypep()) varp->dtypep()->user1Inc(-1); VL_DO_DANGLING(varp->unlinkFrBack()->deleteTree(), varp); *it = NULL; retry = true; } } } - for (std::vector::iterator it = m_dtypesp.begin(); it != m_dtypesp.end();++it) { + for (std::vector::iterator it = m_dtypesp.begin(); it != m_dtypesp.end(); ++it) { if ((*it)->user1() == 0) { - AstNodeUOrStructDType *classp; + AstNodeUOrStructDType* classp; // It's possible that there if a reference to each individual member, but // not to the dtype itself. Check and don't remove the parent dtype if // members are still alive. if ((classp = VN_CAST((*it), NodeUOrStructDType))) { bool cont = true; - for (AstMemberDType *memberp = classp->membersp(); - memberp; memberp = VN_CAST(memberp->nextp(), MemberDType)) { + for (AstMemberDType* memberp = classp->membersp(); memberp; + memberp = VN_CAST(memberp->nextp(), MemberDType)) { if (memberp->user1() != 0) { cont = false; break; } } - if (!cont) - continue; + if (!cont) continue; } VL_DO_DANGLING((*it)->unlinkFrBack()->deleteTree(), *it); } @@ -444,8 +436,8 @@ private: public: // CONSTRUCTORS - DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes, - bool elimScopes, bool elimCells) { + DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes, bool elimScopes, + bool elimCells) { m_modp = NULL; m_elimCells = elimCells; m_elimUserVars = elimUserVars; @@ -476,41 +468,32 @@ public: // Dead class functions void V3Dead::deadifyModules(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 6); } void V3Dead::deadifyDTypes(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } void V3Dead::deadifyDTypesScoped(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); + UINFO(2, __FUNCTION__ << ": " << endl); + { DeadVisitor visitor(nodep, false, true, true, false); } // Destruct before checking + V3Global::dumpCheckGlobalTree("deadDtypesScoped", 0, + v3Global.opt.dumpTreeLevel(__FILE__) >= 3); } void V3Dead::deadifyAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } void V3Dead::deadifyAllScoped(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp index 575ba1ab4..ecf80dccb 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -81,40 +81,41 @@ private: // Cleared each scope/active: // AstAssignDly::user3() -> AstVarScope*. __Vdlyvset__ created for this assign // AstAlwaysPost::user3() -> AstVarScope*. __Vdlyvset__ last referenced in IF - AstUser1InUse m_inuser1; - AstUser2InUse m_inuser2; - AstUser3InUse m_inuser3; - AstUser4InUse m_inuser4; - AstUser5InUse m_inuser5; + AstUser1InUse m_inuser1; + AstUser2InUse m_inuser2; + AstUser3InUse m_inuser3; + AstUser4InUse m_inuser4; + AstUser5InUse m_inuser5; - enum VarUsage { VU_NONE=0, VU_DLY=1, VU_NONDLY=2 }; + enum VarUsage { VU_NONE = 0, VU_DLY = 1, VU_NONDLY = 2 }; // STATE - AstActive* m_activep; // Current activate - AstCFunc* m_cfuncp; // Current public C Function - AstAssignDly* m_nextDlyp; // Next delayed assignment in a list of assignments - bool m_inDly; // True in delayed assignments - bool m_inLoop; // True in for loops - bool m_inInitial; // True in initial blocks - typedef std::map,AstVar*> VarMap; - VarMap m_modVarMap; // Table of new var names created under module - VDouble0 m_statSharedSet; // Statistic tracking - typedef std::map ScopeVecMap; + AstActive* m_activep; // Current activate + AstCFunc* m_cfuncp; // Current public C Function + AstAssignDly* m_nextDlyp; // Next delayed assignment in a list of assignments + bool m_inDly; // True in delayed assignments + bool m_inLoop; // True in for loops + bool m_inInitial; // True in initial blocks + typedef std::map, AstVar*> VarMap; + VarMap m_modVarMap; // Table of new var names created under module + VDouble0 m_statSharedSet; // Statistic tracking + typedef std::map ScopeVecMap; ScopeVecMap m_scopeVecMap; // Next var number for each scope // METHODS VL_DEBUG_FUNC; // Declare debug() void markVarUsage(AstVarScope* nodep, uint32_t flags) { - //UINFO(4," MVU "<user5( nodep->user5() | flags ); + // UINFO(4, " MVU " << flags << " " << nodep << endl); + nodep->user5(nodep->user5() | flags); if ((nodep->user5() & VU_DLY) && (nodep->user5() & VU_NONDLY)) { - nodep->v3warn(BLKANDNBLK, "Unsupported: Blocked and non-blocking assignments to same variable: " - <varp()->prettyNameQ()); + nodep->v3warn(BLKANDNBLK, + "Unsupported: Blocked and non-blocking assignments to same variable: " + << nodep->varp()->prettyNameQ()); } } AstVarScope* createVarSc(AstVarScope* oldvarscp, const string& name, - int width/*0==fromoldvar*/, AstNodeDType* newdtypep) { + int width /*0==fromoldvar*/, AstNodeDType* newdtypep) { // Because we've already scoped it, we may need to add both the AstVar and the AstVarScope UASSERT_OBJ(oldvarscp->scopep(), oldvarscp, "Var unscoped"); AstVar* varp; @@ -126,15 +127,14 @@ private: varp = it->second; } else { if (newdtypep) { - varp = new AstVar(oldvarscp->fileline(), AstVarType::BLOCKTEMP, - name, newdtypep); - } else if (width==0) { - varp = new AstVar(oldvarscp->fileline(), AstVarType::BLOCKTEMP, - name, oldvarscp->varp()); + varp = new AstVar(oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, newdtypep); + } else if (width == 0) { + varp = new AstVar(oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, + oldvarscp->varp()); varp->dtypeFrom(oldvarscp); } else { // Used for vset and dimensions, so can zero init - varp = new AstVar(oldvarscp->fileline(), AstVarType::BLOCKTEMP, - name, VFlagBitPacked(), width); + varp = new AstVar(oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, + VFlagBitPacked(), width); } addmodp->addStmtp(varp); m_modVarMap.insert(make_pair(make_pair(addmodp, name), varp)); @@ -146,8 +146,8 @@ private: } AstActive* createActivePost(AstVarRef* varrefp) { - AstActive* newactp = new AstActive(varrefp->fileline(), "sequentdly", - m_activep->sensesp()); + AstActive* newactp + = new AstActive(varrefp->fileline(), "sequentdly", m_activep->sensesp()); // Was addNext(), but addNextHere() avoids a linear search. m_activep->addNextHere(newactp); return newactp; @@ -159,18 +159,18 @@ private: if (!varrefp->varp()->fileline()->warnIsOff(V3ErrorCode::MULTIDRIVEN) && !varrefp->varp()->user2()) { varrefp->varp()->v3warn( - MULTIDRIVEN, "Signal has multiple driving blocks with different clocking: " - <varp()->prettyNameQ()<warnOther()<<"... Location of first driving block"<warnContextPrimary()<warnOther()<<"... Location of other driving block"<warnContextSecondary() - ); + MULTIDRIVEN, + "Signal has multiple driving blocks with different clocking: " + << varrefp->varp()->prettyNameQ() << endl + << varrefp->warnOther() << "... Location of first driving block" << endl + << varrefp->warnContextPrimary() << endl + << oldactivep->warnOther() << "... Location of other driving block" << endl + << oldactivep->warnContextSecondary()); varrefp->varp()->user2(true); } - UINFO(4,"AssignDupDlyVar: "<sensesp()->sensesp()->cloneTree(true); AstNodeSenItem* senb = oldactivep->sensesp()->sensesp()->cloneTree(true); @@ -191,8 +191,8 @@ private: // Return the new LHS for the assignment, Null = unlink // Find selects AstNode* newlhsp = NULL; // NULL = unlink old assign - AstSel* bitselp = NULL; - AstArraySel* arrayselp = NULL; + AstSel* bitselp = NULL; + AstArraySel* arrayselp = NULL; if (VN_IS(lhsp, Sel)) { bitselp = VN_CAST(lhsp, Sel); arrayselp = VN_CAST(bitselp->fromp(), ArraySel); @@ -202,12 +202,12 @@ private: UASSERT_OBJ(arrayselp, nodep, "No arraysel under bitsel?"); UASSERT_OBJ(!VN_IS(arrayselp->dtypep()->skipRefp(), UnpackArrayDType), nodep, "ArraySel with unpacked arrays should have been removed in V3Slice"); - UINFO(4,"AssignDlyArray: "< dimvalp; // Assignment value for each dimension of assignment AstNode* dimselp = arrayselp; - for (; VN_IS(dimselp, ArraySel); dimselp=VN_CAST(dimselp, ArraySel)->fromp()) { + for (; VN_IS(dimselp, ArraySel); dimselp = VN_CAST(dimselp, ArraySel)->fromp()) { AstNode* valp = VN_CAST(dimselp, ArraySel)->bitp()->unlinkFrBack(); dimvalp.push_front(valp); } @@ -219,19 +219,17 @@ private: int modVecNum = m_scopeVecMap[varrefp->varScopep()]++; // std::deque dimreadps; // Read value for each dimension of assignment - for (unsigned dimension=0; dimensionshortName()+"__v"+cvtToStr(modVecNum)); - AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), - bitvarname, dimp->width(), NULL); - AstAssign* bitassignp - = new AstAssign(nodep->fileline(), - new AstVarRef(nodep->fileline(), bitvscp, true), - dimp); + string bitvarname = (string("__Vdlyvdim") + cvtToStr(dimension) + "__" + + oldvarp->shortName() + "__v" + cvtToStr(modVecNum)); + AstVarScope* bitvscp + = createVarSc(varrefp->varScopep(), bitvarname, dimp->width(), NULL); + AstAssign* bitassignp = new AstAssign( + nodep->fileline(), new AstVarRef(nodep->fileline(), bitvscp, true), dimp); nodep->addNextHere(bitassignp); dimreadps.push_front(new AstVarRef(nodep->fileline(), bitvscp, false)); } @@ -241,15 +239,16 @@ private: AstNode* bitreadp = NULL; // Code to read Vdlyvlsb if (bitselp) { AstNode* lsbvaluep = bitselp->lsbp()->unlinkFrBack(); - if (VN_IS(bitselp->fromp(), Const)) { // vlsb = constant, can just push constant into where we use it + if (VN_IS(bitselp->fromp(), Const)) { + // vlsb = constant, can just push constant into where we use it bitreadp = lsbvaluep; } else { - string bitvarname = (string("__Vdlyvlsb__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum)); - AstVarScope* bitvscp = createVarSc(varrefp->varScopep(), - bitvarname, lsbvaluep->width(), NULL); - AstAssign* bitassignp = new AstAssign(nodep->fileline(), - new AstVarRef(nodep->fileline(), bitvscp, true), - lsbvaluep); + string bitvarname = (string("__Vdlyvlsb__") + oldvarp->shortName() + "__v" + + cvtToStr(modVecNum)); + AstVarScope* bitvscp + = createVarSc(varrefp->varScopep(), bitvarname, lsbvaluep->width(), NULL); + AstAssign* bitassignp = new AstAssign( + nodep->fileline(), new AstVarRef(nodep->fileline(), bitvscp, true), lsbvaluep); nodep->addNextHere(bitassignp); bitreadp = new AstVarRef(nodep->fileline(), bitvscp, false); } @@ -257,11 +256,14 @@ private: // //=== Value: __Vdlyvval__ AstNode* valreadp; // Code to read Vdlyvval - if (VN_IS(nodep->rhsp(), Const)) { // vval = constant, can just push constant into where we use it + if (VN_IS(nodep->rhsp(), Const)) { + // vval = constant, can just push constant into where we use it valreadp = nodep->rhsp()->unlinkFrBack(); } else { - string valvarname = (string("__Vdlyvval__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum)); - AstVarScope* valvscp = createVarSc(varrefp->varScopep(), valvarname, 0, nodep->rhsp()->dtypep()); + string valvarname + = (string("__Vdlyvval__") + oldvarp->shortName() + "__v" + cvtToStr(modVecNum)); + AstVarScope* valvscp + = createVarSc(varrefp->varScopep(), valvarname, 0, nodep->rhsp()->dtypep()); newlhsp = new AstVarRef(nodep->fileline(), valvscp, true); valreadp = new AstVarRef(nodep->fileline(), valvscp, false); } @@ -278,14 +280,14 @@ private: setvscp = VN_CAST(nodep->user3p(), VarScope); ++m_statSharedSet; } else { // Create new one - string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum)); + string setvarname + = (string("__Vdlyvset__") + oldvarp->shortName() + "__v" + cvtToStr(modVecNum)); setvscp = createVarSc(varrefp->varScopep(), setvarname, 1, NULL); setinitp = new AstAssignPre(nodep->fileline(), new AstVarRef(nodep->fileline(), setvscp, true), new AstConst(nodep->fileline(), 0)); AstAssign* setassignp - = new AstAssign(nodep->fileline(), - new AstVarRef(nodep->fileline(), setvscp, true), + = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), setvscp, true), new AstConst(nodep->fileline(), AstConst::LogicTrue())); nodep->addNextHere(setassignp); } @@ -299,7 +301,7 @@ private: // in correctly ordered code - the last assignment must be last. // It also has the nice side effect of assisting cache locality. AstNode* selectsp = varrefp; - for (int dimension=int(dimreadps.size())-1; dimension>=0; --dimension) { + for (int dimension = int(dimreadps.size()) - 1; dimension >= 0; --dimension) { selectsp = new AstArraySel(nodep->fileline(), selectsp, dimreadps[dimension]); } if (bitselp) { @@ -307,16 +309,16 @@ private: bitselp->widthp()->cloneTree(false)); } // Build "IF (changeit) ... - UINFO(9," For "<varScopep()->user4p(), AlwaysPost); if (finalp) { AstActive* oldactivep = VN_CAST(finalp->user2p(), Active); checkActivePost(varrefp, oldactivep); if (setinitp) oldactivep->addStmtsp(setinitp); } else { // first time we've dealt with this memory - finalp = new AstAlwaysPost(nodep->fileline(), NULL/*sens*/, NULL/*body*/); - UINFO(9," Created "<fileline(), NULL /*sens*/, NULL /*body*/); + UINFO(9, " Created " << finalp << endl); AstActive* newactp = createActivePost(varrefp); newactp->addStmtsp(finalp); varrefp->varScopep()->user4p(finalp); @@ -332,9 +334,8 @@ private: "Delayed assignment misoptimized; prev var found w/o associated IF"); } else { postLogicp = new AstIf(nodep->fileline(), - new AstVarRef(nodep->fileline(), setvscp, false), - NULL, NULL); - UINFO(9," Created "<fileline(), setvscp, false), NULL, NULL); + UINFO(9, " Created " << postLogicp << endl); finalp->addBodysp(postLogicp); finalp->user3p(setvscp); // Remember IF's vset variable finalp->user4p(postLogicp); // and the associated IF, as we may be able to reuse it @@ -345,12 +346,12 @@ private: // VISITORS virtual void visit(AstNetlist* nodep) VL_OVERRIDE { - //VV***** We reset all userp() on the netlist + // VV***** We reset all userp() on the netlist m_modVarMap.clear(); iterateChildren(nodep); } virtual void visit(AstScope* nodep) VL_OVERRIDE { - UINFO(4," MOD "<hasInitial(); - AstNode::user3ClearTree(); // Two sets to same variable in different actives must use different vars. + AstNode::user3ClearTree(); // Two sets to same variable in different + // actives must use different vars. iterateChildren(nodep); m_inInitial = oldinit; } virtual void visit(AstAssignDly* nodep) VL_OVERRIDE { m_inDly = true; - m_nextDlyp = VN_CAST(nodep->nextp(), AssignDly); // Next assignment in same block, maybe NULL. - if (m_cfuncp) nodep->v3error("Unsupported: Delayed assignment inside public function/task"); + m_nextDlyp + = VN_CAST(nodep->nextp(), AssignDly); // Next assignment in same block, maybe NULL. + if (m_cfuncp) { + nodep->v3error("Unsupported: Delayed assignment inside public function/task"); + } if (VN_IS(nodep->lhsp(), ArraySel) || (VN_IS(nodep->lhsp(), Sel) && VN_IS(VN_CAST(nodep->lhsp(), Sel)->fromp(), ArraySel))) { AstNode* lhsp = nodep->lhsp()->unlinkFrBack(); AstNode* newlhsp = createDlyArray(nodep, lhsp); - if (m_inLoop) nodep->v3warn(BLKLOOPINIT, "Unsupported: Delayed assignment to array inside for loops (non-delayed is ok - see docs)"); + if (m_inLoop) { + nodep->v3warn(BLKLOOPINIT, "Unsupported: Delayed assignment to array inside for " + "loops (non-delayed is ok - see docs)"); + } if (newlhsp) { nodep->lhsp(newlhsp); } else { VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } VL_DO_DANGLING(lhsp->deleteTree(), lhsp); - } - else { + } else { iterateChildren(nodep); } m_inDly = false; @@ -394,11 +401,12 @@ private: virtual void visit(AstVarRef* nodep) VL_OVERRIDE { if (!nodep->user2Inc()) { // Not done yet if (m_inDly && nodep->lvalue()) { - UINFO(4,"AssignDlyVar: "<varScopep(), VU_DLY); UASSERT_OBJ(m_activep, nodep, "<= not under sensitivity block"); if (!m_activep->hasClocked()) { - nodep->v3error("Internal: Blocking <= assignment in non-clocked block, should have converted in V3Active"); + nodep->v3error("Internal: Blocking <= assignment in non-clocked block, should " + "have converted in V3Active"); } AstVarScope* oldvscp = nodep->varScopep(); UASSERT_OBJ(oldvscp, nodep, "Var didn't get varscoped in V3Scope.cpp"); @@ -408,16 +416,14 @@ private: checkActivePost(nodep, oldactivep); } if (!dlyvscp) { // First use of this delayed variable - string newvarname = (string("__Vdly__")+nodep->varp()->shortName()); + string newvarname = (string("__Vdly__") + nodep->varp()->shortName()); dlyvscp = createVarSc(oldvscp, newvarname, 0, NULL); - AstNodeAssign* prep - = new AstAssignPre(nodep->fileline(), - new AstVarRef(nodep->fileline(), dlyvscp, true), - new AstVarRef(nodep->fileline(), oldvscp, false)); - AstNodeAssign* postp - = new AstAssignPost(nodep->fileline(), - new AstVarRef(nodep->fileline(), oldvscp, true), - new AstVarRef(nodep->fileline(), dlyvscp, false)); + AstNodeAssign* prep = new AstAssignPre( + nodep->fileline(), new AstVarRef(nodep->fileline(), dlyvscp, true), + new AstVarRef(nodep->fileline(), oldvscp, false)); + AstNodeAssign* postp = new AstAssignPost( + nodep->fileline(), new AstVarRef(nodep->fileline(), oldvscp, true), + new AstVarRef(nodep->fileline(), dlyvscp, false)); postp->lhsp()->user2(true); // Don't detect this assignment oldvscp->user1p(dlyvscp); // So we can find it later // Make new ACTIVE with identical sensitivity tree @@ -428,12 +434,12 @@ private: } AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, true); newrefp->user2(true); // No reason to do it again - nodep->replaceWith(newrefp); VL_DO_DANGLING(nodep->deleteTree(), nodep); - } - else if (!m_inDly && nodep->lvalue()) { - //UINFO(9,"NBA "<replaceWith(newrefp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); + } else if (!m_inDly && nodep->lvalue()) { + // UINFO(9, "NBA " << nodep << endl); if (!m_inInitial) { - UINFO(4,"AssignNDlyVar: "<varScopep(), VU_NONDLY); } } @@ -441,7 +447,8 @@ private: } virtual void visit(AstNodeFor* nodep) VL_OVERRIDE { - nodep->v3fatalSrc("For statements should have been converted to while statements in V3Begin"); + nodep->v3fatalSrc( + "For statements should have been converted to while statements in V3Begin"); } virtual void visit(AstWhile* nodep) VL_OVERRIDE { bool oldloop = m_inLoop; @@ -474,9 +481,7 @@ public: // Delayed class functions void V3Delayed::delayedAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Depth.cpp b/src/V3Depth.cpp index 9565a4a7a..ae23d3cd2 100644 --- a/src/V3Depth.cpp +++ b/src/V3Depth.cpp @@ -51,7 +51,7 @@ private: void createDeepTemp(AstNode* nodep) { UINFO(6, " Deep " << nodep << endl); - // if (debug()>=9) nodep->dumpTree(cout, "deep:"); + // if (debug() >= 9) nodep->dumpTree(cout, "deep:"); string newvarname = (string("__Vdeeptemp") + cvtToStr(m_modp->varNumGetInc())); AstVar* varp = new AstVar(nodep->fileline(), AstVarType::STMTTEMP, newvarname, diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp index 3b0beaa15..4f4966a60 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -258,7 +258,7 @@ private: nodep->varScopep(NULL); } virtual void visit(AstNodeCCall* nodep) VL_OVERRIDE { - // UINFO(9," "< VarVec; typedef std::map VarSortMap; // Map size class to VarVec - bool m_suppressSemi; - AstVarRef* m_wideTempRefp; // Variable that _WW macros should be setting - VarVec m_ctorVarsVec; // All variables in constructor order - int m_labelNum; // Next label number - int m_splitSize; // # of cfunc nodes placed into output file - int m_splitFilenum; // File number being created, 0 = primary + bool m_suppressSemi; + AstVarRef* m_wideTempRefp; // Variable that _WW macros should be setting + VarVec m_ctorVarsVec; // All variables in constructor order + int m_labelNum; // Next label number + int m_splitSize; // # of cfunc nodes placed into output file + int m_splitFilenum; // File number being created, 0 = primary public: // METHODS @@ -57,27 +57,37 @@ public: // ACCESSORS int splitFilenum() const { return m_splitFilenum; } - int splitFilenumInc() { m_splitSize = 0; return ++m_splitFilenum; } + int splitFilenumInc() { + m_splitSize = 0; + return ++m_splitFilenum; + } int splitSize() const { return m_splitSize; } void splitSizeInc(int count) { m_splitSize += count; } void splitSizeInc(AstNode* nodep) { splitSizeInc(EmitCBaseCounterVisitor(nodep).count()); } - bool splitNeeded() { return (splitSize() && v3Global.opt.outputSplit() - && v3Global.opt.outputSplit() < splitSize()); } + bool splitNeeded() { + return (splitSize() && v3Global.opt.outputSplit() + && v3Global.opt.outputSplit() < splitSize()); + } // METHODS - void displayNode(AstNode* nodep, AstScopeName* scopenamep, - const string& vformat, AstNode* exprsp, bool isScan); + void displayNode(AstNode* nodep, AstScopeName* scopenamep, const string& vformat, + AstNode* exprsp, bool isScan); void displayEmit(AstNode* nodep, bool isScan); - void displayArg(AstNode* dispp, AstNode** elistp, bool isScan, - const string& vfmt, char fmtLetter); + void displayArg(AstNode* dispp, AstNode** elistp, bool isScan, const string& vfmt, + char fmtLetter); void emitVarDecl(const AstVar* nodep, const string& prefixIfImp); - typedef enum {EVL_CLASS_IO, EVL_CLASS_SIG, EVL_CLASS_TEMP, EVL_CLASS_PAR, EVL_CLASS_ALL, - EVL_FUNC_ALL} EisWhich; + typedef enum { + EVL_CLASS_IO, + EVL_CLASS_SIG, + EVL_CLASS_TEMP, + EVL_CLASS_PAR, + EVL_CLASS_ALL, + EVL_FUNC_ALL + } EisWhich; void emitVarList(AstNode* firstp, EisWhich which, const string& prefixIfImp, string& sectionr); static void emitVarSort(const VarSortMap& vmap, VarVec* sortedp); - void emitSortedVarList(const VarVec& anons, - const VarVec& nonanons, const string& prefixIfImp); + void emitSortedVarList(const VarVec& anons, const VarVec& nonanons, const string& prefixIfImp); void emitVarCtors(bool* firstp); void emitCtorSep(bool* firstp); bool emitSimpleOk(AstNodeMath* nodep); @@ -87,34 +97,33 @@ public: } void emitScIQW(AstVar* nodep) { UASSERT_OBJ(nodep->isSc(), nodep, "emitting SystemC operator on non-SC variable"); + // clang-format off puts(nodep->isScBigUint() ? "SB" : nodep->isScUint() ? "SU" : nodep->isScBv() ? "SW" : (nodep->isScQuad() ? "SQ" : "SI")); + // clang-format on } - void emitOpName(AstNode* nodep, const string& format, - AstNode* lhsp, AstNode* rhsp, AstNode* thsp); + void emitOpName(AstNode* nodep, const string& format, AstNode* lhsp, AstNode* rhsp, + AstNode* thsp); void emitDeclArrayBrackets(const AstVar* nodep) { // This isn't very robust and may need cleanup for other data types for (const AstUnpackArrayDType* arrayp - = VN_CAST_CONST(nodep->dtypeSkipRefp(), UnpackArrayDType); - arrayp; - arrayp = VN_CAST_CONST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) { - puts("["+cvtToStr(arrayp->elementsConst())+"]"); + = VN_CAST_CONST(nodep->dtypeSkipRefp(), UnpackArrayDType); + arrayp; arrayp = VN_CAST_CONST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) { + puts("[" + cvtToStr(arrayp->elementsConst()) + "]"); } } void emitVarCmtChg(const AstVar* varp, string* curVarCmtp) { string newVarCmt = varp->mtasksString(); if (*curVarCmtp != newVarCmt) { *curVarCmtp = newVarCmt; - if (v3Global.opt.threads()) { - puts("// Begin mtask footprint "+*curVarCmtp+"\n"); - } + if (v3Global.opt.threads()) puts("// Begin mtask footprint " + *curVarCmtp + "\n"); } } void emitTypedefs(AstNode* firstp) { bool first = true; - for (AstNode* loopp=firstp; loopp; loopp = loopp->nextp()) { + for (AstNode* loopp = firstp; loopp; loopp = loopp->nextp()) { if (const AstTypedef* nodep = VN_CAST(loopp, Typedef)) { if (nodep->attrPublic()) { if (first) { @@ -126,12 +135,13 @@ public: } if (const AstEnumDType* adtypep = VN_CAST(nodep->dtypep()->skipRefToEnump(), EnumDType)) { - if (adtypep->width()>64) { - putsDecoration("// enum "+nodep->nameProtect()+" // Ignored: Too wide for C++\n"); + if (adtypep->width() > 64) { + putsDecoration("// enum " + nodep->nameProtect() + + " // Ignored: Too wide for C++\n"); } else { - puts("enum "+nodep->name()+" {\n"); - for (AstEnumItem* itemp = adtypep->itemsp(); - itemp; itemp = VN_CAST(itemp->nextp(), EnumItem)) { + puts("enum " + nodep->name() + " {\n"); + for (AstEnumItem* itemp = adtypep->itemsp(); itemp; + itemp = VN_CAST(itemp->nextp(), EnumItem)) { puts(itemp->nameProtect()); puts(" = "); iterateAndNextNull(itemp->valuep()); @@ -157,8 +167,7 @@ public: for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) { if (const AstCFunc* funcp = VN_CAST(nodep, CFunc)) { - if (!funcp->skipDecl() - && funcp->isMethod() == methodFuncs + if (!funcp->skipDecl() && funcp->isMethod() == methodFuncs && !funcp->dpiImport()) { // DPI is prototyped in __Dpi.h funcsp.push_back(funcp); } @@ -208,9 +217,10 @@ public: // VISITORS virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { - bool paren = true; bool decind = false; + bool paren = true; + bool decind = false; if (AstSel* selp = VN_CAST(nodep->lhsp(), Sel)) { - if (selp->widthMin()==1) { + if (selp->widthMin() == 1) { putbs("VL_ASSIGNBIT_"); emitIQW(selp->fromp()); if (nodep->rhsp()->isAllOnesV()) { @@ -218,18 +228,22 @@ public: } else { puts("I("); } - puts(cvtToStr(nodep->widthMin())+","); - iterateAndNextNull(selp->lsbp()); puts(", "); - iterateAndNextNull(selp->fromp()); puts(", "); + puts(cvtToStr(nodep->widthMin()) + ","); + iterateAndNextNull(selp->lsbp()); + puts(", "); + iterateAndNextNull(selp->fromp()); + puts(", "); } else { putbs("VL_ASSIGNSEL_"); emitIQW(selp->fromp()); puts("II"); emitIQW(nodep->rhsp()); puts("("); - puts(cvtToStr(nodep->widthMin())+","); - iterateAndNextNull(selp->lsbp()); puts(", "); - iterateAndNextNull(selp->fromp()); puts(", "); + puts(cvtToStr(nodep->widthMin()) + ","); + iterateAndNextNull(selp->lsbp()); + puts(", "); + iterateAndNextNull(selp->fromp()); + puts(", "); } } else if (AstGetcRefN* selp = VN_CAST(nodep->lhsp(), GetcRefN)) { iterateAndNextNull(selp->lhsp()); @@ -244,34 +258,37 @@ public: emitScIQW(varp); emitIQW(nodep); puts("("); - puts(cvtToStr(nodep->widthMin())+","); - iterateAndNextNull(nodep->lhsp()); puts(", "); + puts(cvtToStr(nodep->widthMin()) + ","); + iterateAndNextNull(nodep->lhsp()); + puts(", "); } else if (AstVar* varp = AstVar::scVarRecurse(nodep->rhsp())) { putbs("VL_ASSIGN_"); // Get a systemC variable emitIQW(nodep); emitScIQW(varp); puts("("); - puts(cvtToStr(nodep->widthMin())+","); - iterateAndNextNull(nodep->lhsp()); puts(", "); - } else if (nodep->isWide() - && VN_IS(nodep->lhsp(), VarRef) - && !VN_IS(nodep->rhsp(), CMath) - && !VN_IS(nodep->rhsp(), CMethodHard) - && !VN_IS(nodep->rhsp(), VarRef) - && !VN_IS(nodep->rhsp(), AssocSel) + puts(cvtToStr(nodep->widthMin()) + ","); + iterateAndNextNull(nodep->lhsp()); + puts(", "); + } else if (nodep->isWide() && VN_IS(nodep->lhsp(), VarRef) // + && !VN_IS(nodep->rhsp(), CMath) // + && !VN_IS(nodep->rhsp(), CMethodHard) // + && !VN_IS(nodep->rhsp(), VarRef) // + && !VN_IS(nodep->rhsp(), AssocSel) // && !VN_IS(nodep->rhsp(), ArraySel)) { // Wide functions assign into the array directly, don't need separate assign statement m_wideTempRefp = VN_CAST(nodep->lhsp(), VarRef); paren = false; } else if (nodep->isWide()) { putbs("VL_ASSIGN_W("); - puts(cvtToStr(nodep->widthMin())+","); - iterateAndNextNull(nodep->lhsp()); puts(", "); + puts(cvtToStr(nodep->widthMin()) + ","); + iterateAndNextNull(nodep->lhsp()); + puts(", "); } else { paren = false; iterateAndNextNull(nodep->lhsp()); puts(" "); - ofp()->blockInc(); decind = true; + ofp()->blockInc(); + decind = true; if (!VN_IS(nodep->rhsp(), Const)) ofp()->putBreak(); puts("= "); } @@ -280,8 +297,7 @@ public: if (decind) ofp()->blockDec(); if (!m_suppressSemi) puts(";\n"); } - virtual void visit(AstAlwaysPublic*) VL_OVERRIDE { - } + virtual void visit(AstAlwaysPublic*) VL_OVERRIDE {} virtual void visit(AstAssocSel* nodep) VL_OVERRIDE { iterateAndNextNull(nodep->fromp()); putbs(".at("); @@ -315,7 +331,7 @@ public: puts("("); puts(nodep->argTypes()); bool comma = (nodep->argTypes() != ""); - for (AstNode* subnodep=nodep->argsp(); subnodep; subnodep = subnodep->nextp()) { + for (AstNode* subnodep = nodep->argsp(); subnodep; subnodep = subnodep->nextp()) { if (comma) puts(", "); iterate(subnodep); comma = true; @@ -341,12 +357,11 @@ public: puts(")"); // Some are statements some are math. if (nodep->isStatement()) puts(";\n"); - UASSERT_OBJ(!nodep->isStatement() || VN_IS(nodep->dtypep(), VoidDType), - nodep, "Statement of non-void data type"); + UASSERT_OBJ(!nodep->isStatement() || VN_IS(nodep->dtypep(), VoidDType), nodep, + "Statement of non-void data type"); } virtual void visit(AstIntfRef* nodep) VL_OVERRIDE { - putsQuoted(VIdProtect::protectWordsIf(AstNode::vcdName(nodep->name()), - nodep->protect())); + putsQuoted(VIdProtect::protectWordsIf(AstNode::vcdName(nodep->name()), nodep->protect())); } virtual void visit(AstNodeCase* nodep) VL_OVERRIDE { // In V3Case... @@ -355,32 +370,39 @@ public: virtual void visit(AstComment* nodep) VL_OVERRIDE { string at; if (nodep->showAt()) { - at = " at "+nodep->fileline()->ascii(); + at = " at " + nodep->fileline()->ascii(); // If protecting, passthru less information about the design if (!v3Global.opt.protectIds()) return; } if (!(nodep->protect() && v3Global.opt.protectIds())) { - putsDecoration(string("// ")+nodep->name()+at+"\n"); + putsDecoration(string("// ") + nodep->name() + at + "\n"); } iterateChildren(nodep); } virtual void visit(AstCoverDecl* nodep) VL_OVERRIDE { puts("__vlCoverInsert("); // As Declared in emitCoverageDecl puts("&(vlSymsp->__Vcoverage["); - puts(cvtToStr(nodep->dataDeclThisp()->binNum())); puts("])"); + puts(cvtToStr(nodep->dataDeclThisp()->binNum())); + puts("])"); // If this isn't the first instantiation of this module under this // design, don't really count the bucket, and rely on verilator_cov to // aggregate counts. This is because Verilator combines all // hierarchies itself, and if verilator_cov also did it, you'd end up // with (number-of-instant) times too many counts in this bin. puts(", first"); // Enable, passed from __Vconfigure parameter - puts(", "); putsQuoted(protect(nodep->fileline()->filename())); - puts(", "); puts(cvtToStr(nodep->fileline()->lineno())); - puts(", "); puts(cvtToStr(nodep->column())); - puts(", "); putsQuoted((!nodep->hier().empty() ? "." : "") - +protectWordsIf(nodep->hier(), nodep->protect())); - puts(", "); putsQuoted(protectWordsIf(nodep->page(), nodep->protect())); - puts(", "); putsQuoted(protectWordsIf(nodep->comment(), nodep->protect())); + puts(", "); + putsQuoted(protect(nodep->fileline()->filename())); + puts(", "); + puts(cvtToStr(nodep->fileline()->lineno())); + puts(", "); + puts(cvtToStr(nodep->column())); + puts(", "); + putsQuoted((!nodep->hier().empty() ? "." : "") + + protectWordsIf(nodep->hier(), nodep->protect())); + puts(", "); + putsQuoted(protectWordsIf(nodep->page(), nodep->protect())); + puts(", "); + putsQuoted(protectWordsIf(nodep->comment(), nodep->protect())); puts(");\n"); } virtual void visit(AstCoverInc* nodep) VL_OVERRIDE { @@ -449,7 +471,7 @@ public: if (!nodep->dpiExport()) { // this is where the DPI import context scope is set string scope = nodep->scopeDpiName(); - putbs("(&(vlSymsp->"+protect("__Vscope_"+scope)+"))"); + putbs("(&(vlSymsp->" + protect("__Vscope_" + scope) + "))"); } } virtual void visit(AstSFormat* nodep) VL_OVERRIDE { @@ -496,8 +518,10 @@ public: void checkMaxWords(AstNode* nodep) { if (nodep->widthWords() > VL_TO_STRING_MAX_WORDS) { - nodep->v3error("String of "<width() - <<" bits exceeds hardcoded limit VL_TO_STRING_MAX_WORDS in verilatedos.h"); + nodep->v3error( + "String of " + << nodep->width() + << " bits exceeds hardcoded limit VL_TO_STRING_MAX_WORDS in verilatedos.h"); } } virtual void visit(AstFOpen* nodep) VL_OVERRIDE { @@ -505,7 +529,8 @@ public: puts(" = VL_FOPEN_"); emitIQW(nodep->filenamep()); emitIQW(nodep->modep()); - if (nodep->modep()->width()>4*8) nodep->modep()->v3error("$fopen mode should be <= 4 characters"); + if (nodep->modep()->width() > 4 * 8) + nodep->modep()->v3error("$fopen mode should be <= 4 characters"); puts("("); if (nodep->filenamep()->isWide()) { puts(cvtToStr(nodep->filenamep()->widthWords())); @@ -527,19 +552,18 @@ public: uint32_t array_lsb = 0; { const AstVarRef* varrefp = VN_CAST(nodep->memp(), VarRef); - if (!varrefp) { nodep->v3error(nodep->verilogKwd() << " loading non-variable"); } - else if (VN_IS(varrefp->varp()->dtypeSkipRefp(), AssocArrayDType)) { + if (!varrefp) { + nodep->v3error(nodep->verilogKwd() << " loading non-variable"); + } else if (VN_IS(varrefp->varp()->dtypeSkipRefp(), AssocArrayDType)) { // nodep->memp() below will when verilated code is compiled create a C++ template - } - else if (const AstUnpackArrayDType* adtypep - = VN_CAST(varrefp->varp()->dtypeSkipRefp(), UnpackArrayDType)) { + } else if (const AstUnpackArrayDType* adtypep + = VN_CAST(varrefp->varp()->dtypeSkipRefp(), UnpackArrayDType)) { putbs(", "); puts(cvtToStr(varrefp->varp()->dtypep()->arrayUnpackedElements())); array_lsb = adtypep->lsb(); putbs(", "); puts(cvtToStr(array_lsb)); - } - else { + } else { nodep->v3error(nodep->verilogKwd() << " loading other than unpacked/associative-array variable"); } @@ -549,10 +573,17 @@ public: putbs(", "); iterateAndNextNull(nodep->memp()); putbs(", "); - if (nodep->lsbp()) { iterateAndNextNull(nodep->lsbp()); } - else puts(cvtToStr(array_lsb)); + if (nodep->lsbp()) { + iterateAndNextNull(nodep->lsbp()); + } else { + puts(cvtToStr(array_lsb)); + } putbs(", "); - if (nodep->msbp()) { iterateAndNextNull(nodep->msbp()); } else puts("~VL_ULL(0)"); + if (nodep->msbp()) { + iterateAndNextNull(nodep->msbp()); + } else { + puts("~VL_ULL(0)"); + } puts(");\n"); } virtual void visit(AstFClose* nodep) VL_OVERRIDE { @@ -601,15 +632,15 @@ public: uint32_t array_size = 0; { const AstVarRef* varrefp = VN_CAST(nodep->memp(), VarRef); - if (!varrefp) { nodep->v3error(nodep->verilogKwd() << " loading non-variable"); } - else if (VN_CAST(varrefp->varp()->dtypeSkipRefp(), BasicDType)) { } - else if (const AstUnpackArrayDType* adtypep - = VN_CAST(varrefp->varp()->dtypeSkipRefp(), UnpackArrayDType)) { + if (!varrefp) { + nodep->v3error(nodep->verilogKwd() << " loading non-variable"); + } else if (VN_CAST(varrefp->varp()->dtypeSkipRefp(), BasicDType)) { + } else if (const AstUnpackArrayDType* adtypep + = VN_CAST(varrefp->varp()->dtypeSkipRefp(), UnpackArrayDType)) { memory = true; array_lsb = adtypep->lsb(); array_size = adtypep->elementsConst(); - } - else { + } else { nodep->v3error(nodep->verilogKwd() << " loading other than unpacked-array variable"); } @@ -624,11 +655,17 @@ public: putbs(", "); iterateAndNextNull(nodep->filep()); putbs(", "); - if (nodep->startp()) iterateAndNextNull(nodep->startp()); - else puts(cvtToStr(array_lsb)); + if (nodep->startp()) { + iterateAndNextNull(nodep->startp()); + } else { + puts(cvtToStr(array_lsb)); + } putbs(", "); - if (nodep->countp()) iterateAndNextNull(nodep->countp()); - else puts(cvtToStr(array_size)); + if (nodep->countp()) { + iterateAndNextNull(nodep->countp()); + } else { + puts(cvtToStr(array_size)); + } puts(");\n"); } virtual void visit(AstSysFuncAsTask* nodep) VL_OVERRIDE { @@ -661,14 +698,14 @@ public: puts(")"); } virtual void visit(AstJumpGo* nodep) VL_OVERRIDE { - puts("goto __Vlabel"+cvtToStr(nodep->labelp()->labelNum())+";\n"); + puts("goto __Vlabel" + cvtToStr(nodep->labelp()->labelNum()) + ";\n"); } virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE { nodep->labelNum(++m_labelNum); puts("{\n"); // Make it visually obvious label jumps outside these iterateAndNextNull(nodep->stmtsp()); puts("}\n"); - puts("__Vlabel"+cvtToStr(nodep->labelNum())+": ;\n"); + puts("__Vlabel" + cvtToStr(nodep->labelNum()) + ": ;\n"); } virtual void visit(AstWhile* nodep) VL_OVERRIDE { iterateAndNextNull(nodep->precondsp()); @@ -683,7 +720,8 @@ public: virtual void visit(AstNodeIf* nodep) VL_OVERRIDE { puts("if ("); if (!nodep->branchPred().unknown()) { - puts(nodep->branchPred().ascii()); puts("("); + puts(nodep->branchPred().ascii()); + puts("("); } iterateAndNextNull(nodep->condp()); if (!nodep->branchPred().unknown()) puts(")"); @@ -733,13 +771,13 @@ public: iterateAndNextNull(nodep->bodysp()); } virtual void visit(AstUCStmt* nodep) VL_OVERRIDE { - putsDecoration(ifNoProtect("// $c statement at "+nodep->fileline()->ascii()+"\n")); + putsDecoration(ifNoProtect("// $c statement at " + nodep->fileline()->ascii() + "\n")); iterateAndNextNull(nodep->bodysp()); puts("\n"); } virtual void visit(AstUCFunc* nodep) VL_OVERRIDE { puts("\n"); - putsDecoration(ifNoProtect("// $c function at "+nodep->fileline()->ascii()+"\n")); + putsDecoration(ifNoProtect("// $c function at " + nodep->fileline()->ascii() + "\n")); iterateAndNextNull(nodep->bodysp()); puts("\n"); } @@ -750,17 +788,24 @@ public: } virtual void visit(AstNodeUniop* nodep) VL_OVERRIDE { if (emitSimpleOk(nodep)) { - putbs("("); puts(nodep->emitSimpleOperator()); puts(" "); - iterateAndNextNull(nodep->lhsp()); puts(")"); + putbs("("); + puts(nodep->emitSimpleOperator()); + puts(" "); + iterateAndNextNull(nodep->lhsp()); + puts(")"); } else { emitOpName(nodep, nodep->emitC(), nodep->lhsp(), NULL, NULL); } } virtual void visit(AstNodeBiop* nodep) VL_OVERRIDE { if (emitSimpleOk(nodep)) { - putbs("("); iterateAndNextNull(nodep->lhsp()); - puts(" "); putbs(nodep->emitSimpleOperator()); puts(" "); - iterateAndNextNull(nodep->rhsp()); puts(")"); + putbs("("); + iterateAndNextNull(nodep->lhsp()); + puts(" "); + putbs(nodep->emitSimpleOperator()); + puts(" "); + iterateAndNextNull(nodep->rhsp()); + puts(")"); } else { emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), NULL); } @@ -782,36 +827,41 @@ public: } virtual void visit(AstMulS* nodep) VL_OVERRIDE { if (nodep->widthWords() > VL_MULS_MAX_WORDS) { - nodep->v3error("Unsupported: Signed multiply of "<width() - <<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); + nodep->v3error("Unsupported: Signed multiply of " + << nodep->width() + << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); } visit(VN_CAST(nodep, NodeBiop)); } virtual void visit(AstPow* nodep) VL_OVERRIDE { if (nodep->widthWords() > VL_MULS_MAX_WORDS) { - nodep->v3error("Unsupported: Power of "<width() - <<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); + nodep->v3error("Unsupported: Power of " + << nodep->width() + << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); } visit(VN_CAST(nodep, NodeBiop)); } virtual void visit(AstPowSS* nodep) VL_OVERRIDE { if (nodep->widthWords() > VL_MULS_MAX_WORDS) { - nodep->v3error("Unsupported: Power of "<width() - <<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); + nodep->v3error("Unsupported: Power of " + << nodep->width() + << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); } visit(VN_CAST(nodep, NodeBiop)); } virtual void visit(AstPowSU* nodep) VL_OVERRIDE { if (nodep->widthWords() > VL_MULS_MAX_WORDS) { - nodep->v3error("Unsupported: Power of "<width() - <<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); + nodep->v3error("Unsupported: Power of " + << nodep->width() + << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); } visit(VN_CAST(nodep, NodeBiop)); } virtual void visit(AstPowUS* nodep) VL_OVERRIDE { if (nodep->widthWords() > VL_MULS_MAX_WORDS) { - nodep->v3error("Unsupported: Power of "<width() - <<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); + nodep->v3error("Unsupported: Power of " + << nodep->width() + << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); } visit(VN_CAST(nodep, NodeBiop)); } @@ -831,9 +881,12 @@ public: emitOpName(nodep, nodep->emitC(), nodep->condp(), nodep->expr1p(), nodep->expr2p()); } else { putbs("("); - iterateAndNextNull(nodep->condp()); putbs(" ? "); - iterateAndNextNull(nodep->expr1p()); putbs(" : "); - iterateAndNextNull(nodep->expr2p()); puts(")"); + iterateAndNextNull(nodep->condp()); + putbs(" ? "); + iterateAndNextNull(nodep->expr1p()); + putbs(" : "); + iterateAndNextNull(nodep->expr2p()); + puts(")"); } } virtual void visit(AstMemberSel* nodep) VL_OVERRIDE { @@ -870,17 +923,20 @@ public: virtual void visit(AstReplicate* nodep) VL_OVERRIDE { if (nodep->lhsp()->widthMin() == 1 && !nodep->isWide()) { UASSERT_OBJ((static_cast(VN_CAST(nodep->rhsp(), Const)->toUInt()) - * nodep->lhsp()->widthMin()) == nodep->widthMin(), + * nodep->lhsp()->widthMin()) + == nodep->widthMin(), nodep, "Replicate non-constant or width miscomputed"); puts("VL_REPLICATE_"); emitIQW(nodep); puts("OI("); puts(cvtToStr(nodep->widthMin())); - if (nodep->lhsp()) { puts(","+cvtToStr(nodep->lhsp()->widthMin())); } - if (nodep->rhsp()) { puts(","+cvtToStr(nodep->rhsp()->widthMin())); } + if (nodep->lhsp()) { puts("," + cvtToStr(nodep->lhsp()->widthMin())); } + if (nodep->rhsp()) { puts("," + cvtToStr(nodep->rhsp()->widthMin())); } puts(","); - iterateAndNextNull(nodep->lhsp()); puts(", "); - iterateAndNextNull(nodep->rhsp()); puts(")"); + iterateAndNextNull(nodep->lhsp()); + puts(", "); + iterateAndNextNull(nodep->rhsp()); + puts(")"); } else { emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), NULL); } @@ -896,17 +952,18 @@ public: emitIQW(nodep->lhsp()); puts("I("); puts(cvtToStr(nodep->widthMin())); - puts(","+cvtToStr(nodep->lhsp()->widthMin())); - puts(","+cvtToStr(nodep->rhsp()->widthMin())); + puts("," + cvtToStr(nodep->lhsp()->widthMin())); + puts("," + cvtToStr(nodep->rhsp()->widthMin())); puts(","); - iterateAndNextNull(nodep->lhsp()); puts(", "); + iterateAndNextNull(nodep->lhsp()); + puts(", "); uint32_t rd_log2 = V3Number::log2b(VN_CAST(nodep->rhsp(), Const)->toUInt()); - puts(cvtToStr(rd_log2)+")"); + puts(cvtToStr(rd_log2) + ")"); return; } } - emitOpName(nodep, "VL_STREAML_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)", - nodep->lhsp(), nodep->rhsp(), NULL); + emitOpName(nodep, "VL_STREAML_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)", nodep->lhsp(), + nodep->rhsp(), NULL); } // Terminals virtual void visit(AstVarRef* nodep) VL_OVERRIDE { @@ -923,7 +980,8 @@ public: emitIQW(nodep); puts("("); if (nodep->isWide()) { - puts(cvtToStr(nodep->widthWords())); // Note argument width, not node width (which is always 32) + // Note argument width, not node width (which is always 32) + puts(cvtToStr(nodep->widthWords())); puts(", "); } iterateAndNextNull(nodep); @@ -943,11 +1001,11 @@ public: int chunks = 0; if (upWidth > EMITC_NUM_CONSTW * VL_EDATASIZE) { // Output e.g. 8 words in groups of e.g. 8 - chunks = (upWidth-1) / (EMITC_NUM_CONSTW * VL_EDATASIZE); + chunks = (upWidth - 1) / (EMITC_NUM_CONSTW * VL_EDATASIZE); upWidth %= (EMITC_NUM_CONSTW * VL_EDATASIZE); if (upWidth == 0) upWidth = (EMITC_NUM_CONSTW * VL_EDATASIZE); } - { // Upper e.g. 8 words + { // Upper e.g. 8 words if (chunks) { putbs("VL_CONSTHI_W_"); puts(cvtToStr(VL_WORDS_I(upWidth))); @@ -970,11 +1028,11 @@ public: } else { iterateAndNextNull(assigntop); } - for (int word=VL_WORDS_I(upWidth)-1; word>=0; word--) { + for (int word = VL_WORDS_I(upWidth) - 1; word >= 0; word--) { // Only 32 bits - llx + long long here just to appease CPP format warning ofp()->printf(",0x%08" VL_PRI64 "x", - static_cast(nodep->num().edataWord - (word+chunks * EMITC_NUM_CONSTW))); + static_cast( + nodep->num().edataWord(word + chunks * EMITC_NUM_CONSTW))); } puts(")"); } @@ -993,18 +1051,17 @@ public: } else { iterateAndNextNull(assigntop); } - for (int word=EMITC_NUM_CONSTW-1; word>=0; word--) { + for (int word = EMITC_NUM_CONSTW - 1; word >= 0; word--) { // Only 32 bits - llx + long long here just to appease CPP format warning ofp()->printf(",0x%08" VL_PRI64 "x", - static_cast(nodep->num().edataWord - (word+chunks * EMITC_NUM_CONSTW))); + static_cast( + nodep->num().edataWord(word + chunks * EMITC_NUM_CONSTW))); } puts(")"); } } else if (nodep->isDouble()) { if (int(nodep->num().toDouble()) == nodep->num().toDouble() - && nodep->num().toDouble() < 1000 - && nodep->num().toDouble() > -1000) { + && nodep->num().toDouble() < 1000 && nodep->num().toDouble() > -1000) { ofp()->printf("%3.1f", nodep->num().toDouble()); // Force decimal point } else { // Not %g as will not always put in decimal point, so not obvious to compiler @@ -1013,13 +1070,19 @@ public: } } else if (nodep->isQuad()) { vluint64_t num = nodep->toUQuad(); - if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "u)", num); - else ofp()->printf("VL_ULL(0x%" VL_PRI64 "x)", num); + if (num < 10) { + ofp()->printf("VL_ULL(%" VL_PRI64 "u)", num); + } else { + ofp()->printf("VL_ULL(0x%" VL_PRI64 "x)", num); + } } else { uint32_t num = nodep->toUInt(); // Only 32 bits - llx + long long here just to appease CPP format warning - if (num<10) puts(cvtToStr(num)); - else ofp()->printf("0x%" VL_PRI64 "x", static_cast(num)); + if (num < 10) { + puts(cvtToStr(num)); + } else { + ofp()->printf("0x%" VL_PRI64 "x", static_cast(num)); + } // If signed, we'll do our own functions // But must be here, or <= comparisons etc may end up signed puts("U"); @@ -1044,15 +1107,9 @@ public: } // Just iterate - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { - iterateChildren(nodep); - } - virtual void visit(AstTopScope* nodep) VL_OVERRIDE { - iterateChildren(nodep); - } - virtual void visit(AstScope* nodep) VL_OVERRIDE { - iterateChildren(nodep); - } + virtual void visit(AstNetlist* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstTopScope* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstScope* nodep) VL_OVERRIDE { iterateChildren(nodep); } // NOPs virtual void visit(AstTypedef*) VL_OVERRIDE {} virtual void visit(AstPragma*) VL_OVERRIDE {} @@ -1062,13 +1119,13 @@ public: virtual void visit(AstTraceDecl*) VL_OVERRIDE {} // Handled outside the Visit class virtual void visit(AstTraceInc*) VL_OVERRIDE {} // Handled outside the Visit class virtual void visit(AstCFile*) VL_OVERRIDE {} // Handled outside the Visit class - virtual void visit(AstCellInline*) VL_OVERRIDE {} // Handled outside the Visit class (EmitCSyms) + virtual void visit(AstCellInline*) VL_OVERRIDE {} // Handled outside visit (in EmitCSyms) virtual void visit(AstCUse*) VL_OVERRIDE {} // Handled outside the Visit class // Default virtual void visit(AstNode* nodep) VL_OVERRIDE { - puts(string("\n???? // ")+nodep->prettyTypeName()+"\n"); + puts(string("\n???? // ") + nodep->prettyTypeName() + "\n"); iterateChildren(nodep); - nodep->v3fatalSrc("Unknown node type reached emitter: "<prettyTypeName()); + nodep->v3fatalSrc("Unknown node type reached emitter: " << nodep->prettyTypeName()); } void init() { @@ -1080,10 +1137,8 @@ public: } public: - EmitCStmts() { - init(); - } - EmitCStmts(AstNode* nodep, V3OutCFile* ofp, bool trackText=false) { + EmitCStmts() { init(); } + EmitCStmts(AstNode* nodep, V3OutCFile* ofp, bool trackText = false) { init(); m_ofp = ofp; m_trackText = trackText; @@ -1104,16 +1159,14 @@ private: public: // CONSTRUCTORS explicit EmitVarTspSorter(const MTaskIdSet& mtaskIds) - : m_mtaskIds(mtaskIds), - m_serial(++m_serialNext) {} + : m_mtaskIds(mtaskIds) + , m_serial(++m_serialNext) {} virtual ~EmitVarTspSorter() {} // METHODS bool operator<(const TspStateBase& other) const { return operator<(dynamic_cast(other)); } - bool operator<(const EmitVarTspSorter& other) const { - return m_serial < other.m_serial; - } + bool operator<(const EmitVarTspSorter& other) const { return m_serial < other.m_serial; } const MTaskIdSet& mtaskIds() const { return m_mtaskIds; } virtual int cost(const TspStateBase* otherp) const { return cost(dynamic_cast(otherp)); @@ -1126,8 +1179,7 @@ public: // Returns the number of elements in set_a that don't appear in set_b static int diffs(const MTaskIdSet& set_a, const MTaskIdSet& set_b) { int diffs = 0; - for (MTaskIdSet::iterator it = set_a.begin(); - it != set_a.end(); ++it) { + for (MTaskIdSet::iterator it = set_a.begin(); it != set_a.end(); ++it) { if (set_b.find(*it) == set_b.end()) ++diffs; } return diffs; @@ -1141,10 +1193,10 @@ unsigned EmitVarTspSorter::m_serialNext = 0; class EmitCImp : EmitCStmts { // MEMBERS - AstNodeModule* m_modp; + AstNodeModule* m_modp; std::vector m_blkChangeDetVec; // All encountered changes in block - bool m_slow; // Creating __Slow file - bool m_fast; // Creating non __Slow file (or both) + bool m_slow; // Creating __Slow file + bool m_fast; // Creating non __Slow file (or both) //--------------------------------------- // METHODS @@ -1153,18 +1205,19 @@ class EmitCImp : EmitCStmts { // cppcheck-suppress variableScope static int s_addDoubleOr = 10; // Determined experimentally as best if (!changep->rhsp()) { - if (!gotOne) gotOne = true; - else puts(" | "); + if (!gotOne) { + gotOne = true; + } else { + puts(" | "); + } iterateAndNextNull(changep->lhsp()); - } - else { + } else { AstNode* lhsp = changep->lhsp(); AstNode* rhsp = changep->rhsp(); UASSERT_OBJ(VN_IS(lhsp, VarRef) || VN_IS(lhsp, ArraySel), changep, "Not ref?"); UASSERT_OBJ(VN_IS(rhsp, VarRef) || VN_IS(rhsp, ArraySel), changep, "Not ref?"); - for (int word=0; - word < (changep->lhsp()->isWide() ? changep->lhsp()->widthWords() : 1); - ++word) { + for (int word = 0; + word < (changep->lhsp()->isWide() ? changep->lhsp()->widthWords() : 1); ++word) { if (!gotOne) { gotOne = true; s_addDoubleOr = 10; @@ -1176,17 +1229,20 @@ class EmitCImp : EmitCStmts { puts(" | ("); } iterateAndNextNull(changep->lhsp()); - if (changep->lhsp()->isWide()) puts("["+cvtToStr(word)+"]"); - if (changep->lhsp()->isDouble()) puts(" != "); - else puts(" ^ "); + if (changep->lhsp()->isWide()) puts("[" + cvtToStr(word) + "]"); + if (changep->lhsp()->isDouble()) { + puts(" != "); + } else { + puts(" ^ "); + } iterateAndNextNull(changep->rhsp()); - if (changep->lhsp()->isWide()) puts("["+cvtToStr(word)+"]"); + if (changep->lhsp()->isWide()) puts("[" + cvtToStr(word) + "]"); puts(")"); } } } - V3OutCFile* newOutCFile(AstNodeModule* modp, bool slow, bool source, int filenum=0) { + V3OutCFile* newOutCFile(AstNodeModule* modp, bool slow, bool source, int filenum = 0) { string filenameNoExt = v3Global.opt.makeDir() + "/" + prefixNameProtect(modp); if (filenum) filenameNoExt += "__" + cvtToStr(filenum); filenameNoExt += (slow ? "__Slow" : ""); @@ -1197,32 +1253,34 @@ class EmitCImp : EmitCStmts { string filename = VL_DEV_NULL; newCFile(filename, slow, source); ofp = new V3OutCFile(filename); - } - else if (optSystemC()) { - string filename = filenameNoExt+(source?".cpp":".h"); + } else if (optSystemC()) { + string filename = filenameNoExt + (source ? ".cpp" : ".h"); newCFile(filename, slow, source); ofp = new V3OutScFile(filename); - } - else { - string filename = filenameNoExt+(source?".cpp":".h"); + } else { + string filename = filenameNoExt + (source ? ".cpp" : ".h"); newCFile(filename, slow, source); ofp = new V3OutCFile(filename); } ofp->putsHeader(); if (modp->isTop() && !source) { - ofp->puts("// DESCR" "IPTION: Verilator output: Primary design header\n"); + ofp->puts("// DESCR" + "IPTION: Verilator output: Primary design header\n"); ofp->puts("//\n"); - ofp->puts("// This header should be included by all source files instantiating the design.\n"); + ofp->puts("// This header should be included by all source files instantiating the " + "design.\n"); ofp->puts("// The class here is then constructed to instantiate the design.\n"); ofp->puts("// See the Verilator manual for examples.\n"); } else { if (source) { - ofp->puts("// DESCR" "IPTION: Verilator output: Design implementation internals\n"); + ofp->puts("// DESCR" + "IPTION: Verilator output: Design implementation internals\n"); } else { - ofp->puts("// DESCR" "IPTION: Verilator output: Design internal header\n"); + ofp->puts("// DESCR" + "IPTION: Verilator output: Design internal header\n"); } - ofp->puts("// See "+v3Global.opt.prefix()+".h for the primary calling header\n"); + ofp->puts("// See " + v3Global.opt.prefix() + ".h for the primary calling header\n"); } return ofp; } @@ -1234,9 +1292,7 @@ class EmitCImp : EmitCStmts { uint32_t result = 0; for (V3GraphEdge* edgep = mtaskp->inBeginp(); edgep; edgep = edgep->inNextp()) { const ExecMTask* prevp = dynamic_cast(edgep->fromp()); - if (prevp->thread() != mtaskp->thread()) { - ++result; - } + if (prevp->thread() != mtaskp->thread()) ++result; } return result; } @@ -1254,10 +1310,10 @@ class EmitCImp : EmitCStmts { puts("VlProfileRec* " + recName + " = NULL;\n"); // Leave this if() here, as don't want to call VL_RDTSC_Q unless profiling puts("if (VL_UNLIKELY(vlTOPp->__Vm_profile_cycle_start)) {\n"); - puts( recName + " = vlTOPp->__Vm_threadPoolp->profileAppend();\n"); - puts( recName + "->startRecord(VL_RDTSC_Q() - vlTOPp->__Vm_profile_cycle_start,"); - puts( " "+cvtToStr(curExecMTaskp->id())+ ","); - puts( " "+cvtToStr(curExecMTaskp->cost())+");\n"); + puts(recName + " = vlTOPp->__Vm_threadPoolp->profileAppend();\n"); + puts(recName + "->startRecord(VL_RDTSC_Q() - vlTOPp->__Vm_profile_cycle_start,"); + puts(" " + cvtToStr(curExecMTaskp->id()) + ","); + puts(" " + cvtToStr(curExecMTaskp->cost()) + ");\n"); puts("}\n"); } puts("Verilated::mtaskId(" + cvtToStr(curExecMTaskp->id()) + ");\n"); @@ -1267,8 +1323,8 @@ class EmitCImp : EmitCStmts { if (v3Global.opt.profThreads()) { // Leave this if() here, as don't want to call VL_RDTSC_Q unless profiling - puts("if (VL_UNLIKELY("+recName+")) {\n"); - puts( recName + "->endRecord(VL_RDTSC_Q() - vlTOPp->__Vm_profile_cycle_start);\n"); + puts("if (VL_UNLIKELY(" + recName + ")) {\n"); + puts(recName + "->endRecord(VL_RDTSC_Q() - vlTOPp->__Vm_profile_cycle_start);\n"); puts("}\n"); } @@ -1277,11 +1333,10 @@ class EmitCImp : EmitCStmts { // For any downstream mtask that's on another thread, bump its // counter and maybe notify it. - for (V3GraphEdge* edgep = curExecMTaskp->outBeginp(); - edgep; edgep = edgep->outNextp()) { + for (V3GraphEdge* edgep = curExecMTaskp->outBeginp(); edgep; edgep = edgep->outNextp()) { const ExecMTask* nextp = dynamic_cast(edgep->top()); if (nextp->thread() != curExecMTaskp->thread()) { - puts("vlTOPp->__Vm_mt_"+cvtToStr(nextp->id()) + puts("vlTOPp->__Vm_mt_" + cvtToStr(nextp->id()) + ".signalUpstreamDone(even_cycle);\n"); } } @@ -1304,9 +1359,9 @@ class EmitCImp : EmitCStmts { puts("(bool even_cycle, void* symtab) {\n"); // Declare and set vlSymsp - puts(EmitCBaseVisitor::symClassVar() + " = (" - + EmitCBaseVisitor::symClassName() + "*)symtab;\n"); - puts(EmitCBaseVisitor::symTopAssign()+"\n"); + puts(EmitCBaseVisitor::symClassVar() + " = (" + EmitCBaseVisitor::symClassName() + + "*)symtab;\n"); + puts(EmitCBaseVisitor::symTopAssign() + "\n"); emitMTaskBody(nodep); puts("}\n"); @@ -1326,7 +1381,7 @@ class EmitCImp : EmitCStmts { splitSizeInc(nodep); puts("\n"); - if (nodep->ifdef()!="") puts("#ifdef "+nodep->ifdef()+"\n"); + if (nodep->ifdef() != "") puts("#ifdef " + nodep->ifdef() + "\n"); if (nodep->isInline()) puts("VL_INLINE_OPT "); if (!nodep->isConstructor() && !nodep->isDestructor()) { puts(nodep->rtnTypeVoid()); @@ -1341,21 +1396,21 @@ class EmitCImp : EmitCStmts { // "+" in the debug indicates a print from the model puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+ "); - for (int i=0; ilevel(); ++i) { puts(" "); } + for (int i = 0; i < m_modp->level(); ++i) { puts(" "); } puts(prefixNameProtect(m_modp) + "::" + nodep->nameProtect() + "\\n\"); );\n"); // Declare and set vlTOPp - if (nodep->symProlog()) puts(EmitCBaseVisitor::symTopAssign()+"\n"); + if (nodep->symProlog()) puts(EmitCBaseVisitor::symTopAssign() + "\n"); if (nodep->initsp()) putsDecoration("// Variables\n"); - for (AstNode* subnodep=nodep->argsp(); subnodep; subnodep = subnodep->nextp()) { + for (AstNode* subnodep = nodep->argsp(); subnodep; subnodep = subnodep->nextp()) { if (AstVar* varp = VN_CAST(subnodep, Var)) { if (varp->isFuncReturn()) emitVarDecl(varp, ""); } } string section; - emitVarList(nodep->initsp(), EVL_FUNC_ALL, "", section/*ref*/); - emitVarList(nodep->stmtsp(), EVL_FUNC_ALL, "", section/*ref*/); + emitVarList(nodep->initsp(), EVL_FUNC_ALL, "", section /*ref*/); + emitVarList(nodep->stmtsp(), EVL_FUNC_ALL, "", section /*ref*/); iterateAndNextNull(nodep->initsp()); @@ -1369,14 +1424,15 @@ class EmitCImp : EmitCStmts { if (!m_blkChangeDetVec.empty()) puts("return __req;\n"); - //puts("__Vm_activity = true;\n"); + // puts("__Vm_activity = true;\n"); puts("}\n"); - if (nodep->ifdef()!="") puts("#endif // "+nodep->ifdef()+"\n"); + if (nodep->ifdef() != "") puts("#endif // " + nodep->ifdef() + "\n"); } void emitChangeDet() { putsDecoration("// Change detection\n"); - puts("QData __req = false; // Logically a bool\n"); // But not because it results in faster code + puts("QData __req = false; // Logically a bool\n"); // But not because it results in + // faster code bool gotOne = false; for (std::vector::iterator it = m_blkChangeDetVec.begin(); it != m_blkChangeDetVec.end(); ++it) { @@ -1384,14 +1440,15 @@ class EmitCImp : EmitCStmts { if (changep->lhsp()) { if (!gotOne) { // Not a clocked block puts("__req |= ("); + } else { + puts("\n"); } - else puts("\n"); doubleOrDetect(changep, gotOne); } } if (gotOne) puts(");\n"); if (gotOne && !v3Global.opt.protectIds()) { - //puts("VL_DEBUG_IF( if (__req) cout<<\"- CLOCKREQ );"); + // puts("VL_DEBUG_IF( if (__req) cout<<\"- CLOCKREQ );"); for (std::vector::iterator it = m_blkChangeDetVec.begin(); it != m_blkChangeDetVec.end(); ++it) { AstChangeDet* nodep = *it; @@ -1401,18 +1458,18 @@ class EmitCImp : EmitCStmts { doubleOrDetect(nodep, gotOneIgnore); string varname; if (VN_IS(nodep->lhsp(), VarRef)) { - varname = ": "+VN_CAST(nodep->lhsp(), VarRef)->varp()->prettyName(); + varname = ": " + VN_CAST(nodep->lhsp(), VarRef)->varp()->prettyName(); } puts(")) VL_DBG_MSGF(\" CHANGE: "); puts(protect(nodep->fileline()->filename())); - puts(":"+cvtToStr(nodep->fileline()->lineno())); - puts(varname+"\\n\"); );\n"); + puts(":" + cvtToStr(nodep->fileline()->lineno())); + puts(varname + "\\n\"); );\n"); } } } } - virtual void visit(AstChangeDet* nodep) VL_OVERRIDE { + virtual void visit(AstChangeDet* nodep) VL_OVERRIDE { // m_blkChangeDetVec.push_back(nodep); } @@ -1437,13 +1494,13 @@ class EmitCImp : EmitCStmts { std::vector execMTasks; // Start each root mtask - for (const V3GraphVertex* vxp = nodep->depGraphp()->verticesBeginp(); - vxp; vxp = vxp->verticesNextp()) { + for (const V3GraphVertex* vxp = nodep->depGraphp()->verticesBeginp(); vxp; + vxp = vxp->verticesNextp()) { const ExecMTask* etp = dynamic_cast(vxp); if (etp->threadRoot()) execMTasks.push_back(etp); } - UASSERT_OBJ(execMTasks.size() <= static_cast(v3Global.opt.threads()), - nodep, "More root mtasks than available threads"); + UASSERT_OBJ(execMTasks.size() <= static_cast(v3Global.opt.threads()), nodep, + "More root mtasks than available threads"); if (!execMTasks.empty()) { for (uint32_t i = 0; i < execMTasks.size(); ++i) { @@ -1456,8 +1513,7 @@ class EmitCImp : EmitCStmts { puts("Verilated::mtaskId(0);\n"); } else { // The other N-1 go to the thread pool. - puts("vlTOPp->__Vm_threadPoolp->workerp(" - + cvtToStr(i)+")->addTask(" + puts("vlTOPp->__Vm_threadPoolp->workerp(" + cvtToStr(i) + ")->addTask(" + protect(execMTasks[i]->cFuncName()) + ", vlTOPp->__Vm_even_cycle, vlSymsp);\n"); } @@ -1497,24 +1553,23 @@ class EmitCImp : EmitCStmts { UASSERT_OBJ(varp->valuep(), varp, "No init for a param?"); // If a simple CONST value we initialize it using an enum // If an ARRAYINIT we initialize it using an initial block similar to a signal - //puts("// parameter "+varp->nameProtect()+" = "+varp->valuep()->name()+"\n"); + // puts("// parameter "+varp->nameProtect()+" = "+varp->valuep()->name()+"\n"); } else if (AstInitArray* initarp = VN_CAST(varp->valuep(), InitArray)) { if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) { if (initarp->defaultp()) { // MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block puts("{ int __Vi=0;"); - puts(" for (; __Vi<"+cvtToStr(adtypep->elementsConst())); + puts(" for (; __Vi<" + cvtToStr(adtypep->elementsConst())); puts("; ++__Vi) {\n"); - emitSetVarConstant(varp->nameProtect()+"[__Vi]", + emitSetVarConstant(varp->nameProtect() + "[__Vi]", VN_CAST(initarp->defaultp(), Const)); puts("}}\n"); } const AstInitArray::KeyItemMap& mapr = initarp->map(); - for (AstInitArray::KeyItemMap::const_iterator it = mapr.begin(); - it != mapr.end(); ++it) { + for (AstInitArray::KeyItemMap::const_iterator it = mapr.begin(); it != mapr.end(); + ++it) { AstNode* valuep = it->second->valuep(); - emitSetVarConstant(varp->nameProtect() - +"["+cvtToStr(it->first)+"]", + emitSetVarConstant(varp->nameProtect() + "[" + cvtToStr(it->first) + "]", VN_CAST(valuep, Const)); } } else { @@ -1530,49 +1585,48 @@ class EmitCImp : EmitCStmts { AstBasicDType* basicp = dtypep->basicp(); // Returns string to do resetting, empty to do nothing (which caller should handle) if (AstAssocArrayDType* adtypep = VN_CAST(dtypep, AssocArrayDType)) { - string cvtarray = (adtypep->subDTypep()->isWide() ? ".data()" : ""); // Access std::array as C array - return emitVarResetRecurse(varp, adtypep->subDTypep(), depth+1, + string cvtarray + = (adtypep->subDTypep()->isWide() ? ".data()" + : ""); // Access std::array as C array + return emitVarResetRecurse(varp, adtypep->subDTypep(), depth + 1, ".atDefault()" + cvtarray); - } - else if (AstClassRefDType* adtypep = VN_CAST(dtypep, ClassRefDType)) { + } else if (AstClassRefDType* adtypep = VN_CAST(dtypep, ClassRefDType)) { return ""; // Constructor does it - } - else if (AstDynArrayDType* adtypep = VN_CAST(dtypep, DynArrayDType)) { - return emitVarResetRecurse(varp, adtypep->subDTypep(), depth+1, ".atDefault()"); - } - else if (AstQueueDType* adtypep = VN_CAST(dtypep, QueueDType)) { - return emitVarResetRecurse(varp, adtypep->subDTypep(), depth+1, ".atDefault()"); - } - else if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) { + } else if (AstDynArrayDType* adtypep = VN_CAST(dtypep, DynArrayDType)) { + return emitVarResetRecurse(varp, adtypep->subDTypep(), depth + 1, ".atDefault()"); + } else if (AstQueueDType* adtypep = VN_CAST(dtypep, QueueDType)) { + return emitVarResetRecurse(varp, adtypep->subDTypep(), depth + 1, ".atDefault()"); + } else if (AstUnpackArrayDType* adtypep = VN_CAST(dtypep, UnpackArrayDType)) { UASSERT_OBJ(adtypep->msb() >= adtypep->lsb(), varp, "Should have swapped msb & lsb earlier."); - string ivar = string("__Vi")+cvtToStr(depth); + string ivar = string("__Vi") + cvtToStr(depth); // MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block - string pre = ("{ int "+ivar+"="+cvtToStr(0)+";" - +" for (; "+ivar+"<"+cvtToStr(adtypep->elementsConst()) - +"; ++"+ivar+") {\n"); - string below = emitVarResetRecurse(varp, adtypep->subDTypep(), depth+1, suffix+"["+ivar+"]"); + string pre = ("{ int " + ivar + "=" + cvtToStr(0) + ";" + " for (; " + ivar + "<" + + cvtToStr(adtypep->elementsConst()) + "; ++" + ivar + ") {\n"); + string below = emitVarResetRecurse(varp, adtypep->subDTypep(), depth + 1, + suffix + "[" + ivar + "]"); string post = "}}\n"; return below.empty() ? "" : pre + below + post; - } - else if (basicp && basicp->keyword() == AstBasicDTypeKwd::STRING) { + } else if (basicp && basicp->keyword() == AstBasicDTypeKwd::STRING) { // String's constructor deals with it return ""; - } - else if (basicp) { - bool zeroit = (varp->attrFileDescr() // Zero so we don't core dump if never $fopen - || (basicp && basicp->isZeroInit()) - || (v3Global.opt.underlineZero() - && !varp->name().empty() && varp->name()[0] == '_') - || (v3Global.opt.xInitial() == "fast" - || v3Global.opt.xInitial() == "0")); + } else if (basicp) { + bool zeroit + = (varp->attrFileDescr() // Zero so we don't core dump if never $fopen + || (basicp && basicp->isZeroInit()) + || (v3Global.opt.underlineZero() && !varp->name().empty() + && varp->name()[0] == '_') + || (v3Global.opt.xInitial() == "fast" || v3Global.opt.xInitial() == "0")); splitSizeInc(1); if (dtypep->isWide()) { // Handle unpacked; not basicp->isWide string out; - if (zeroit) out += "VL_ZERO_RESET_W("; - else out += "VL_RAND_RESET_W("; + if (zeroit) { + out += "VL_ZERO_RESET_W("; + } else { + out += "VL_RAND_RESET_W("; + } out += cvtToStr(dtypep->widthMin()); - out += ", "+varp->nameProtect()+suffix+");\n"; + out += ", " + varp->nameProtect() + suffix + ");\n"; return out; } else { string out = varp->nameProtect() + suffix; @@ -1586,13 +1640,12 @@ class EmitCImp : EmitCStmts { } else { out += " = VL_RAND_RESET_"; out += dtypep->charIQWN(); - out += "("+ cvtToStr(dtypep->widthMin())+");\n"; + out += "(" + cvtToStr(dtypep->widthMin()) + ");\n"; } return out; } - } - else { - v3fatalSrc("Unknown node type in reset generator: "<prettyTypeName()); + } else { + v3fatalSrc("Unknown node type in reset generator: " << varp->prettyTypeName()); } return ""; } @@ -1627,9 +1680,7 @@ public: virtual ~EmitCImp() {} void mainImp(AstNodeModule* modp, bool slow, bool fast); void mainInt(AstNodeModule* modp); - void mainDoFunc(AstCFunc* nodep) { - iterate(nodep); - } + void mainDoFunc(AstCFunc* nodep) { iterate(nodep); } }; //###################################################################### @@ -1643,11 +1694,15 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) { if (nodep->attrScClocked() && nodep->isReadOnly()) { puts("sc_in_clk "); } else { - if (nodep->isInoutish()) puts("sc_inout<"); - else if (nodep->isWritable()) puts("sc_out<"); - else if (nodep->isNonOutput()) puts("sc_in<"); - else nodep->v3fatalSrc("Unknown type"); - + if (nodep->isInoutish()) { + puts("sc_inout<"); + } else if (nodep->isWritable()) { + puts("sc_out<"); + } else if (nodep->isNonOutput()) { + puts("sc_in<"); + } else { + nodep->v3fatalSrc("Unknown type"); + } puts(nodep->scType()); puts("> "); } @@ -1655,23 +1710,32 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) { emitDeclArrayBrackets(nodep); puts(";\n"); } else if (nodep->isIO() && basicp && !basicp->isOpaque()) { - if (nodep->isInoutish()) puts("VL_INOUT"); - else if (nodep->isWritable()) puts("VL_OUT"); - else if (nodep->isNonOutput()) puts("VL_IN"); - else nodep->v3fatalSrc("Unknown type"); + if (nodep->isInoutish()) { + puts("VL_INOUT"); + } else if (nodep->isWritable()) { + puts("VL_OUT"); + } else if (nodep->isNonOutput()) { + puts("VL_IN"); + } else { + nodep->v3fatalSrc("Unknown type"); + } - if (nodep->isQuad()) puts("64"); - else if (nodep->widthMin() <= 8) puts("8"); - else if (nodep->widthMin() <= 16) puts("16"); - else if (nodep->isWide()) puts("W"); + if (nodep->isQuad()) { + puts("64"); + } else if (nodep->widthMin() <= 8) { + puts("8"); + } else if (nodep->widthMin() <= 16) { + puts("16"); + } else if (nodep->isWide()) { + puts("W"); + } - puts("("+nodep->nameProtect()); + puts("(" + nodep->nameProtect()); emitDeclArrayBrackets(nodep); // If it's a packed struct/array then nodep->width is the whole // thing, msb/lsb is just lowest dimension - puts(","+cvtToStr(basicp->lsb()+nodep->width()-1) - +","+cvtToStr(basicp->lsb())); - if (nodep->isWide()) puts(","+cvtToStr(nodep->widthWords())); + puts("," + cvtToStr(basicp->lsb() + nodep->width() - 1) + "," + cvtToStr(basicp->lsb())); + if (nodep->isWide()) puts("," + cvtToStr(nodep->widthWords())); puts(");\n"); } else { // strings and other fundamental c types @@ -1682,7 +1746,8 @@ void EmitCStmts::emitVarDecl(const AstVar* nodep, const string& prefixIfImp) { void EmitCStmts::emitCtorSep(bool* firstp) { if (*firstp) { - puts(" : "); *firstp = false; + puts(" : "); + *firstp = false; } else { puts(", "); } @@ -1704,7 +1769,9 @@ void EmitCStmts::emitVarCtors(bool* firstp) { } else { emitCtorSep(firstp); puts(varp->nameProtect()); - puts("("); putsQuoted(varp->nameProtect()); puts(")"); + puts("("); + putsQuoted(varp->nameProtect()); + puts(")"); } } puts("\n#endif\n"); @@ -1716,14 +1783,20 @@ bool EmitCStmts::emitSimpleOk(AstNodeMath* nodep) { // Can we put out a simple (A + B) instead of VL_ADD_III(A,B)? if (nodep->emitSimpleOperator() == "") return false; if (nodep->isWide()) return false; - if (nodep->op1p()) { if (nodep->op1p()->isWide()) return false; } - if (nodep->op2p()) { if (nodep->op2p()->isWide()) return false; } - if (nodep->op3p()) { if (nodep->op3p()->isWide()) return false; } + if (nodep->op1p()) { + if (nodep->op1p()->isWide()) return false; + } + if (nodep->op2p()) { + if (nodep->op2p()->isWide()) return false; + } + if (nodep->op3p()) { + if (nodep->op3p()->isWide()) return false; + } return true; } -void EmitCStmts::emitOpName(AstNode* nodep, const string& format, - AstNode* lhsp, AstNode* rhsp, AstNode* thsp) { +void EmitCStmts::emitOpName(AstNode* nodep, const string& format, AstNode* lhsp, AstNode* rhsp, + AstNode* thsp) { // Look at emitOperator() format for term/uni/dual/triops, // and write out appropriate text. // %n* node @@ -1739,30 +1812,49 @@ void EmitCStmts::emitOpName(AstNode* nodep, const string& format, // , Commas suppressed if the previous field is suppressed string nextComma; bool needComma = false; -#define COMMA { if (!nextComma.empty()) { puts(nextComma); nextComma=""; } } +#define COMMA \ + { \ + if (!nextComma.empty()) { \ + puts(nextComma); \ + nextComma = ""; \ + } \ + } putbs(""); for (string::const_iterator pos = format.begin(); pos != format.end(); ++pos) { - if (pos[0]==',') { + if (pos[0] == ',') { // Remember we need to add one, but don't do yet to avoid ",)" if (needComma) { - if (pos[1]==' ') { nextComma = ", "; } - else nextComma = ","; + if (pos[1] == ' ') { + nextComma = ", "; + } else + nextComma = ","; needComma = false; } - if (pos[1]==' ') { ++pos; } // Must do even if no nextComma - } - else if (pos[0]=='%') { + if (pos[1] == ' ') { ++pos; } // Must do even if no nextComma + } else if (pos[0] == '%') { ++pos; bool detail = false; AstNode* detailp = NULL; switch (pos[0]) { - case '%': puts("%"); break; - case 'k': putbs(""); break; - case 'n': detail = true; detailp = nodep; break; - case 'l': detail = true; detailp = lhsp; break; - case 'r': detail = true; detailp = rhsp; break; - case 't': detail = true; detailp = thsp; break; + case '%': puts("%"); break; + case 'k': putbs(""); break; + case 'n': + detail = true; + detailp = nodep; + break; + case 'l': + detail = true; + detailp = lhsp; + break; + case 'r': + detail = true; + detailp = rhsp; + break; + case 't': + detail = true; + detailp = thsp; + break; case 'P': if (nodep->isWide()) { UASSERT_OBJ(m_wideTempRefp, nodep, @@ -1774,9 +1866,7 @@ void EmitCStmts::emitOpName(AstNode* nodep, const string& format, needComma = true; } break; - default: - nodep->v3fatalSrc("Unknown emitOperator format code: %"<v3fatalSrc("Unknown emitOperator format code: %" << pos[0]); break; } if (detail) { // Get next letter of %[nlrt] @@ -1802,19 +1892,24 @@ void EmitCStmts::emitOpName(AstNode* nodep, const string& format, needComma = true; break; default: - nodep->v3fatalSrc("Unknown emitOperator format code: %[nlrt]"<v3fatalSrc("Unknown emitOperator format code: %[nlrt]" << pos[0]); break; } } } else if (pos[0] == ')') { - nextComma = ""; puts(")"); + nextComma = ""; + puts(")"); } else if (pos[0] == '(') { - COMMA; needComma = false; puts("("); + COMMA; + needComma = false; + puts("("); } else { // Normal text if (isalnum(pos[0])) needComma = true; COMMA; - string s; s += pos[0]; puts(s); + string s; + s += pos[0]; + puts(s); } } } @@ -1825,8 +1920,8 @@ void EmitCStmts::emitOpName(AstNode* nodep, const string& format, // We only do one display at once, so can just use static state struct EmitDispState { - string m_format; // "%s" and text from user - std::vector m_argsChar; // Format of each argument to be printed + string m_format; // "%s" and text from user + std::vector m_argsChar; // Format of each argument to be printed std::vector m_argsp; // Each argument to be printed std::vector m_argsFunc; // Function before each argument to be printed EmitDispState() { clear(); } @@ -1840,7 +1935,8 @@ struct EmitDispState { void pushFormat(char fmt) { m_format += fmt; } void pushArg(char fmtChar, AstNode* nodep, const string& func) { m_argsChar.push_back(fmtChar); - m_argsp.push_back(nodep); m_argsFunc.push_back(func); + m_argsp.push_back(nodep); + m_argsFunc.push_back(func); } } emitDispState; @@ -1859,7 +1955,9 @@ void EmitCStmts::displayEmit(AstNode* nodep, bool isScan) { } else if (const AstSScanF* dispp = VN_CAST(nodep, SScanF)) { isStmt = false; checkMaxWords(dispp->fromp()); - puts("VL_SSCANF_I"); emitIQW(dispp->fromp()); puts("X("); + puts("VL_SSCANF_I"); + emitIQW(dispp->fromp()); + puts("X("); puts(cvtToStr(dispp->fromp()->widthMin())); puts(","); iterate(dispp->fromp()); @@ -1888,34 +1986,42 @@ void EmitCStmts::displayEmit(AstNode* nodep, bool isScan) { } ofp()->putsQuoted(emitDispState.m_format); // Arguments - for (unsigned i=0; i < emitDispState.m_argsp.size(); i++) { + for (unsigned i = 0; i < emitDispState.m_argsp.size(); i++) { puts(","); - char fmt = emitDispState.m_argsChar[i]; + char fmt = emitDispState.m_argsChar[i]; AstNode* argp = emitDispState.m_argsp[i]; - string func = emitDispState.m_argsFunc[i]; + string func = emitDispState.m_argsFunc[i]; ofp()->indentInc(); ofp()->putbs(""); - if (func!="") puts(func); + if (func != "") puts(func); if (argp) { - if (isScan) puts("&("); - else if (fmt == '@') puts("&("); + if (isScan) { + puts("&("); + } else if (fmt == '@') { + puts("&("); + } iterate(argp); - if (isScan) puts(")"); - else if (fmt == '@') puts(")"); + if (isScan) { + puts(")"); + } else if (fmt == '@') { + puts(")"); + } } ofp()->indentDec(); } // End puts(")"); - if (isStmt) puts(";\n"); - else puts(" "); + if (isStmt) + puts(";\n"); + else + puts(" "); // Prep for next emitDispState.clear(); } } -void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan, - const string& vfmt, char fmtLetter) { +void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan, const string& vfmt, + char fmtLetter) { // Print display argument, edits elistp AstNode* argp = *elistp; if (VL_UNCOVERABLE(!argp)) { @@ -1924,22 +2030,22 @@ void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan, return; // LCOV_EXCL_LINE } if (argp->widthMin() > VL_VALUE_STRING_MAX_WIDTH) { - dispp->v3error("Exceeded limit of "+cvtToStr(VL_VALUE_STRING_MAX_WIDTH)+" bits for any $display-like arguments"); + dispp->v3error("Exceeded limit of " + cvtToStr(VL_VALUE_STRING_MAX_WIDTH) + + " bits for any $display-like arguments"); } if (argp->widthMin() > 8 && fmtLetter == 'c') { // Technically legal, but surely not what the user intended. - argp->v3warn(WIDTH, dispp->verilogKwd()<<"of %c format of > 8 bit value"); + argp->v3warn(WIDTH, dispp->verilogKwd() << "of %c format of > 8 bit value"); } - //string pfmt = "%"+displayFormat(argp, vfmt, fmtLetter)+fmtLetter; + // string pfmt = "%"+displayFormat(argp, vfmt, fmtLetter)+fmtLetter; string pfmt; - if ((fmtLetter=='#' || fmtLetter=='d' || fmtLetter=='t') - && !isScan + if ((fmtLetter == '#' || fmtLetter == 'd' || fmtLetter == 't') && !isScan && vfmt == "") { // Size decimal output. Spec says leading spaces, not zeros - double mantissabits = argp->widthMin() - ((fmtLetter=='d')?1:0); + double mantissabits = argp->widthMin() - ((fmtLetter == 'd') ? 1 : 0); double maxval = pow(2.0, mantissabits); - double dchars = log10(maxval)+1.0; - if (fmtLetter=='d') dchars++; // space for sign + double dchars = log10(maxval) + 1.0; + if (fmtLetter == 'd') dchars++; // space for sign int nchars = int(dchars); pfmt = string("%") + cvtToStr(nchars) + fmtLetter; } else { @@ -1953,9 +2059,8 @@ void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan, *elistp = (*elistp)->nextp(); } -void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep, - const string& vformat, AstNode* exprsp, - bool isScan) { +void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep, const string& vformat, + AstNode* exprsp, bool isScan) { AstNode* elistp = exprsp; // Convert Verilog display to C printf formats @@ -1965,8 +2070,8 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep, string::const_iterator pos = vformat.begin(); bool inPct = false; for (; pos != vformat.end(); ++pos) { - //UINFO(1,"Parse '"<<*pos<<"' IP"<scopePrettySymName(); - if (suffix=="") emitDispState.pushFormat("%S"); - else emitDispState.pushFormat("%N"); // Add a . when needed + if (suffix == "") { + emitDispState.pushFormat("%S"); + } else { + emitDispState.pushFormat("%N"); // Add a . when needed + } emitDispState.pushArg(' ', NULL, "vlSymsp->name()"); emitDispState.pushFormat(suffix); break; @@ -2017,7 +2126,7 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep, break; } default: - nodep->v3error("Unknown $display-like format code: '%"<v3error("Unknown $display-like format code: '%" << pos[0] << "'"); break; } } @@ -2039,7 +2148,7 @@ void EmitCImp::emitCoverageDecl(AstNodeModule* modp) { puts("void __vlCoverInsert("); puts(v3Global.opt.threads() ? "std::atomic" : "uint32_t"); puts("* countp, bool enable, const char* filenamep, int lineno, int column,\n"); - puts( "const char* hierp, const char* pagep, const char* commentp);\n"); + puts("const char* hierp, const char* pagep, const char* commentp);\n"); } } @@ -2049,13 +2158,12 @@ void EmitCImp::emitMTaskVertexCtors(bool* firstp) { const V3Graph* depGraphp = execGraphp->depGraphp(); unsigned finalEdgesInCt = 0; - for (const V3GraphVertex* vxp = depGraphp->verticesBeginp(); - vxp; vxp = vxp->verticesNextp()) { + for (const V3GraphVertex* vxp = depGraphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) { const ExecMTask* mtp = dynamic_cast(vxp); unsigned edgesInCt = packedMTaskMayBlock(mtp); if (packedMTaskMayBlock(mtp) > 0) { emitCtorSep(firstp); - puts("__Vm_mt_"+cvtToStr(mtp->id())+"("+cvtToStr(edgesInCt)+")"); + puts("__Vm_mt_" + cvtToStr(mtp->id()) + "(" + cvtToStr(edgesInCt) + ")"); } // Each mtask with no packed successor will become a dependency // for the final node: @@ -2066,11 +2174,14 @@ void EmitCImp::emitMTaskVertexCtors(bool* firstp) { puts("__Vm_mt_final(" + cvtToStr(finalEdgesInCt) + ")"); // This will flip to 'true' before the start of the 0th cycle. - emitCtorSep(firstp); puts("__Vm_threadPoolp(NULL)"); + emitCtorSep(firstp); + puts("__Vm_threadPoolp(NULL)"); if (v3Global.opt.profThreads()) { - emitCtorSep(firstp); puts("__Vm_profile_cycle_start(0)"); + emitCtorSep(firstp); + puts("__Vm_profile_cycle_start(0)"); } - emitCtorSep(firstp); puts("__Vm_even_cycle(false)"); + emitCtorSep(firstp); + puts("__Vm_even_cycle(false)"); } void EmitCImp::emitCtorImp(AstNodeModule* modp) { @@ -2085,9 +2196,7 @@ void EmitCImp::emitCtorImp(AstNodeModule* modp) { first = false; // VL_CTOR_IMP includes the first ':' } emitVarCtors(&first); - if (modp->isTop() && v3Global.opt.mtasks()) { - emitMTaskVertexCtors(&first); - } + if (modp->isTop() && v3Global.opt.mtasks()) emitMTaskVertexCtors(&first); puts(" {\n"); emitCellCtors(modp); emitSensitives(); @@ -2098,7 +2207,7 @@ void EmitCImp::emitCtorImp(AstNodeModule* modp) { puts("\n"); } putsDecoration("// Reset structure values\n"); - puts(protect("_ctor_var_reset")+"();\n"); + puts(protect("_ctor_var_reset") + "();\n"); emitTextSection(AstType::atScCtor); if (modp->isTop() && v3Global.opt.mtasks()) { @@ -2123,8 +2232,7 @@ void EmitCImp::emitCtorImp(AstNodeModule* modp) { // Note we create N-1 threads in the thread pool. The thread // that calls eval() becomes the final Nth thread for the // duration of the eval call. - + cvtToStr(v3Global.opt.threads() - 1) - + ", " + cvtToStr(v3Global.opt.profThreads()) + + cvtToStr(v3Global.opt.threads() - 1) + ", " + cvtToStr(v3Global.opt.profThreads()) + ");\n"); if (v3Global.opt.profThreads()) { @@ -2139,45 +2247,43 @@ void EmitCImp::emitCtorImp(AstNodeModule* modp) { void EmitCImp::emitConfigureImp(AstNodeModule* modp) { puts("\nvoid " + prefixNameProtect(modp) + "::" + protect("__Vconfigure") + "(" + symClassName() + "* vlSymsp, bool first) {\n"); - puts( "if (false && first) {} // Prevent unused\n"); - puts( "this->__VlSymsp = vlSymsp;\n"); // First, as later stuff needs it. - puts( "if (false && this->__VlSymsp) {} // Prevent unused\n"); - if (v3Global.opt.coverage() ) { - puts(protect("_configure_coverage")+"(vlSymsp, first);\n"); - } + puts("if (false && first) {} // Prevent unused\n"); + puts("this->__VlSymsp = vlSymsp;\n"); // First, as later stuff needs it. + puts("if (false && this->__VlSymsp) {} // Prevent unused\n"); + if (v3Global.opt.coverage()) puts(protect("_configure_coverage") + "(vlSymsp, first);\n"); puts("}\n"); splitSizeInc(10); } void EmitCImp::emitCoverageImp(AstNodeModule* modp) { - if (v3Global.opt.coverage() ) { + if (v3Global.opt.coverage()) { puts("\n// Coverage\n"); // Rather than putting out VL_COVER_INSERT calls directly, we do it via this function // This gets around gcc slowness constructing all of the template arguments. puts("void " + prefixNameProtect(m_modp) + "::__vlCoverInsert("); puts(v3Global.opt.threads() ? "std::atomic" : "uint32_t"); puts("* countp, bool enable, const char* filenamep, int lineno, int column,\n"); - puts( "const char* hierp, const char* pagep, const char* commentp) {\n"); + puts("const char* hierp, const char* pagep, const char* commentp) {\n"); if (v3Global.opt.threads()) { - puts( "assert(sizeof(uint32_t) == sizeof(std::atomic));\n"); - puts( "uint32_t* count32p = reinterpret_cast(countp);\n"); + puts("assert(sizeof(uint32_t) == sizeof(std::atomic));\n"); + puts("uint32_t* count32p = reinterpret_cast(countp);\n"); } else { - puts( "uint32_t* count32p = countp;\n"); + puts("uint32_t* count32p = countp;\n"); } // static doesn't need save-restore as is constant - puts( "static uint32_t fake_zero_count = 0;\n"); + puts("static uint32_t fake_zero_count = 0;\n"); // Used for second++ instantiation of identical bin - puts( "if (!enable) count32p = &fake_zero_count;\n"); - puts( "*count32p = 0;\n"); + puts("if (!enable) count32p = &fake_zero_count;\n"); + puts("*count32p = 0;\n"); puts("VL_COVER_INSERT(count32p,"); - puts( " \"filename\",filenamep,"); - puts( " \"lineno\",lineno,"); - puts( " \"column\",column,\n"); + puts(" \"filename\",filenamep,"); + puts(" \"lineno\",lineno,"); + puts(" \"column\",column,\n"); // Need to move hier into scopes and back out if do this - //puts( "\"hier\",std::string(__VlSymsp->name())+hierp,"); - puts( "\"hier\",std::string(name())+hierp,"); - puts( " \"page\",pagep,"); - puts( " \"comment\",commentp);\n"); + // puts( "\"hier\",std::string(__VlSymsp->name())+hierp,"); + puts("\"hier\",std::string(name())+hierp,"); + puts(" \"page\",pagep,"); + puts(" \"comment\",commentp);\n"); puts("}\n"); splitSizeInc(10); } @@ -2187,9 +2293,7 @@ void EmitCImp::emitDestructorImp(AstNodeModule* modp) { puts("\n"); puts(prefixNameProtect(modp) + "::~" + prefixNameProtect(modp) + "() {\n"); if (modp->isTop()) { - if (v3Global.opt.mtasks()) { - puts("delete __Vm_threadPoolp; __Vm_threadPoolp = NULL;\n"); - } + if (v3Global.opt.mtasks()) puts("delete __Vm_threadPoolp; __Vm_threadPoolp = NULL;\n"); // Call via function in __Trace.cpp as this .cpp file does not have trace header if (v3Global.needTraceDumper()) { puts("#ifdef VM_TRACE\n"); @@ -2204,9 +2308,9 @@ void EmitCImp::emitDestructorImp(AstNodeModule* modp) { } void EmitCImp::emitSavableImp(AstNodeModule* modp) { - if (v3Global.opt.savable() ) { + if (v3Global.opt.savable()) { puts("\n// Savable\n"); - for (int de=0; de<2; ++de) { + for (int de = 0; de < 2; ++de) { string classname = de ? "VerilatedDeserialize" : "VerilatedSerialize"; string funcname = de ? "__Vdeserialize" : "__Vserialize"; string op = de ? ">>" : "<<"; @@ -2223,8 +2327,8 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) { hash.insert(varp->dtypep()->width()); } } - ofp()->printf( "vluint64_t __Vcheckval = VL_ULL(0x%" VL_PRI64 "x);\n", - static_cast(hash.digestUInt64())); + ofp()->printf("vluint64_t __Vcheckval = VL_ULL(0x%" VL_PRI64 "x);\n", + static_cast(hash.digestUInt64())); if (de) { puts("os.readAssert(__Vcheckval);\n"); } else { @@ -2232,30 +2336,28 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) { } // Save all members - if (v3Global.opt.inhibitSim()) puts("os"+op+"__Vm_inhibitSim;\n"); + if (v3Global.opt.inhibitSim()) puts("os" + op + "__Vm_inhibitSim;\n"); for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) { if (const AstVar* varp = VN_CAST(nodep, Var)) { if (varp->isIO() && modp->isTop() && optSystemC()) { // System C top I/O doesn't need loading, as the // lower level subinst code does it. - } - else if (varp->isParam()) {} - else if (varp->isStatic() && varp->isConst()) {} - else { + } else if (varp->isParam()) { + } else if (varp->isStatic() && varp->isConst()) { + } else { int vects = 0; AstNodeDType* elementp = varp->dtypeSkipRefp(); for (AstUnpackArrayDType* arrayp = VN_CAST(elementp, UnpackArrayDType); - arrayp; - arrayp = VN_CAST(elementp, UnpackArrayDType)) { + arrayp; arrayp = VN_CAST(elementp, UnpackArrayDType)) { int vecnum = vects++; UASSERT_OBJ(arrayp->msb() >= arrayp->lsb(), varp, "Should have swapped msb & lsb earlier."); - string ivar = string("__Vi")+cvtToStr(vecnum); + string ivar = string("__Vi") + cvtToStr(vecnum); // MSVC++ pre V7 doesn't support 'for (int ...)', // so declare in sep block - puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(0)+";"); - puts(" for (; "+ivar+"<"+cvtToStr(arrayp->elementsConst())); - puts("; ++"+ivar+") {\n"); + puts("{ int __Vi" + cvtToStr(vecnum) + "=" + cvtToStr(0) + ";"); + puts(" for (; " + ivar + "<" + cvtToStr(arrayp->elementsConst())); + puts("; ++" + ivar + ") {\n"); elementp = arrayp->subDTypep()->skipRefp(); } // Want to detect types that are represented as arrays @@ -2264,21 +2366,21 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) { if (elementp->isWide() && !(basicp && basicp->keyword() == AstBasicDTypeKwd::STRING)) { int vecnum = vects++; - string ivar = string("__Vi")+cvtToStr(vecnum); - puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(0)+";"); - puts(" for (; "+ivar+"<"+cvtToStr(elementp->widthWords())); - puts("; ++"+ivar+") {\n"); + string ivar = string("__Vi") + cvtToStr(vecnum); + puts("{ int __Vi" + cvtToStr(vecnum) + "=" + cvtToStr(0) + ";"); + puts(" for (; " + ivar + "<" + cvtToStr(elementp->widthWords())); + puts("; ++" + ivar + ") {\n"); } - puts("os"+op+varp->nameProtect()); - for (int v=0; vnameProtect()); + for (int v = 0; v < vects; ++v) puts("[__Vi" + cvtToStr(v) + "]"); puts(";\n"); - for (int v=0; visTop()) { // Save the children - puts( "__VlSymsp->"+protect(funcname)+"(os);\n"); + puts("__VlSymsp->" + protect(funcname) + "(os);\n"); } puts("}\n"); } @@ -2294,8 +2396,8 @@ void EmitCImp::emitTextSection(AstType type) { if (last_line < 0) { puts("\n//*** Below code from `systemc in Verilog file\n"); } - putsDecoration(ifNoProtect("// From `systemc at " - +nodep->fileline()->ascii()+"\n")); + putsDecoration( + ifNoProtect("// From `systemc at " + nodep->fileline()->ascii() + "\n")); last_line = nodep->fileline()->lineno(); } ofp()->putsNoTracking(textp->text()); @@ -2303,16 +2405,15 @@ void EmitCImp::emitTextSection(AstType type) { } } } - if (last_line > 0) { - puts("//*** Above code from `systemc in Verilog file\n\n"); - } + if (last_line > 0) puts("//*** Above code from `systemc in Verilog file\n\n"); } void EmitCImp::emitCellCtors(AstNodeModule* modp) { if (modp->isTop()) { // Must be before other constructors, as __vlCoverInsert calls it - puts(EmitCBaseVisitor::symClassVar()+" = __VlSymsp = new "+symClassName()+"(this, name());\n"); - puts(EmitCBaseVisitor::symTopAssign()+"\n"); + puts(EmitCBaseVisitor::symClassVar() + " = __VlSymsp = new " + symClassName() + + "(this, name());\n"); + puts(EmitCBaseVisitor::symTopAssign() + "\n"); } for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) { if (AstCell* cellp = VN_CAST(nodep, Cell)) { @@ -2330,27 +2431,27 @@ void EmitCImp::emitSensitives() { puts("SC_METHOD(eval);\n"); for (AstNode* nodep = m_modp->stmtsp(); nodep; nodep = nodep->nextp()) { if (const AstVar* varp = VN_CAST(nodep, Var)) { - if (varp->isNonOutput() && (varp->isScSensitive() - || varp->isUsedClock())) { + if (varp->isNonOutput() && (varp->isScSensitive() || varp->isUsedClock())) { int vects = 0; // This isn't very robust and may need cleanup for other data types for (AstUnpackArrayDType* arrayp - = VN_CAST(varp->dtypeSkipRefp(), UnpackArrayDType); + = VN_CAST(varp->dtypeSkipRefp(), UnpackArrayDType); arrayp; arrayp = VN_CAST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) { int vecnum = vects++; UASSERT_OBJ(arrayp->msb() >= arrayp->lsb(), varp, "Should have swapped msb & lsb earlier."); - string ivar = string("__Vi")+cvtToStr(vecnum); + string ivar = string("__Vi") + cvtToStr(vecnum); // MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block - puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(arrayp->lsb())+";"); - puts(" for (; "+ivar+"<="+cvtToStr(arrayp->msb())); - puts("; ++"+ivar+") {\n"); + puts("{ int __Vi" + cvtToStr(vecnum) + "=" + cvtToStr(arrayp->lsb()) + + ";"); + puts(" for (; " + ivar + "<=" + cvtToStr(arrayp->msb())); + puts("; ++" + ivar + ") {\n"); } - puts("sensitive << "+varp->nameProtect()); - for (int v=0; vnameProtect()); + for (int v = 0; v < vects; ++v) puts("[__Vi" + cvtToStr(v) + "]"); puts(";\n"); - for (int v=0; v "+cvtToStr(v3Global.opt.convergeLimit()) - +")) {\n"); - puts( "// About to fail, so enable debug to see what's not settling.\n"); - puts( "// Note you must run make with OPT=-DVL_DEBUG for debug prints.\n"); - puts( "int __Vsaved_debug = Verilated::debug();\n"); - puts( "Verilated::debug(1);\n"); - puts( "__Vchange = "+protect("_change_request")+"(vlSymsp);\n"); - puts( "Verilated::debug(__Vsaved_debug);\n"); - puts( "VL_FATAL_MT("); + puts(eval_call + "\n"); + puts("if (VL_UNLIKELY(++__VclockLoop > " + cvtToStr(v3Global.opt.convergeLimit()) + ")) {\n"); + puts("// About to fail, so enable debug to see what's not settling.\n"); + puts("// Note you must run make with OPT=-DVL_DEBUG for debug prints.\n"); + puts("int __Vsaved_debug = Verilated::debug();\n"); + puts("Verilated::debug(1);\n"); + puts("__Vchange = " + protect("_change_request") + "(vlSymsp);\n"); + puts("Verilated::debug(__Vsaved_debug);\n"); + puts("VL_FATAL_MT("); putsQuoted(protect(m_modp->fileline()->filename())); puts(", "); puts(cvtToStr(m_modp->fileline()->lineno())); @@ -2381,9 +2481,9 @@ void EmitCImp::emitSettleLoop(const std::string& eval_call, bool initial) { if (initial) puts("DC "); puts("converge\\n\"\n"); puts("\"- See DIDNOTCONVERGE in the Verilator manual\");\n"); - puts( "} else {\n"); - puts( "__Vchange = "+protect("_change_request")+"(vlSymsp);\n"); - puts( "}\n"); + puts("} else {\n"); + puts("__Vchange = " + protect("_change_request") + "(vlSymsp);\n"); + puts("}\n"); puts("} while (VL_UNLIKELY(__Vchange));\n"); } @@ -2391,73 +2491,69 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) { puts("\nvoid " + prefixNameProtect(modp) + "::eval_step() {\n"); puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+++++TOP Evaluate " + prefixNameProtect(modp) + "::eval\\n\"); );\n"); - puts(EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp; // Setup global symbol table\n"); - puts(EmitCBaseVisitor::symTopAssign()+"\n"); + puts(EmitCBaseVisitor::symClassVar() + " = this->__VlSymsp; // Setup global symbol table\n"); + puts(EmitCBaseVisitor::symTopAssign() + "\n"); puts("#ifdef VL_DEBUG\n"); putsDecoration("// Debug assertions\n"); - puts(protect("_eval_debug_assertions")+"();\n"); + puts(protect("_eval_debug_assertions") + "();\n"); puts("#endif // VL_DEBUG\n"); putsDecoration("// Initialize\n"); - puts("if (VL_UNLIKELY(!vlSymsp->__Vm_didInit)) " - +protect("_eval_initial_loop")+"(vlSymsp);\n"); - if (v3Global.opt.inhibitSim()) { - puts("if (VL_UNLIKELY(__Vm_inhibitSim)) return;\n"); - } + puts("if (VL_UNLIKELY(!vlSymsp->__Vm_didInit)) " + protect("_eval_initial_loop") + + "(vlSymsp);\n"); + if (v3Global.opt.inhibitSim()) puts("if (VL_UNLIKELY(__Vm_inhibitSim)) return;\n"); if (v3Global.opt.threads() == 1) { uint32_t mtaskId = 0; - putsDecoration("// MTask "+cvtToStr(mtaskId)+" start\n"); - puts("VL_DEBUG_IF(VL_DBG_MSGF(\"MTask"+cvtToStr(mtaskId)+" starting\\n\"););\n"); - puts("Verilated::mtaskId("+cvtToStr(mtaskId)+");\n"); + putsDecoration("// MTask " + cvtToStr(mtaskId) + " start\n"); + puts("VL_DEBUG_IF(VL_DBG_MSGF(\"MTask" + cvtToStr(mtaskId) + " starting\\n\"););\n"); + puts("Verilated::mtaskId(" + cvtToStr(mtaskId) + ");\n"); } - if (v3Global.opt.mtasks() - && v3Global.opt.profThreads()) { + if (v3Global.opt.mtasks() && v3Global.opt.profThreads()) { puts("if (VL_UNLIKELY((Verilated::profThreadsStart() != __Vm_profile_time_finished)\n"); - puts( " && (VL_TIME_Q() > Verilated::profThreadsStart())\n"); - puts( " && (Verilated::profThreadsWindow() >= 1))) {\n"); + puts(" && (VL_TIME_Q() > Verilated::profThreadsStart())\n"); + puts(" && (Verilated::profThreadsWindow() >= 1))) {\n"); // Within a profile (either starting, middle, or end) - puts( "if (vlTOPp->__Vm_profile_window_ct == 0) {\n"); // Opening file? + puts("if (vlTOPp->__Vm_profile_window_ct == 0) {\n"); // Opening file? // Start profile on this cycle. We'll capture a window worth, then // only analyze the next window worth. The idea is that the first window // capture will hit some cache-cold stuff (eg printf) but it'll be warm // by the time we hit the second window, we hope. - puts( "vlTOPp->__Vm_profile_cycle_start = VL_RDTSC_Q();\n"); + puts("vlTOPp->__Vm_profile_cycle_start = VL_RDTSC_Q();\n"); // "* 2" as first half is warmup, second half is collection - puts( "vlTOPp->__Vm_profile_window_ct = Verilated::profThreadsWindow() * 2 + 1;\n"); - puts( "}\n"); - puts( "--vlTOPp->__Vm_profile_window_ct;\n"); - puts( "if (vlTOPp->__Vm_profile_window_ct == (Verilated::profThreadsWindow())) {\n"); + puts("vlTOPp->__Vm_profile_window_ct = Verilated::profThreadsWindow() * 2 + 1;\n"); + puts("}\n"); + puts("--vlTOPp->__Vm_profile_window_ct;\n"); + puts("if (vlTOPp->__Vm_profile_window_ct == (Verilated::profThreadsWindow())) {\n"); // This barrier record in every threads' profile demarcates the // cache-warm-up cycles before the barrier from the actual profile // cycles afterward. - puts( "vlTOPp->__Vm_threadPoolp->profileAppendAll("); - puts( "VlProfileRec(VlProfileRec::Barrier()));\n"); - puts( "vlTOPp->__Vm_profile_cycle_start = VL_RDTSC_Q();\n"); - puts( "}\n"); - puts( "else if (vlTOPp->__Vm_profile_window_ct == 0) {\n"); + puts("vlTOPp->__Vm_threadPoolp->profileAppendAll("); + puts("VlProfileRec(VlProfileRec::Barrier()));\n"); + puts("vlTOPp->__Vm_profile_cycle_start = VL_RDTSC_Q();\n"); + puts("}\n"); + puts("else if (vlTOPp->__Vm_profile_window_ct == 0) {\n"); // Ending file. - puts( "vluint64_t elapsed = VL_RDTSC_Q() - vlTOPp->__Vm_profile_cycle_start;\n"); - puts( "vlTOPp->__Vm_threadPoolp->profileDump(Verilated::profThreadsFilenamep(), elapsed);\n"); + puts("vluint64_t elapsed = VL_RDTSC_Q() - vlTOPp->__Vm_profile_cycle_start;\n"); + puts("vlTOPp->__Vm_threadPoolp->profileDump(Verilated::profThreadsFilenamep(), " + "elapsed);\n"); // This turns off the test to enter the profiling code, but still // allows the user to collect another profile by changing // profThreadsStart - puts( "__Vm_profile_time_finished = Verilated::profThreadsStart();\n"); - puts( "vlTOPp->__Vm_profile_cycle_start = 0;\n"); - puts( "}\n"); + puts("__Vm_profile_time_finished = Verilated::profThreadsStart();\n"); + puts("vlTOPp->__Vm_profile_cycle_start = 0;\n"); + puts("}\n"); puts("}\n"); } - emitSettleLoop( - (string("VL_DEBUG_IF(VL_DBG_MSGF(\"+ Clock loop\\n\"););\n") - + (v3Global.opt.trace() ? "vlSymsp->__Vm_activity = true;\n" : "") - + protect("_eval")+"(vlSymsp);"), false); + emitSettleLoop((string("VL_DEBUG_IF(VL_DBG_MSGF(\"+ Clock loop\\n\"););\n") + + (v3Global.opt.trace() ? "vlSymsp->__Vm_activity = true;\n" : "") + + protect("_eval") + "(vlSymsp);"), + false); if (v3Global.opt.threads() == 1) { puts("Verilated::endOfThreadMTask(vlSymsp->__Vm_evalMsgQp);\n"); } - if (v3Global.opt.threads()) { - puts("Verilated::endOfEval(vlSymsp->__Vm_evalMsgQp);\n"); - } + if (v3Global.opt.threads()) puts("Verilated::endOfEval(vlSymsp->__Vm_evalMsgQp);\n"); puts("}\n"); splitSizeInc(10); @@ -2467,8 +2563,9 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) { puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+eval_end_step " + prefixNameProtect(modp) + "::eval_end_step\\n\"); );\n"); puts("#ifdef VM_TRACE\n"); - puts(EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp; // Setup global symbol table\n"); - puts(EmitCBaseVisitor::symTopAssign()+"\n"); + puts(EmitCBaseVisitor::symClassVar() + + " = this->__VlSymsp; // Setup global symbol table\n"); + puts(EmitCBaseVisitor::symTopAssign() + "\n"); putsDecoration("// Tracing\n"); // SystemC's eval loop deals with calling trace, not us puts("if (VL_UNLIKELY(vlSymsp->__Vm_dumping)) _traceDump();\n"); @@ -2480,12 +2577,11 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) { puts("\nvoid " + prefixNameProtect(modp) + "::" + protect("_eval_initial_loop") + "(" + EmitCBaseVisitor::symClassVar() + ") {\n"); puts("vlSymsp->__Vm_didInit = true;\n"); - puts(protect("_eval_initial")+"(vlSymsp);\n"); - if (v3Global.opt.trace()) { - puts("vlSymsp->__Vm_activity = true;\n"); - } - emitSettleLoop((protect("_eval_settle")+"(vlSymsp);\n" - +protect("_eval")+"(vlSymsp);"), true); + puts(protect("_eval_initial") + "(vlSymsp);\n"); + if (v3Global.opt.trace()) puts("vlSymsp->__Vm_activity = true;\n"); + emitSettleLoop((protect("_eval_settle") + "(vlSymsp);\n" // + + protect("_eval") + "(vlSymsp);"), + true); puts("}\n"); splitSizeInc(10); } @@ -2508,40 +2604,52 @@ void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& pref VarSortMap varAnonMap; VarSortMap varNonanonMap; - for (int isstatic=1; isstatic>=0; isstatic--) { - if (prefixIfImp!="" && !isstatic) continue; - for (AstNode* nodep=firstp; nodep; nodep = nodep->nextp()) { + for (int isstatic = 1; isstatic >= 0; isstatic--) { + if (prefixIfImp != "" && !isstatic) continue; + for (AstNode* nodep = firstp; nodep; nodep = nodep->nextp()) { if (const AstVar* varp = VN_CAST(nodep, Var)) { bool doit = true; switch (which) { - case EVL_CLASS_IO: doit = varp->isIO(); break; + case EVL_CLASS_IO: doit = varp->isIO(); break; case EVL_CLASS_SIG: - doit = ((varp->isSignal() || varp->isClassMember()) && !varp->isIO()); break; + doit = ((varp->isSignal() || varp->isClassMember()) && !varp->isIO()); + break; case EVL_CLASS_TEMP: doit = (varp->isTemp() && !varp->isIO()); break; - case EVL_CLASS_PAR: doit = (varp->isParam() && !VN_IS(varp->valuep(), Const)); break; - case EVL_CLASS_ALL: doit = true; break; - case EVL_FUNC_ALL: doit = true; break; + case EVL_CLASS_PAR: + doit = (varp->isParam() && !VN_IS(varp->valuep(), Const)); + break; + case EVL_CLASS_ALL: doit = true; break; + case EVL_FUNC_ALL: doit = true; break; default: v3fatalSrc("Bad Case"); } if (varp->isStatic() ? !isstatic : isstatic) doit = false; if (doit) { int sigbytes = varp->dtypeSkipRefp()->widthAlignBytes(); int sortbytes = 9; - if (varp->isUsedClock() && varp->widthMin()==1) sortbytes = 0; - else if (VN_IS(varp->dtypeSkipRefp(), UnpackArrayDType)) sortbytes = 8; - else if (varp->basicp() && varp->basicp()->isOpaque()) sortbytes = 7; - else if (varp->isScBv() || varp->isScBigUint()) sortbytes = 6; - else if (sigbytes==8) sortbytes = 5; - else if (sigbytes==4) sortbytes = 4; - else if (sigbytes==2) sortbytes = 2; - else if (sigbytes==1) sortbytes = 1; - + if (varp->isUsedClock() && varp->widthMin() == 1) { + sortbytes = 0; + } else if (VN_IS(varp->dtypeSkipRefp(), UnpackArrayDType)) { + sortbytes = 8; + } else if (varp->basicp() && varp->basicp()->isOpaque()) { + sortbytes = 7; + } else if (varp->isScBv() || varp->isScBigUint()) { + sortbytes = 6; + } else if (sigbytes == 8) { + sortbytes = 5; + } else if (sigbytes == 4) { + sortbytes = 4; + } else if (sigbytes == 2) { + sortbytes = 2; + } else if (sigbytes == 1) { + sortbytes = 1; + } bool anonOk = (v3Global.opt.compLimitMembers() != 0 // Enabled - && !varp->isStatic() - && !varp->isIO() // Confusing to user + && !varp->isStatic() && !varp->isIO() // Confusing to user && !varp->isSc() // Aggregates can't be anon - && (varp->basicp() && !varp->basicp()->isOpaque()) // Aggregates can't be anon - && which != EVL_FUNC_ALL); // Anon not legal in funcs, and gcc bug free there anyhow + && (varp->basicp() + && !varp->basicp()->isOpaque()) // Aggregates can't be anon + && which != EVL_FUNC_ALL); // Anon not legal in funcs, and gcc + // bug free there anyhow if (anonOk) { varAnonMap[sortbytes].push_back(varp); } else { @@ -2570,10 +2678,8 @@ void EmitCStmts::emitVarSort(const VarSortMap& vmap, VarVec* sortedp) { if (!v3Global.opt.mtasks()) { // Plain old serial mode. Sort by size, from small to large, // to optimize for both packing and small offsets in code. - for (VarSortMap::const_iterator it = vmap.begin(); - it != vmap.end(); ++it) { - for (VarVec::const_iterator jt = it->second.begin(); - jt != it->second.end(); ++jt) { + for (VarSortMap::const_iterator it = vmap.begin(); it != vmap.end(); ++it) { + for (VarVec::const_iterator jt = it->second.begin(); jt != it->second.end(); ++jt) { sortedp->push_back(*jt); } } @@ -2602,16 +2708,14 @@ void EmitCStmts::emitVarSort(const VarSortMap& vmap, VarVec* sortedp) { V3TSP::StateVec sorted_states; V3TSP::tspSort(states, &sorted_states); - for (V3TSP::StateVec::iterator it = sorted_states.begin(); - it != sorted_states.end(); ++it) { + for (V3TSP::StateVec::iterator it = sorted_states.begin(); it != sorted_states.end(); ++it) { const EmitVarTspSorter* statep = dynamic_cast(*it); const VarSortMap& localVmap = m2v[statep->mtaskIds()]; // use rbegin/rend to sort size large->small - for (VarSortMap::const_reverse_iterator jt = localVmap.rbegin(); - jt != localVmap.rend(); ++jt) { + for (VarSortMap::const_reverse_iterator jt = localVmap.rbegin(); jt != localVmap.rend(); + ++jt) { const VarVec& vec = jt->second; - for (VarVec::const_iterator kt = vec.begin(); - kt != vec.end(); ++kt) { + for (VarVec::const_iterator kt = vec.begin(); kt != vec.end(); ++kt) { sortedp->push_back(*kt); } } @@ -2619,8 +2723,7 @@ void EmitCStmts::emitVarSort(const VarSortMap& vmap, VarVec* sortedp) { } } -void EmitCStmts::emitSortedVarList(const VarVec& anons, - const VarVec& nonanons, +void EmitCStmts::emitSortedVarList(const VarVec& anons, const VarVec& nonanons, const string& prefixIfImp) { string curVarCmt; // Output anons @@ -2630,25 +2733,26 @@ void EmitCStmts::emitSortedVarList(const VarVec& anons, int anonL3s = 1; int anonL2s = 1; int anonL1s = 1; - if (anonMembers > (lim*lim*lim)) { - anonL3s = (anonMembers + (lim*lim*lim) - 1) / (lim*lim*lim); + if (anonMembers > (lim * lim * lim)) { + anonL3s = (anonMembers + (lim * lim * lim) - 1) / (lim * lim * lim); anonL2s = lim; anonL1s = lim; - } else if (anonMembers > (lim*lim)) { - anonL2s = (anonMembers + (lim*lim) - 1) / (lim*lim); + } else if (anonMembers > (lim * lim)) { + anonL2s = (anonMembers + (lim * lim) - 1) / (lim * lim); anonL1s = lim; } else if (anonMembers > lim) { anonL1s = (anonMembers + lim - 1) / lim; } - if (anonL1s != 1) puts("// Anonymous structures to workaround compiler member-count bugs\n"); + if (anonL1s != 1) + puts("// Anonymous structures to workaround compiler member-count bugs\n"); VarVec::const_iterator it = anons.begin(); - for (int l3=0; l3depGraphp(); - for (const V3GraphVertex* vxp = depGraphp->verticesBeginp(); - vxp; vxp = vxp->verticesNextp()) { + for (const V3GraphVertex* vxp = depGraphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) { const ExecMTask* mtp = dynamic_cast(vxp); if (packedMTaskMayBlock(mtp) > 0) { puts("VlMTaskVertex __Vm_mt_" + cvtToStr(mtp->id()) + ";\n"); @@ -2780,23 +2883,24 @@ void EmitCImp::emitInt(AstNodeModule* modp) { string section; section = "\n// PORTS\n"; - if (modp->isTop()) section += ("// The application code writes and reads these signals to\n" - "// propagate new values into/out from the Verilated model.\n"); - emitVarList(modp->stmtsp(), EVL_CLASS_IO, "", section/*ref*/); + if (modp->isTop()) + section += ("// The application code writes and reads these signals to\n" + "// propagate new values into/out from the Verilated model.\n"); + emitVarList(modp->stmtsp(), EVL_CLASS_IO, "", section /*ref*/); section = "\n// LOCAL SIGNALS\n"; if (modp->isTop()) section += "// Internals; generally not touched by application code\n"; - emitVarList(modp->stmtsp(), EVL_CLASS_SIG, "", section/*ref*/); + emitVarList(modp->stmtsp(), EVL_CLASS_SIG, "", section /*ref*/); section = "\n// LOCAL VARIABLES\n"; if (modp->isTop()) section += "// Internals; generally not touched by application code\n"; - emitVarList(modp->stmtsp(), EVL_CLASS_TEMP, "", section/*ref*/); + emitVarList(modp->stmtsp(), EVL_CLASS_TEMP, "", section /*ref*/); puts("\n// INTERNAL VARIABLES\n"); if (modp->isTop()) puts("// Internals; generally not touched by application code\n"); if (!VN_IS(modp, Class)) { // Avoid clang unused error (& don't want in every object) ofp()->putsPrivate(!modp->isTop()); // private: unless top - puts(symClassName()+"* __VlSymsp; // Symbol table\n"); + puts(symClassName() + "* __VlSymsp; // Symbol table\n"); } ofp()->putsPrivate(false); // public: if (modp->isTop()) { @@ -2808,27 +2912,33 @@ void EmitCImp::emitInt(AstNodeModule* modp) { emitCoverageDecl(modp); // may flip public/private section = "\n// PARAMETERS\n"; - if (modp->isTop()) section += "// Parameters marked /*verilator public*/ for use by application code\n"; + if (modp->isTop()) + section += "// Parameters marked /*verilator public*/ for use by application code\n"; ofp()->putsPrivate(false); // public: - emitVarList(modp->stmtsp(), EVL_CLASS_PAR, "", section/*ref*/); // Only those that are non-CONST + emitVarList(modp->stmtsp(), EVL_CLASS_PAR, "", + section /*ref*/); // Only those that are non-CONST for (AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) { if (const AstVar* varp = VN_CAST(nodep, Var)) { if (varp->isParam() && (varp->isUsedParam() || varp->isSigPublic())) { - if (section != "") { puts(section); section = ""; } + if (section != "") { + puts(section); + section = ""; + } UASSERT_OBJ(varp->valuep(), nodep, "No init for a param?"); // These should be static const values, however microsloth VC++ doesn't // support them. They also cause problems with GDB under GCC2.95. if (varp->isWide()) { // Unsupported for output - putsDecoration("// enum WData "+varp->nameProtect()+" //wide"); + putsDecoration("// enum WData " + varp->nameProtect() + " //wide"); } else if (!VN_IS(varp->valuep(), Const)) { // Unsupported for output - //putsDecoration("// enum ..... "+varp->nameProtect() + // putsDecoration("// enum ..... "+varp->nameProtect() // +"not simple value, see variable above instead"); } else if (VN_IS(varp->dtypep(), BasicDType) - && VN_CAST(varp->dtypep(), BasicDType)->isOpaque()) { // Can't put out e.g. doubles + && VN_CAST(varp->dtypep(), BasicDType) + ->isOpaque()) { // Can't put out e.g. doubles } else { puts("enum "); - puts(varp->isQuad()?"_QData":"_IData"); - puts(""+varp->nameProtect()+" { "+varp->nameProtect()+" = "); + puts(varp->isQuad() ? "_QData" : "_IData"); + puts("" + varp->nameProtect() + " { " + varp->nameProtect() + " = "); iterateAndNextNull(varp->valuep()); puts("};"); } @@ -2859,7 +2969,8 @@ void EmitCImp::emitInt(AstNodeModule* modp) { ofp()->putsPrivate(false); // public: if (modp->isTop()) { puts("/// Construct the model; called by application code\n"); - puts("/// The special name "" may be used to make a wrapper with a\n"); + puts("/// The special name " + " may be used to make a wrapper with a\n"); puts("/// single model invisible with respect to DPI scope names.\n"); } if (VN_IS(modp, Class)) { @@ -2875,10 +2986,12 @@ void EmitCImp::emitInt(AstNodeModule* modp) { } if (v3Global.opt.trace() && modp->isTop()) { puts("/// Trace signals in the model; called by application code\n"); - puts("void trace("+v3Global.opt.traceClassBase()+"C* tfp, int levels, int options = 0);\n"); + puts("void trace(" + v3Global.opt.traceClassBase() + + "C* tfp, int levels, int options = 0);\n"); if (optSystemC()) { puts("/// SC tracing; avoid overloaded virtual function lint warning\n"); - puts("virtual void trace(sc_trace_file* tfp) const { ::sc_core::sc_module::trace(tfp); }\n"); + puts("virtual void trace(sc_trace_file* tfp) const { " + "::sc_core::sc_module::trace(tfp); }\n"); } } @@ -2888,20 +3001,32 @@ void EmitCImp::emitInt(AstNodeModule* modp) { puts("\n// API METHODS\n"); string callEvalEndStep = (v3Global.needTraceDumper() && !optSystemC()) ? "eval_end_step(); " : ""; - if (optSystemC()) ofp()->putsPrivate(true); ///< eval() is invoked by our sensitive() calls. - if (!optSystemC()) puts("/// Evaluate the model. Application must call when inputs change.\n"); + if (optSystemC()) { + ofp()->putsPrivate(true); ///< eval() is invoked by our sensitive() calls. + } + if (!optSystemC()) { + puts("/// Evaluate the model. Application must call when inputs change.\n"); + } puts("void eval() { eval_step(); " + callEvalEndStep + "}\n"); - if (!optSystemC()) puts("/// Evaluate when calling multiple units/models per time step.\n"); + if (!optSystemC()) { + puts("/// Evaluate when calling multiple units/models per time step.\n"); + } puts("void eval_step();\n"); if (!optSystemC()) { puts("/// Evaluate at end of a timestep for tracing, when using eval_step().\n"); puts("/// Application must call after all eval() and before time changes.\n"); puts("void eval_end_step()"); - if (callEvalEndStep == "") puts(" {}\n"); - else puts(";\n"); + if (callEvalEndStep == "") { + puts(" {}\n"); + } else { + puts(";\n"); + } } ofp()->putsPrivate(false); // public: - if (!optSystemC()) puts("/// Simulation complete, run final blocks. Application must call on completion.\n"); + if (!optSystemC()) { + puts("/// Simulation complete, run final blocks. Application " + "must call on completion.\n"); + } puts("void final();\n"); if (v3Global.opt.inhibitSim()) { puts("/// Disable evaluation of module (e.g. turn off)\n"); @@ -2931,17 +3056,17 @@ void EmitCImp::emitInt(AstNodeModule* modp) { if (v3Global.opt.trace() && !VN_IS(modp, Class)) { ofp()->putsPrivate(false); // public: - puts("static void "+protect("traceInit")+"("+v3Global.opt.traceClassBase() - +"* vcdp, void* userthis, uint32_t code);\n"); - puts("static void "+protect("traceFull")+"("+v3Global.opt.traceClassBase() - +"* vcdp, void* userthis, uint32_t code);\n"); - puts("static void "+protect("traceChg")+"("+v3Global.opt.traceClassBase() - +"* vcdp, void* userthis, uint32_t code);\n"); + puts("static void " + protect("traceInit") + "(" + v3Global.opt.traceClassBase() + + "* vcdp, void* userthis, uint32_t code);\n"); + puts("static void " + protect("traceFull") + "(" + v3Global.opt.traceClassBase() + + "* vcdp, void* userthis, uint32_t code);\n"); + puts("static void " + protect("traceChg") + "(" + v3Global.opt.traceClassBase() + + "* vcdp, void* userthis, uint32_t code);\n"); } if (v3Global.opt.savable()) { ofp()->putsPrivate(false); // public: - puts("void "+protect("__Vserialize")+"(VerilatedSerialize& os);\n"); - puts("void "+protect("__Vdeserialize")+"(VerilatedDeserialize& os);\n"); + puts("void " + protect("__Vserialize") + "(VerilatedSerialize& os);\n"); + puts("void " + protect("__Vdeserialize") + "(VerilatedDeserialize& os);\n"); } puts("}"); @@ -2955,14 +3080,11 @@ void EmitCImp::emitInt(AstNodeModule* modp) { if (v3Global.opt.savable() && modp->isTop()) { puts("\n"); puts("inline VerilatedSerialize& operator<<(VerilatedSerialize& os, " - + prefixNameProtect(modp) + "& rhs) {\n" - + "Verilated::quiesce(); rhs." - + protect("__Vserialize") + "(os); return os; }\n"); + + prefixNameProtect(modp) + "& rhs) {\n" // + + "Verilated::quiesce(); rhs." + protect("__Vserialize") + "(os); return os; }\n"); puts("inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, " - + prefixNameProtect(modp) - + "& rhs) {\n" - + "Verilated::quiesce(); rhs." - + protect("__Vdeserialize") + "(os); return os; }\n"); + + prefixNameProtect(modp) + "& rhs) {\n" // + + "Verilated::quiesce(); rhs." + protect("__Vdeserialize") + "(os); return os; }\n"); } } @@ -2988,7 +3110,7 @@ void EmitCImp::emitImp(AstNodeModule* modp) { puts("\n//==========\n"); if (m_slow) { string section; - emitVarList(modp->stmtsp(), EVL_CLASS_ALL, prefixNameProtect(modp), section/*ref*/); + emitVarList(modp->stmtsp(), EVL_CLASS_ALL, prefixNameProtect(modp), section /*ref*/); if (!VN_IS(modp, Class)) emitCtorImp(modp); if (!VN_IS(modp, Class)) emitConfigureImp(modp); if (!VN_IS(modp, Class)) emitDestructorImp(modp); @@ -3017,7 +3139,7 @@ void EmitCImp::maybeSplit(AstNodeModule* fileModp) { // Close old file VL_DO_CLEAR(delete m_ofp, m_ofp = NULL); // Open a new file - m_ofp = newOutCFile(fileModp, !m_fast, true/*source*/, splitFilenumInc()); + m_ofp = newOutCFile(fileModp, !m_fast, true /*source*/, splitFilenumInc()); emitImpTop(fileModp); } splitSizeInc(10); // Even blank functions get a file with a low csplit @@ -3031,7 +3153,7 @@ void EmitCImp::mainInt(AstNodeModule* modp) { UINFO(5, " Emitting " << prefixNameProtect(modp) << endl); - m_ofp = newOutCFile(fileModp, false/*slow*/, false/*source*/); + m_ofp = newOutCFile(fileModp, false /*slow*/, false /*source*/); emitIntTop(modp); emitInt(modp); if (AstClassPackage* packagep = VN_CAST(modp, ClassPackage)) { @@ -3053,7 +3175,7 @@ void EmitCImp::mainImp(AstNodeModule* modp, bool slow, bool fast) { UINFO(5, " Emitting " << prefixNameProtect(modp) << endl); - m_ofp = newOutCFile(fileModp, !m_fast, true/*source*/); + m_ofp = newOutCFile(fileModp, !m_fast, true /*source*/); emitImpTop(fileModp); emitImp(modp); @@ -3071,8 +3193,8 @@ void EmitCImp::mainImp(AstNodeModule* modp, bool slow, bool fast) { // in the ExecGraph AstExecGraph* execGraphp = v3Global.rootp()->execGraphp(); const V3Graph* depGraphp = execGraphp->depGraphp(); - for (const V3GraphVertex* vxp = depGraphp->verticesBeginp(); - vxp; vxp = vxp->verticesNextp()) { + for (const V3GraphVertex* vxp = depGraphp->verticesBeginp(); vxp; + vxp = vxp->verticesNextp()) { const ExecMTask* mtaskp = dynamic_cast(vxp); if (mtaskp->threadRoot()) { maybeSplit(modp); @@ -3097,20 +3219,20 @@ class EmitCTrace : EmitCStmts { AstUser1InUse m_inuser1; // MEMBERS - AstCFunc* m_funcp; // Function we're in now - bool m_slow; // Making slow file - int m_enumNum; // Enumeration number (whole netlist) - int m_baseCode; // Code of first AstTraceInc in this function + AstCFunc* m_funcp; // Function we're in now + bool m_slow; // Making slow file + int m_enumNum; // Enumeration number (whole netlist) + int m_baseCode; // Code of first AstTraceInc in this function // METHODS void newOutCFile(int filenum) { - string filename = (v3Global.opt.makeDir()+"/" - +topClassName()+"_"+protect("_Trace")); - if (filenum) filename += "__"+cvtToStr(filenum); - filename += (m_slow ? "__Slow":""); + string filename + = (v3Global.opt.makeDir() + "/" + topClassName() + "_" + protect("_Trace")); + if (filenum) filename += "__" + cvtToStr(filenum); + filename += (m_slow ? "__Slow" : ""); filename += ".cpp"; - AstCFile* cfilep = newCFile(filename, m_slow, true/*source*/); + AstCFile* cfilep = newCFile(filename, m_slow, true /*source*/); cfilep->support(true); if (m_ofp) v3fatalSrc("Previous file not closed"); @@ -3120,7 +3242,8 @@ class EmitCTrace : EmitCStmts { m_ofp = new V3OutCFile(filename); } m_ofp->putsHeader(); - m_ofp->puts("// DESCR" "IPTION: Verilator output: Tracing implementation internals\n"); + m_ofp->puts("// DESCR" + "IPTION: Verilator output: Tracing implementation internals\n"); emitTraceHeader(); } @@ -3138,64 +3261,66 @@ class EmitCTrace : EmitCStmts { if (v3Global.needTraceDumper() && !optSystemC()) { puts("void " + topClassName() + "::_traceDump() {\n"); // Caller checked for __Vm_dumperp non-NULL - puts( "VerilatedLockGuard lock(__VlSymsp->__Vm_dumperMutex);\n"); - puts( "__VlSymsp->__Vm_dumperp->dump(VL_TIME_Q());\n"); + puts("VerilatedLockGuard lock(__VlSymsp->__Vm_dumperMutex);\n"); + puts("__VlSymsp->__Vm_dumperp->dump(VL_TIME_Q());\n"); puts("}\n"); splitSizeInc(10); } if (v3Global.needTraceDumper()) { puts("void " + topClassName() + "::_traceDumpOpen() {\n"); - puts( "VerilatedLockGuard lock(__VlSymsp->__Vm_dumperMutex);\n"); - puts( "if (VL_UNLIKELY(!__VlSymsp->__Vm_dumperp)) {\n"); - puts( "__VlSymsp->__Vm_dumperp = new " + v3Global.opt.traceClassLang() + "();\n"); - puts( "const char* cp = vl_dumpctl_filenamep();\n"); - puts( "trace(__VlSymsp->__Vm_dumperp, 0, 0);\n"); - puts( "__VlSymsp->__Vm_dumperp->open(vl_dumpctl_filenamep());\n"); - puts( "__VlSymsp->__Vm_dumperp->changeThread();\n"); - puts( "__VlSymsp->__Vm_dumping = true;\n"); - puts( "}\n"); + puts("VerilatedLockGuard lock(__VlSymsp->__Vm_dumperMutex);\n"); + puts("if (VL_UNLIKELY(!__VlSymsp->__Vm_dumperp)) {\n"); + puts("__VlSymsp->__Vm_dumperp = new " + v3Global.opt.traceClassLang() + "();\n"); + puts("const char* cp = vl_dumpctl_filenamep();\n"); + puts("trace(__VlSymsp->__Vm_dumperp, 0, 0);\n"); + puts("__VlSymsp->__Vm_dumperp->open(vl_dumpctl_filenamep());\n"); + puts("__VlSymsp->__Vm_dumperp->changeThread();\n"); + puts("__VlSymsp->__Vm_dumping = true;\n"); + puts("}\n"); puts("}\n"); splitSizeInc(10); puts("void " + topClassName() + "::_traceDumpClose() {\n"); - puts( "VerilatedLockGuard lock(__VlSymsp->__Vm_dumperMutex);\n"); - puts( "__VlSymsp->__Vm_dumping = false;\n"); - puts( "delete __VlSymsp->__Vm_dumperp; __VlSymsp->__Vm_dumperp = NULL;\n"); + puts("VerilatedLockGuard lock(__VlSymsp->__Vm_dumperMutex);\n"); + puts("__VlSymsp->__Vm_dumping = false;\n"); + puts("delete __VlSymsp->__Vm_dumperp; __VlSymsp->__Vm_dumperp = NULL;\n"); puts("}\n"); splitSizeInc(10); } - puts("void "+topClassName()+"::trace("); - puts(v3Global.opt.traceClassBase()+"C* tfp, int, int) {\n"); - puts( "tfp->spTrace()->addCallback(" - "&"+topClassName()+"::"+protect("traceInit") - +", &"+topClassName()+"::"+protect("traceFull") - +", &"+topClassName()+"::"+protect("traceChg")+", this);\n"); + puts("void " + topClassName() + "::trace("); + puts(v3Global.opt.traceClassBase() + "C* tfp, int, int) {\n"); + puts("tfp->spTrace()->addCallback(" + "&" + + topClassName() + "::" + protect("traceInit") + ", &" + topClassName() + + "::" + protect("traceFull") + ", &" + topClassName() + "::" + protect("traceChg") + + ", this);\n"); puts("}\n"); splitSizeInc(10); - puts("void "+topClassName()+"::"+protect("traceInit")+"(" - +v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n"); + puts("void " + topClassName() + "::" + protect("traceInit") + "(" + + v3Global.opt.traceClassBase() + "* vcdp, void* userthis, uint32_t code) {\n"); putsDecoration("// Callback from vcd->open()\n"); - puts(topClassName()+"* t = ("+topClassName()+"*)userthis;\n"); - puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n"); + puts(topClassName() + "* t = (" + topClassName() + "*)userthis;\n"); + puts(EmitCBaseVisitor::symClassVar() + " = t->__VlSymsp; // Setup global symbol table\n"); puts("if (!Verilated::calcUnusedSigs()) {\n"); - puts( "VL_FATAL_MT(__FILE__, __LINE__, __FILE__,\n"); - puts( " \"Turning on wave traces requires Verilated::traceEverOn(true) call before time 0.\");\n"); + puts("VL_FATAL_MT(__FILE__, __LINE__, __FILE__,\n"); + puts(" \"Turning on wave traces requires Verilated::traceEverOn(true) call " + "before time 0.\");\n"); puts("}\n"); puts("vcdp->scopeEscape(' ');\n"); - puts("t->"+protect("traceInitThis")+"(vlSymsp, vcdp, code);\n"); + puts("t->" + protect("traceInitThis") + "(vlSymsp, vcdp, code);\n"); puts("vcdp->scopeEscape('.');\n"); // Restore so later traced files won't break puts("}\n"); splitSizeInc(10); - puts("void "+topClassName()+"::"+protect("traceFull")+"(" - +v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n"); + puts("void " + topClassName() + "::" + protect("traceFull") + "(" + + v3Global.opt.traceClassBase() + "* vcdp, void* userthis, uint32_t code) {\n"); putsDecoration("// Callback from vcd->dump()\n"); - puts(topClassName()+"* t = ("+topClassName()+"*)userthis;\n"); - puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n"); - puts("t->"+protect("traceFullThis")+"(vlSymsp, vcdp, code);\n"); + puts(topClassName() + "* t = (" + topClassName() + "*)userthis;\n"); + puts(EmitCBaseVisitor::symClassVar() + " = t->__VlSymsp; // Setup global symbol table\n"); + puts("t->" + protect("traceFullThis") + "(vlSymsp, vcdp, code);\n"); puts("}\n"); splitSizeInc(10); @@ -3205,13 +3330,13 @@ class EmitCTrace : EmitCStmts { void emitTraceFast() { puts("\n//======================\n\n"); - puts("void "+topClassName()+"::"+protect("traceChg")+"(" - +v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n"); + puts("void " + topClassName() + "::" + protect("traceChg") + "(" + + v3Global.opt.traceClassBase() + "* vcdp, void* userthis, uint32_t code) {\n"); putsDecoration("// Callback from vcd->dump()\n"); - puts(topClassName()+"* t = ("+topClassName()+"*)userthis;\n"); - puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n"); + puts(topClassName() + "* t = (" + topClassName() + "*)userthis;\n"); + puts(EmitCBaseVisitor::symClassVar() + " = t->__VlSymsp; // Setup global symbol table\n"); puts("if (vlSymsp->getClearActivity()) {\n"); - puts("t->"+protect("traceChgThis")+"(vlSymsp, vcdp, code);\n"); + puts("t->" + protect("traceChgThis") + "(vlSymsp, vcdp, code);\n"); puts("}\n"); puts("}\n"); splitSizeInc(10); @@ -3253,24 +3378,25 @@ class EmitCTrace : EmitCStmts { puts("vcdp->declBit"); } - puts("(c+"+cvtToStr(nodep->code())); - if (nodep->arrayRange().ranged()) puts("+i*"+cvtToStr(nodep->widthWords())); + puts("(c+" + cvtToStr(nodep->code())); + if (nodep->arrayRange().ranged()) puts("+i*" + cvtToStr(nodep->widthWords())); puts(","); - if (nodep->isScoped()) { - puts("Verilated::catName(scopep,"); - } + if (nodep->isScoped()) puts("Verilated::catName(scopep,"); putsQuoted(VIdProtect::protectWordsIf(nodep->showname(), nodep->protect())); - if (nodep->isScoped()) { - puts(",\" \")"); - } + if (nodep->isScoped()) puts(",\" \")"); // Direction if (v3Global.opt.traceFormat().fstFlavor()) { - puts(","+cvtToStr(enumNum)); + puts("," + cvtToStr(enumNum)); // fstVarDir - if (nodep->declDirection().isInoutish()) puts(",FST_VD_INOUT"); - else if (nodep->declDirection().isWritable()) puts(",FST_VD_OUTPUT"); - else if (nodep->declDirection().isNonOutput()) puts(",FST_VD_INPUT"); - else puts(", FST_VD_IMPLICIT"); + if (nodep->declDirection().isInoutish()) { + puts(",FST_VD_INOUT"); + } else if (nodep->declDirection().isWritable()) { + puts(",FST_VD_OUTPUT"); + } else if (nodep->declDirection().isNonOutput()) { + puts(",FST_VD_INPUT"); + } else { + puts(", FST_VD_IMPLICIT"); + } // // fstVarType AstVarType vartype = nodep->varType(); @@ -3280,8 +3406,11 @@ class EmitCTrace : EmitCStmts { if (nodep->dtypep()->basicp()->isDouble()) { if (vartype == AstVarType::GPARAM || vartype == AstVarType::LPARAM) { fstvt = "FST_VT_VCD_REAL_PARAMETER"; - } else fstvt = "FST_VT_VCD_REAL"; + } else { + fstvt = "FST_VT_VCD_REAL"; + } } + // clang-format off else if (vartype == AstVarType::GPARAM) fstvt = "FST_VT_VCD_PARAMETER"; else if (vartype == AstVarType::LPARAM) fstvt = "FST_VT_VCD_PARAMETER"; else if (vartype == AstVarType::SUPPLY0) fstvt = "FST_VT_VCD_SUPPLY0"; @@ -3300,6 +3429,7 @@ class EmitCTrace : EmitCStmts { else if (kwd == AstBasicDTypeKwd::LONGINT) fstvt = "FST_VT_SV_LONGINT"; else if (kwd == AstBasicDTypeKwd::BYTE) fstvt = "FST_VT_SV_BYTE"; else fstvt = "FST_VT_SV_BIT"; + // clang-format on // // Not currently supported // FST_VT_VCD_EVENT @@ -3314,7 +3444,7 @@ class EmitCTrace : EmitCStmts { // FST_VT_VCD_WOR // FST_VT_SV_ENUM // FST_VT_GEN_STRING - puts(","+fstvt); + puts("," + fstvt); } // Range if (nodep->arrayRange().ranged()) { @@ -3341,31 +3471,28 @@ class EmitCTrace : EmitCStmts { enump->user1(enumNum); int nvals = 0; puts("{\n"); - puts("const char* "+protect("__VenumItemNames")+"[]\n"); + puts("const char* " + protect("__VenumItemNames") + "[]\n"); puts("= {"); for (AstEnumItem* itemp = enump->itemsp(); itemp; itemp = VN_CAST(itemp->nextp(), EnumItem)) { if (++nvals > 1) puts(", "); - putbs("\""+itemp->prettyName()+"\""); + putbs("\"" + itemp->prettyName() + "\""); } puts("};\n"); nvals = 0; - puts("const char* "+protect("__VenumItemValues")+"[]\n"); + puts("const char* " + protect("__VenumItemValues") + "[]\n"); puts("= {"); for (AstEnumItem* itemp = enump->itemsp(); itemp; itemp = VN_CAST(itemp->nextp(), EnumItem)) { AstConst* constp = VN_CAST(itemp->valuep(), Const); if (++nvals > 1) puts(", "); - putbs("\""+constp->num().displayed(nodep, "%0b")+"\""); + putbs("\"" + constp->num().displayed(nodep, "%0b") + "\""); } puts("};\n"); - puts("vcdp->declDTypeEnum("+cvtToStr(enumNum) - +", \""+enump->prettyName()+"\", " - +cvtToStr(nvals) - +", "+cvtToStr(enump->widthMin()) - +", "+protect("__VenumItemNames") - +", "+protect("__VenumItemValues") - +");\n"); + puts("vcdp->declDTypeEnum(" + cvtToStr(enumNum) + ", \"" + enump->prettyName() + + "\", " + cvtToStr(nvals) + ", " + cvtToStr(enump->widthMin()) + ", " + + protect("__VenumItemNames") + ", " + protect("__VenumItemValues") + + ");\n"); puts("}\n"); } return enumNum; @@ -3378,7 +3505,8 @@ class EmitCTrace : EmitCStmts { iterateAndNextNull(nodep->precondsp()); string full = ((m_funcp->funcType() == AstCFuncType::TRACE_FULL || m_funcp->funcType() == AstCFuncType::TRACE_FULL_SUB) - ? "full":"chg"); + ? "full" + : "chg"); bool emitWidth = false; if (nodep->dtypep()->basicp()->isDouble()) { puts("vcdp->" + full + "Double"); @@ -3406,19 +3534,30 @@ class EmitCTrace : EmitCStmts { AstVarRef* varrefp = VN_CAST(nodep->valuep(), VarRef); AstVar* varp = varrefp->varp(); puts("("); - if (emitTraceIsScBigUint(nodep)) puts("(vluint32_t*)"); - else if (emitTraceIsScBv(nodep)) puts("VL_SC_BV_DATAP("); + if (emitTraceIsScBigUint(nodep)) { + puts("(vluint32_t*)"); + } else if (emitTraceIsScBv(nodep)) { + puts("VL_SC_BV_DATAP("); + } iterate(varrefp); // Put var name out // Tracing only supports 1D arrays if (nodep->declp()->arrayRange().ranged()) { - if (arrayindex==-2) puts("[i]"); - else if (arrayindex==-1) puts("[0]"); - else puts("["+cvtToStr(arrayindex)+"]"); + if (arrayindex == -2) { + puts("[i]"); + } else if (arrayindex == -1) { + puts("[0]"); + } else { + puts("[" + cvtToStr(arrayindex) + "]"); + } } if (varp->isSc()) puts(".read()"); - if (emitTraceIsScUint(nodep)) puts(nodep->isQuad() ? ".to_uint64()" : ".to_uint()"); - else if (emitTraceIsScBigUint(nodep)) puts(".get_raw()"); - else if (emitTraceIsScBv(nodep)) puts(")"); + if (emitTraceIsScUint(nodep)) { + puts(nodep->isQuad() ? ".to_uint64()" : ".to_uint()"); + } else if (emitTraceIsScBigUint(nodep)) { + puts(".get_raw()"); + } else if (emitTraceIsScBv(nodep)) { + puts(")"); + } puts(")"); } else { puts("("); @@ -3433,9 +3572,7 @@ class EmitCTrace : EmitCStmts { // Top module only iterate(nodep->topModulep()); } - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { - iterateChildren(nodep); - } + virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { iterateChildren(nodep); } virtual void visit(AstCFunc* nodep) VL_OVERRIDE { if (nodep->slow() != m_slow) return; if (nodep->funcType().isTrace()) { // TRACE_* @@ -3451,11 +3588,11 @@ class EmitCTrace : EmitCStmts { splitSizeInc(nodep); puts("\n"); - puts(nodep->rtnTypeVoid()); puts(" "); - puts(topClassName()+"::"+nodep->nameProtect() - +"("+cFuncArgs(nodep)+") {\n"); + puts(nodep->rtnTypeVoid()); + puts(" "); + puts(topClassName() + "::" + nodep->nameProtect() + "(" + cFuncArgs(nodep) + ") {\n"); - if (nodep->symProlog()) puts(EmitCBaseVisitor::symTopAssign()+"\n"); + if (nodep->symProlog()) puts(EmitCBaseVisitor::symTopAssign() + "\n"); m_baseCode = -1; @@ -3482,7 +3619,9 @@ class EmitCTrace : EmitCStmts { } else if (nodep->funcType() == AstCFuncType::TRACE_FULL_SUB) { } else if (nodep->funcType() == AstCFuncType::TRACE_CHANGE) { } else if (nodep->funcType() == AstCFuncType::TRACE_CHANGE_SUB) { - } else nodep->v3fatalSrc("Bad Case"); + } else { + nodep->v3fatalSrc("Bad Case"); + } if (nodep->initsp()) { string section; @@ -3508,7 +3647,7 @@ class EmitCTrace : EmitCStmts { virtual void visit(AstTraceDecl* nodep) VL_OVERRIDE { int enumNum = emitTraceDeclDType(nodep->dtypep()); if (nodep->arrayRange().ranged()) { - puts("{int i; for (i=0; i<"+cvtToStr(nodep->arrayRange().elements())+"; i++) {\n"); + puts("{int i; for (i=0; i<" + cvtToStr(nodep->arrayRange().elements()) + "; i++) {\n"); emitTraceInitOne(nodep, enumNum); puts("}}\n"); } else { @@ -3519,17 +3658,15 @@ class EmitCTrace : EmitCStmts { virtual void visit(AstTraceInc* nodep) VL_OVERRIDE { if (nodep->declp()->arrayRange().ranged()) { // It traces faster if we unroll the loop - for (int i=0; ideclp()->arrayRange().elements(); i++) { + for (int i = 0; i < nodep->declp()->arrayRange().elements(); i++) { emitTraceChangeOne(nodep, i); } } else { emitTraceChangeOne(nodep, -1); } } - virtual void visit(AstCoverDecl* nodep) VL_OVERRIDE { - } - virtual void visit(AstCoverInc* nodep) VL_OVERRIDE { - } + virtual void visit(AstCoverDecl* nodep) VL_OVERRIDE {} + virtual void visit(AstCoverInc* nodep) VL_OVERRIDE {} public: explicit EmitCTrace(bool slow) { @@ -3542,8 +3679,11 @@ public: // Put out the file newOutCFile(0); - if (m_slow) emitTraceSlow(); - else emitTraceFast(); + if (m_slow) { + emitTraceSlow(); + } else { + emitTraceFast(); + } iterate(v3Global.rootp()); @@ -3555,11 +3695,12 @@ public: // EmitC class functions void V3EmitC::emitc() { - UINFO(2,__FUNCTION__<<": "<modulesp(); - nodep; nodep = VN_CAST(nodep->nextp(), NodeModule)) { + for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep; + nodep = VN_CAST(nodep->nextp(), NodeModule)) { if (VN_IS(nodep, Class)) continue; // Imped with ClassPackage + // clang-format off { EmitCImp cint; cint.mainInt(nodep); } if (v3Global.opt.outputSplit()) { { EmitCImp fast; fast.mainImp(nodep, false, true); } @@ -3567,25 +3708,29 @@ void V3EmitC::emitc() { } else { { EmitCImp both; both.mainImp(nodep, true, true); } } + // clang-format on } } void V3EmitC::emitcTrace() { - UINFO(2,__FUNCTION__<<": "<filesp(); filep; filep = VN_CAST(filep->nextp(), NodeFile)) { AstCFile* cfilep = VN_CAST(filep, CFile); if (cfilep && cfilep->tblockp()) { V3OutCFile of(cfilep->name()); - of.puts("// DESCR" "IPTION: Verilator generated C++\n"); + of.puts("// DESCR" + "IPTION: Verilator generated C++\n"); EmitCStmts visitor(cfilep->tblockp(), &of, true); } } diff --git a/src/V3EmitCBase.h b/src/V3EmitCBase.h index d0c9d76f8..8e98efafe 100644 --- a/src/V3EmitCBase.h +++ b/src/V3EmitCBase.h @@ -39,23 +39,32 @@ public: V3OutCFile* ofp() const { return m_ofp; } void puts(const string& str) { ofp()->puts(str); } void putbs(const string& str) { ofp()->putbs(str); } - void putsDecoration(const string& str) { if (v3Global.opt.decoration()) puts(str); } + void putsDecoration(const string& str) { + if (v3Global.opt.decoration()) puts(str); + } void putsQuoted(const string& str) { ofp()->putsQuoted(str); } bool optSystemC() { return v3Global.opt.systemC(); } static string protect(const string& name) { return VIdProtect::protectIf(name, true); } static string protectIf(const string& name, bool doIt) { - return VIdProtect::protectIf(name, doIt); } + return VIdProtect::protectIf(name, doIt); + } static string protectWordsIf(const string& name, bool doIt) { - return VIdProtect::protectWordsIf(name, doIt); } + return VIdProtect::protectWordsIf(name, doIt); + } static string ifNoProtect(const string& in) { return v3Global.opt.protectIds() ? "" : in; } - static string symClassName() { return v3Global.opt.prefix()+"_"+protect("_Syms"); } - static string symClassVar() { return symClassName()+"* __restrict vlSymsp"; } + static string symClassName() { return v3Global.opt.prefix() + "_" + protect("_Syms"); } + static string symClassVar() { return symClassName() + "* __restrict vlSymsp"; } static string symTopAssign() { - return v3Global.opt.prefix()+"* __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;"; } + return v3Global.opt.prefix() + "* __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;"; + } static string funcNameProtect(const AstCFunc* nodep, const AstNodeModule* modp) { - if (nodep->isConstructor()) return prefixNameProtect(modp); - else if (nodep->isDestructor()) return string("~") + prefixNameProtect(modp); - else return nodep->nameProtect(); + if (nodep->isConstructor()) { + return prefixNameProtect(modp); + } else if (nodep->isDestructor()) { + return string("~") + prefixNameProtect(modp); + } else { + return nodep->nameProtect(); + } } static string prefixNameProtect(const AstNode* nodep) { // C++ name with prefix const AstNodeModule* modp = VN_CAST_CONST(nodep, NodeModule); @@ -79,15 +88,17 @@ public: // Return argument list for given C function string args = nodep->argTypes(); // Might be a user function with argument list. - for (const AstNode* stmtp = nodep->argsp(); stmtp; stmtp=stmtp->nextp()) { + for (const AstNode* stmtp = nodep->argsp(); stmtp; stmtp = stmtp->nextp()) { if (const AstVar* portp = VN_CAST_CONST(stmtp, Var)) { if (portp->isIO() && !portp->isFuncReturn()) { - if (args != "") args+= ", "; - if (nodep->dpiImport() || nodep->dpiExportWrapper()) + if (args != "") args += ", "; + if (nodep->dpiImport() || nodep->dpiExportWrapper()) { args += portp->dpiArgType(true, false); - else if (nodep->funcPublic()) + } else if (nodep->funcPublic()) { args += portp->cPubArgType(true, false); - else args += portp->vlArgType(true, false, true); + } else { + args += portp->vlArgType(true, false, true); + } } } } @@ -114,6 +125,7 @@ private: m_count++; iterateChildren(nodep); } + public: // CONSTRUCTORS explicit EmitCBaseCounterVisitor(AstNode* nodep) { diff --git a/src/V3EmitCMake.cpp b/src/V3EmitCMake.cpp index 2eed8feb8..793ce9bbc 100644 --- a/src/V3EmitCMake.cpp +++ b/src/V3EmitCMake.cpp @@ -35,8 +35,7 @@ class CMakeEmitter { // STATIC FUNCTIONS // Concatenate all strings in 'strs' with ' ' between them. - template - static string cmake_list(const List& strs) { + template static string cmake_list(const List& strs) { string s; if (strs.begin() != strs.end()) { s.append("\""); @@ -56,16 +55,14 @@ class CMakeEmitter { // "BOOL", "FILEPATH", "PATH", "STRING" or "INTERNAL" for a CACHE variable // See https://cmake.org/cmake/help/latest/command/set.html static void cmake_set_raw(std::ofstream& of, const string& name, const string& raw_value, - const string& cache_type = "", const string& docstring = "") { + const string& cache_type = "", const string& docstring = "") { of << "set(" << name << " " << raw_value; - if (!cache_type.empty()) { - of << " CACHE " << cache_type << " \"" << docstring << "\""; - } + if (!cache_type.empty()) { of << " CACHE " << cache_type << " \"" << docstring << "\""; } of << ")\n"; } static void cmake_set(std::ofstream& of, const string& name, const string& value, - const string& cache_type = "", const string& docstring = "") { + const string& cache_type = "", const string& docstring = "") { string raw_value = "\"" + value + "\""; cmake_set_raw(of, name, raw_value, cache_type, docstring); } @@ -80,22 +77,24 @@ class CMakeEmitter { } static void emitOverallCMake() { - const vl_unique_ptr - of (V3File::new_ofstream(v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+".cmake")); + const vl_unique_ptr of( + V3File::new_ofstream(v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + ".cmake")); string name = v3Global.opt.prefix(); *of << "# Verilated -*- CMake -*-\n"; - *of << "# DESCR" "IPTION: Verilator output: CMake include script with class lists\n"; + *of << "# DESCR" + "IPTION: Verilator output: CMake include script with class lists\n"; *of << "#\n"; - *of << "# This CMake script lists generated Verilated files, for including in higher level CMake scripts.\n"; + *of << "# This CMake script lists generated Verilated files, for " + "including in higher level CMake scripts.\n"; *of << "# This file is meant to be consumed by the verilate() function,\n"; *of << "# which becomes available after executing `find_package(verilator).\n"; *of << "\n### Constants...\n"; - cmake_set(*of, "PERL", deslash(V3Options::getenvPERL()), - "FILEPATH", "Perl executable (from $PERL)"); - cmake_set(*of, "VERILATOR_ROOT", deslash(V3Options::getenvVERILATOR_ROOT()), - "PATH", "Path to Verilator kit (from $VERILATOR_ROOT)"); + cmake_set(*of, "PERL", deslash(V3Options::getenvPERL()), "FILEPATH", + "Perl executable (from $PERL)"); + cmake_set(*of, "VERILATOR_ROOT", deslash(V3Options::getenvVERILATOR_ROOT()), "PATH", + "Path to Verilator kit (from $VERILATOR_ROOT)"); *of << "\n### Compiler flags...\n"; @@ -110,13 +109,19 @@ class CMakeEmitter { *of << "# SystemC output mode? 0/1 (from --sc)\n"; cmake_set_raw(*of, name + "_SC", v3Global.opt.systemC() ? "1" : "0"); *of << "# Coverage output mode? 0/1 (from --coverage)\n"; - cmake_set_raw(*of, name + "_COVERAGE", v3Global.opt.coverage()?"1":"0"); + cmake_set_raw(*of, name + "_COVERAGE", v3Global.opt.coverage() ? "1" : "0"); *of << "# Threaded output mode? 0/1/N threads (from --threads)\n"; cmake_set_raw(*of, name + "_THREADS", cvtToStr(v3Global.opt.threads())); *of << "# VCD Tracing output mode? 0/1 (from --trace)\n"; - cmake_set_raw(*of, name + "_TRACE_VCD", (v3Global.opt.trace() && (v3Global.opt.traceFormat() == TraceFormat::VCD))?"1":"0"); + cmake_set_raw(*of, name + "_TRACE_VCD", + (v3Global.opt.trace() && (v3Global.opt.traceFormat() == TraceFormat::VCD)) + ? "1" + : "0"); *of << "# FST Tracing output mode? 0/1 (from --fst-trace)\n"; - cmake_set_raw(*of, name + "_TRACE_FST", (v3Global.opt.trace() && (v3Global.opt.traceFormat() != TraceFormat::VCD)) ? "1":"0"); + cmake_set_raw(*of, name + "_TRACE_FST", + (v3Global.opt.trace() && (v3Global.opt.traceFormat() != TraceFormat::VCD)) + ? "1" + : "0"); *of << "\n### Sources...\n"; std::vector classes_fast, classes_slow, support_fast, support_slow, global; @@ -141,7 +146,7 @@ class CMakeEmitter { } global.push_back("${VERILATOR_ROOT}/include/verilated.cpp"); - if (v3Global.dpi()) { + if (v3Global.dpi()) { // global.push_back("${VERILATOR_ROOT}/include/verilated_dpi.cpp"); } if (v3Global.opt.vpi()) { @@ -154,21 +159,22 @@ class CMakeEmitter { global.push_back("${VERILATOR_ROOT}/include/verilated_cov.cpp"); } if (v3Global.opt.trace()) { - global.push_back("${VERILATOR_ROOT}/include/" - + v3Global.opt.traceSourceBase() + "_c.cpp"); + global.push_back("${VERILATOR_ROOT}/include/" + v3Global.opt.traceSourceBase() + + "_c.cpp"); if (v3Global.opt.systemC()) { if (v3Global.opt.traceFormat() != TraceFormat::VCD) { - v3error("Unsupported: This trace format is not supported in SystemC, use VCD format."); + v3error("Unsupported: This trace format is not supported in SystemC, " + "use VCD format."); } - global.push_back("${VERILATOR_ROOT}/include/" - + v3Global.opt.traceSourceLang() + ".cpp"); + global.push_back("${VERILATOR_ROOT}/include/" + v3Global.opt.traceSourceLang() + + ".cpp"); } } if (v3Global.opt.mtasks()) { global.push_back("${VERILATOR_ROOT}/include/verilated_threads.cpp"); } if (!v3Global.opt.protectLib().empty()) { - global.push_back(v3Global.opt.makeDir()+"/"+v3Global.opt.protectLib()+".cpp"); + global.push_back(v3Global.opt.makeDir() + "/" + v3Global.opt.protectLib() + ".cpp"); } *of << "# Global classes, need linked once per executable\n"; @@ -177,7 +183,8 @@ class CMakeEmitter { cmake_set_raw(*of, name + "_CLASSES_SLOW", deslash(cmake_list(classes_slow))); *of << "# Generated module classes, fast-path, compile with highest optimization\n"; cmake_set_raw(*of, name + "_CLASSES_FAST", deslash(cmake_list(classes_fast))); - *of << "# Generated support classes, non-fast-path, compile with low/medium optimization\n"; + *of << "# Generated support classes, non-fast-path, compile with " + "low/medium optimization\n"; cmake_set_raw(*of, name + "_SUPPORT_SLOW", deslash(cmake_list(support_slow))); *of << "# Generated support classes, fast-path, compile with highest optimization\n"; cmake_set_raw(*of, name + "_SUPPORT_FAST", deslash(cmake_list(support_fast))); @@ -188,14 +195,13 @@ class CMakeEmitter { *of << "# User .cpp files (from .cpp's on Verilator command line)\n"; cmake_set_raw(*of, name + "_USER_CLASSES", deslash(cmake_list(v3Global.opt.cppFiles()))); } + public: - explicit CMakeEmitter() { - emitOverallCMake(); - } + explicit CMakeEmitter() { emitOverallCMake(); } virtual ~CMakeEmitter() {} }; void V3EmitCMake::emit() { - UINFO(2,__FUNCTION__<<": "<filesp(); - nodep; nodep = VN_CAST(nodep->nextp(), NodeFile)) { + if (v3Global.opt.mtasks()) { putMakeClassEntry(of, "verilated_threads.cpp"); } + } else if (support == 2 && slow) { + } else { + for (AstNodeFile* nodep = v3Global.rootp()->filesp(); nodep; + nodep = VN_CAST(nodep->nextp(), NodeFile)) { AstCFile* cfilep = VN_CAST(nodep, CFile); - if (cfilep && cfilep->source() - && cfilep->slow()==(slow!=0) - && cfilep->support()==(support!=0)) { + if (cfilep && cfilep->source() && cfilep->slow() == (slow != 0) + && cfilep->support() == (support != 0)) { putMakeClassEntry(of, cfilep->name()); } } @@ -122,55 +126,56 @@ public: void emitOverallMake() { // Generate the makefile - V3OutMkFile of (v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+".mk"); + V3OutMkFile of(v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + ".mk"); of.putsHeader(); - of.puts("# DESCR" "IPTION: Verilator output: Makefile for building Verilated archive or executable\n"); + of.puts("# DESCR" + "IPTION: Verilator output: " + "Makefile for building Verilated archive or executable\n"); of.puts("#\n"); of.puts("# Execute this makefile from the object directory:\n"); - of.puts("# make -f "+v3Global.opt.prefix()+".mk"+"\n"); + of.puts("# make -f " + v3Global.opt.prefix() + ".mk" + "\n"); of.puts("\n"); if (v3Global.opt.exe()) { - of.puts("default: "+v3Global.opt.exeName()+"\n"); + of.puts("default: " + v3Global.opt.exeName() + "\n"); } else if (!v3Global.opt.protectLib().empty()) { - of.puts("default: lib"+v3Global.opt.protectLib()+"\n"); + of.puts("default: lib" + v3Global.opt.protectLib() + "\n"); } else { - of.puts("default: "+v3Global.opt.prefix()+"__ALL.a\n"); + of.puts("default: " + v3Global.opt.prefix() + "__ALL.a\n"); } of.puts("\n### Constants...\n"); of.puts("# Perl executable (from $PERL)\n"); - of.puts("PERL = "+V3Options::getenvPERL()+"\n"); + of.puts("PERL = " + V3Options::getenvPERL() + "\n"); of.puts("# Path to Verilator kit (from $VERILATOR_ROOT)\n"); - of.puts("VERILATOR_ROOT = "+V3Options::getenvVERILATOR_ROOT()+"\n"); + of.puts("VERILATOR_ROOT = " + V3Options::getenvVERILATOR_ROOT() + "\n"); of.puts("# SystemC include directory with systemc.h (from $SYSTEMC_INCLUDE)\n"); - of.puts(string("SYSTEMC_INCLUDE ?= ")+V3Options::getenvSYSTEMC_INCLUDE()+"\n"); + of.puts(string("SYSTEMC_INCLUDE ?= ") + V3Options::getenvSYSTEMC_INCLUDE() + "\n"); of.puts("# SystemC library directory with libsystemc.a (from $SYSTEMC_LIBDIR)\n"); - of.puts(string("SYSTEMC_LIBDIR ?= ")+V3Options::getenvSYSTEMC_LIBDIR()+"\n"); + of.puts(string("SYSTEMC_LIBDIR ?= ") + V3Options::getenvSYSTEMC_LIBDIR() + "\n"); of.puts("\n### Switches...\n"); of.puts("# SystemC output mode? 0/1 (from --sc)\n"); - of.puts(string("VM_SC = ")+((v3Global.opt.systemC())?"1":"0")+"\n"); + of.puts(string("VM_SC = ") + ((v3Global.opt.systemC()) ? "1" : "0") + "\n"); of.puts("# Legacy or SystemC output mode? 0/1 (from --sc)\n"); of.puts(string("VM_SP_OR_SC = $(VM_SC)\n")); of.puts("# Deprecated\n"); - of.puts(string("VM_PCLI = ")+(v3Global.opt.systemC()?"0":"1")+"\n"); - of.puts("# Deprecated: SystemC architecture to find link library path (from $SYSTEMC_ARCH)\n"); - of.puts(string("VM_SC_TARGET_ARCH = ")+V3Options::getenvSYSTEMC_ARCH()+"\n"); + of.puts(string("VM_PCLI = ") + (v3Global.opt.systemC() ? "0" : "1") + "\n"); + of.puts( + "# Deprecated: SystemC architecture to find link library path (from $SYSTEMC_ARCH)\n"); + of.puts(string("VM_SC_TARGET_ARCH = ") + V3Options::getenvSYSTEMC_ARCH() + "\n"); of.puts("\n### Vars...\n"); of.puts("# Design prefix (from --prefix)\n"); - of.puts(string("VM_PREFIX = ")+v3Global.opt.prefix()+"\n"); + of.puts(string("VM_PREFIX = ") + v3Global.opt.prefix() + "\n"); of.puts("# Module prefix (from --prefix)\n"); - of.puts(string("VM_MODPREFIX = ")+v3Global.opt.modPrefix()+"\n"); + of.puts(string("VM_MODPREFIX = ") + v3Global.opt.modPrefix() + "\n"); of.puts("# User CFLAGS (from -CFLAGS on Verilator command line)\n"); of.puts("VM_USER_CFLAGS = \\\n"); - if (!v3Global.opt.protectLib().empty()) { - of.puts("\t-fPIC \\\n"); - } + if (!v3Global.opt.protectLib().empty()) of.puts("\t-fPIC \\\n"); const V3StringList& cFlags = v3Global.opt.cFlags(); for (V3StringList::const_iterator it = cFlags.begin(); it != cFlags.end(); ++it) { - of.puts("\t"+*it+" \\\n"); + of.puts("\t" + *it + " \\\n"); } of.puts("\n"); @@ -178,7 +183,7 @@ public: of.puts("VM_USER_LDLIBS = \\\n"); const V3StringList& ldLibs = v3Global.opt.ldLibs(); for (V3StringList::const_iterator it = ldLibs.begin(); it != ldLibs.end(); ++it) { - of.puts("\t"+*it+" \\\n"); + of.puts("\t" + *it + " \\\n"); } of.puts("\n"); @@ -188,7 +193,7 @@ public: const V3StringSet& cppFiles = v3Global.opt.cppFiles(); for (V3StringSet::const_iterator it = cppFiles.begin(); it != cppFiles.end(); ++it) { string cppfile = *it; - of.puts("\t"+V3Os::filenameNonExt(cppfile)+" \\\n"); + of.puts("\t" + V3Os::filenameNonExt(cppfile) + " \\\n"); string dir = V3Os::filenameDir(cppfile); dirs.insert(dir); } @@ -196,14 +201,14 @@ public: of.puts("# User .cpp directories (from .cpp's on Verilator command line)\n"); of.puts("VM_USER_DIR = \\\n"); - for (V3StringSet::iterator it = dirs.begin(); it!=dirs.end(); ++it) { - of.puts("\t"+*it+" \\\n"); + for (V3StringSet::iterator it = dirs.begin(); it != dirs.end(); ++it) { + of.puts("\t" + *it + " \\\n"); } of.puts("\n"); of.puts("\n### Default rules...\n"); of.puts("# Include list of all generated classes\n"); - of.puts("include "+v3Global.opt.prefix()+"_classes.mk\n"); + of.puts("include " + v3Global.opt.prefix() + "_classes.mk\n"); of.puts("# Include global rules\n"); of.puts("include $(VERILATOR_ROOT)/include/verilated.mk\n"); @@ -215,12 +220,13 @@ public: string cppfile = *it; string basename = V3Os::filenameNonExt(cppfile); // NOLINTNEXTLINE(performance-inefficient-string-concatenation) - of.puts(basename+".o: "+cppfile+"\n"); + of.puts(basename + ".o: " + cppfile + "\n"); of.puts("\t$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $<\n"); } of.puts("\n### Link rules... (from --exe)\n"); - of.puts(v3Global.opt.exeName()+": $(VK_USER_OBJS) $(VK_GLOBAL_OBJS) $(VM_PREFIX)__ALL.a\n"); + of.puts(v3Global.opt.exeName() + + ": $(VK_USER_OBJS) $(VK_GLOBAL_OBJS) $(VM_PREFIX)__ALL.a\n"); of.puts("\t$(LINK) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) $(SC_LIBS)\n"); of.puts("\n"); } @@ -229,18 +235,20 @@ public: of.puts("\n### Library rules... (from --protect-lib)\n"); of.puts("# Using -fPIC objects for both static and dynamic libraries " "(which appears to work)\n"); - of.puts(v3Global.opt.protectLibName(false)+": $(VK_OBJS) $(VK_GLOBAL_OBJS)\n"); - of.puts("\t$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o "+ - v3Global.opt.protectLib()+".o "+v3Global.opt.protectLib()+".cpp\n"); - of.puts("\tar rc $@ $^ "+v3Global.opt.protectLib()+".o\n"); + of.puts(v3Global.opt.protectLibName(false) + ": $(VK_OBJS) $(VK_GLOBAL_OBJS)\n"); + of.puts("\t$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o " + + v3Global.opt.protectLib() + ".o " + v3Global.opt.protectLib() + ".cpp\n"); + of.puts("\tar rc $@ $^ " + v3Global.opt.protectLib() + ".o\n"); of.puts("\n"); - of.puts(v3Global.opt.protectLibName(true)+": $(VM_PREFIX)__ALL.a $(VK_GLOBAL_OBJS)\n"); - of.puts("\t$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -shared -o $@ "+v3Global.opt.protectLib()+".cpp $^\n"); + of.puts(v3Global.opt.protectLibName(true) + + ": $(VM_PREFIX)__ALL.a $(VK_GLOBAL_OBJS)\n"); + of.puts("\t$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -shared -o $@ " + + v3Global.opt.protectLib() + ".cpp $^\n"); of.puts("\n"); - of.puts("lib"+v3Global.opt.protectLib()+": "+v3Global.opt.protectLibName(false)+ - " "+v3Global.opt.protectLibName(true)+"\n"); + of.puts("lib" + v3Global.opt.protectLib() + ": " + v3Global.opt.protectLibName(false) + + " " + v3Global.opt.protectLibName(true) + "\n"); } of.puts("\n"); @@ -259,6 +267,6 @@ public: // Gate class functions void V3EmitMk::emitmk() { - UINFO(2,__FUNCTION__<<": "<verilogKwd() + " " + prefixNameProtect(nodep) + ";\n"); iterateChildren(nodep); putqs(nodep, "end" + nodep->verilogKwd() + "\n"); } virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { - putfs(nodep, nodep->isFunction() ? "function":"task"); + putfs(nodep, nodep->isFunction() ? "function" : "task"); puts(" "); puts(nodep->prettyName()); puts(";\n"); - putqs(nodep, "begin\n"); // Only putfs the first time for each visitor; later for same node is putqs + // 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"); } @@ -75,7 +74,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { if (nodep->name() == "") { putbs("begin\n"); } else { - putbs("begin : "+nodep->name()+"\n"); + putbs("begin : " + nodep->name() + "\n"); } iterateChildren(nodep); puts("end\n"); @@ -92,23 +91,31 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } virtual void visit(AstAlways* nodep) VL_OVERRIDE { putfs(nodep, "always "); - if (m_sensesp) iterateAndNextNull(m_sensesp); // In active - else iterateAndNextNull(nodep->sensesp()); + if (m_sensesp) { + iterateAndNextNull(m_sensesp); + } // In active + else { + iterateAndNextNull(nodep->sensesp()); + } putbs(" begin\n"); iterateAndNextNull(nodep->bodysp()); putqs(nodep, "end\n"); } virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE { putfs(nodep, "/*verilator public_flat_rw "); - if (m_sensesp) iterateAndNextNull(m_sensesp); // In active - else iterateAndNextNull(nodep->sensesp()); + if (m_sensesp) { + iterateAndNextNull(m_sensesp); + } // In active + else { + iterateAndNextNull(nodep->sensesp()); + } putqs(nodep, " "); iterateAndNextNull(nodep->bodysp()); putqs(nodep, "*/\n"); } virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { iterateAndNextNull(nodep->lhsp()); - putfs(nodep, " "+nodep->verilogKwd()+" "); + putfs(nodep, " " + nodep->verilogKwd() + " "); iterateAndNextNull(nodep->rhsp()); if (!m_suppressSemi) puts(";\n"); } @@ -139,7 +146,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { virtual void visit(AstSenTree* nodep) VL_OVERRIDE { // AstSenItem is called for dumping in isolation by V3Order putfs(nodep, "@("); - for (AstNode* expp=nodep->sensesp(); expp; expp = expp->nextp()) { + for (AstNode* expp = nodep->sensesp(); expp; expp = expp->nextp()) { iterate(expp); if (expp->nextp()) putqs(expp->nextp(), " or "); } @@ -178,13 +185,15 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { virtual void visit(AstCaseItem* nodep) VL_OVERRIDE { if (nodep->condsp()) { iterateAndNextNull(nodep->condsp()); - } else putbs("default"); + } else { + putbs("default"); + } putfs(nodep, ": begin "); iterateAndNextNull(nodep->bodysp()); putqs(nodep, "end\n"); } virtual void visit(AstComment* nodep) VL_OVERRIDE { - puts(string("// ")+nodep->name()+"\n"); + puts(string("// ") + nodep->name() + "\n"); iterateChildren(nodep); } virtual void visit(AstContinue* nodep) VL_OVERRIDE { @@ -195,20 +204,23 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { virtual void visit(AstCoverInc*) VL_OVERRIDE {} // N/A virtual void visit(AstCoverToggle*) VL_OVERRIDE {} // N/A - void visitNodeDisplay(AstNode* nodep, AstNode* fileOrStrgp, - const string& text, AstNode* exprsp) { + void visitNodeDisplay(AstNode* nodep, AstNode* fileOrStrgp, const string& text, + AstNode* exprsp) { putfs(nodep, nodep->verilogKwd()); putbs(" ("); - if (fileOrStrgp) { iterateAndNextNull(fileOrStrgp); putbs(","); } + if (fileOrStrgp) { + iterateAndNextNull(fileOrStrgp); + putbs(","); + } putsQuoted(text); - for (AstNode* expp=exprsp; expp; expp = expp->nextp()) { + for (AstNode* expp = exprsp; expp; expp = expp->nextp()) { puts(","); iterateAndNextNull(expp); } puts(");\n"); } virtual void visit(AstDisable* nodep) VL_OVERRIDE { - putbs("disable "+nodep->name()+";\n"); + putbs("disable " + nodep->name() + ";\n"); } virtual void visit(AstDisplay* nodep) VL_OVERRIDE { visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp()); @@ -251,10 +263,10 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { puts(");\n"); } virtual void visit(AstJumpGo* nodep) VL_OVERRIDE { - putbs("disable "+cvtToHex(nodep->labelp())+";\n"); + putbs("disable " + cvtToHex(nodep->labelp()) + ";\n"); } virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE { - putbs("begin : "+cvtToHex(nodep)+"\n"); + putbs("begin : " + cvtToHex(nodep) + "\n"); if (nodep->stmtsp()) iterateAndNextNull(nodep->stmtsp()); puts("end\n"); } @@ -264,8 +276,14 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { if (nodep->filenamep()) iterateAndNextNull(nodep->filenamep()); putbs(","); if (nodep->memp()) iterateAndNextNull(nodep->memp()); - if (nodep->lsbp()) { putbs(","); iterateAndNextNull(nodep->lsbp()); } - if (nodep->msbp()) { putbs(","); iterateAndNextNull(nodep->msbp()); } + if (nodep->lsbp()) { + putbs(","); + iterateAndNextNull(nodep->lsbp()); + } + if (nodep->msbp()) { + putbs(","); + iterateAndNextNull(nodep->msbp()); + } puts(");\n"); } virtual void visit(AstSysFuncAsTask* nodep) VL_OVERRIDE { @@ -340,12 +358,8 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { iterateAndNextNull(nodep->lhsp()); puts(";\n"); } - virtual void visit(AstStop* nodep) VL_OVERRIDE { - putfs(nodep, "$stop;\n"); - } - virtual void visit(AstFinish* nodep) VL_OVERRIDE { - putfs(nodep, "$finish;\n"); - } + virtual void visit(AstStop* nodep) VL_OVERRIDE { putfs(nodep, "$stop;\n"); } + virtual void visit(AstFinish* nodep) VL_OVERRIDE { putfs(nodep, "$finish;\n"); } virtual void visit(AstNodeSimpleText* nodep) VL_OVERRIDE { if (nodep->tracking() || m_trackText) { puts(nodep->text()); @@ -360,8 +374,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { if (nodep->commas() && childp->nextp()) puts(", "); } } - virtual void visit(AstScopeName* nodep) VL_OVERRIDE { - } + virtual void visit(AstScopeName* nodep) VL_OVERRIDE {} virtual void visit(AstCStmt* nodep) VL_OVERRIDE { putfs(nodep, "$_CSTMT("); iterateAndNextNull(nodep->bodysp()); @@ -384,8 +397,8 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } // Operators - virtual void emitVerilogFormat(AstNode* nodep, const string& format, - AstNode* lhsp=NULL, AstNode* rhsp=NULL, AstNode* thsp=NULL) { + virtual void emitVerilogFormat(AstNode* nodep, const string& format, AstNode* lhsp = NULL, + AstNode* rhsp = NULL, AstNode* thsp = NULL) { // Look at emitVerilog() format for term/uni/dual/triops, // and write out appropriate text. // %f Potential fileline-if-change and line break @@ -397,16 +410,18 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { bool inPct = false; putbs(""); for (string::const_iterator pos = format.begin(); pos != format.end(); ++pos) { - if (pos[0]=='%') { + if (pos[0] == '%') { inPct = true; } else if (!inPct) { // Normal text - string s; s+=pos[0]; puts(s); + string s; + s += pos[0]; + puts(s); } else { // Format character inPct = false; switch (*pos) { - case '%': puts("%"); break; - case 'f': putfs(nodep, ""); break; - case 'k': putbs(""); break; + case '%': puts("%"); break; + case 'f': putfs(nodep, ""); break; + case 'k': putbs(""); break; case 'l': { UASSERT_OBJ(lhsp, nodep, "emitVerilog() references undef node"); iterateAndNextNull(lhsp); @@ -427,9 +442,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { iterateAndNextNull(nodep->dtypep()); break; } - default: - nodep->v3fatalSrc("Unknown emitVerilog format code: %"<v3fatalSrc("Unknown emitVerilog format code: %" << pos[0]); break; } } } @@ -445,7 +458,8 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp(), nodep->rhsp()); } virtual void visit(AstNodeTriop* nodep) VL_OVERRIDE { - emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp(), nodep->rhsp(), nodep->thsp()); + emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp(), nodep->rhsp(), + nodep->thsp()); } virtual void visit(AstAttrOf* nodep) VL_OVERRIDE { putfs(nodep, "$_ATTROF("); @@ -460,8 +474,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { putfs(nodep, "`{"); int comma = 0; const AstInitArray::KeyItemMap& mapr = nodep->map(); - for (AstInitArray::KeyItemMap::const_iterator it = mapr.begin(); - it != mapr.end(); ++it) { + for (AstInitArray::KeyItemMap::const_iterator it = mapr.begin(); it != mapr.end(); ++it) { if (comma++) putbs(", "); puts(cvtToStr(it->first)); puts(":"); @@ -472,23 +485,31 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } virtual void visit(AstNodeCond* nodep) VL_OVERRIDE { putbs("("); - iterateAndNextNull(nodep->condp()); putfs(nodep, " ? "); - iterateAndNextNull(nodep->expr1p()); putbs(" : "); - iterateAndNextNull(nodep->expr2p()); puts(")"); + iterateAndNextNull(nodep->condp()); + putfs(nodep, " ? "); + iterateAndNextNull(nodep->expr1p()); + putbs(" : "); + iterateAndNextNull(nodep->expr2p()); + puts(")"); } virtual void visit(AstRange* nodep) VL_OVERRIDE { puts("["); if (VN_IS(nodep->msbp(), Const) && VN_IS(nodep->lsbp(), Const)) { // Looks nicer if we print [1:0] rather than [32'sh1:32sh0] - puts(cvtToStr(VN_CAST(nodep->leftp(), Const)->toSInt())); puts(":"); - puts(cvtToStr(VN_CAST(nodep->rightp(), Const)->toSInt())); puts("]"); + puts(cvtToStr(VN_CAST(nodep->leftp(), Const)->toSInt())); + puts(":"); + puts(cvtToStr(VN_CAST(nodep->rightp(), Const)->toSInt())); + puts("]"); } else { - iterateAndNextNull(nodep->leftp()); puts(":"); - iterateAndNextNull(nodep->rightp()); puts("]"); + iterateAndNextNull(nodep->leftp()); + puts(":"); + iterateAndNextNull(nodep->rightp()); + puts("]"); } } virtual void visit(AstSel* nodep) VL_OVERRIDE { - iterateAndNextNull(nodep->fromp()); puts("["); + iterateAndNextNull(nodep->fromp()); + puts("["); if (VN_IS(nodep->lsbp(), Const)) { if (nodep->widthp()->isOne()) { if (VN_IS(nodep->lsbp(), Const)) { @@ -498,14 +519,15 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } } else { puts(cvtToStr(VN_CAST(nodep->lsbp(), Const)->toSInt() - + VN_CAST(nodep->widthp(), Const)->toSInt() - - 1)); + + VN_CAST(nodep->widthp(), Const)->toSInt() - 1)); puts(":"); puts(cvtToStr(VN_CAST(nodep->lsbp(), Const)->toSInt())); } } else { - iterateAndNextNull(nodep->lsbp()); putfs(nodep, "+:"); - iterateAndNextNull(nodep->widthp()); puts("]"); + iterateAndNextNull(nodep->lsbp()); + putfs(nodep, "+:"); + iterateAndNextNull(nodep->widthp()); + puts("]"); } puts("]"); } @@ -515,15 +537,23 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } virtual void visit(AstTypedef* nodep) VL_OVERRIDE { putfs(nodep, "typedef "); - iterateAndNextNull(nodep->dtypep()); puts(" "); + iterateAndNextNull(nodep->dtypep()); + puts(" "); puts(nodep->prettyName()); puts(";\n"); } virtual void visit(AstBasicDType* nodep) VL_OVERRIDE { if (nodep->isSigned()) putfs(nodep, "signed "); putfs(nodep, nodep->prettyName()); - if (nodep->rangep()) { puts(" "); iterateAndNextNull(nodep->rangep()); puts(" "); } - else if (nodep->isRanged()) { puts(" ["); puts(cvtToStr(nodep->msb())); puts(":0] "); } + if (nodep->rangep()) { + puts(" "); + iterateAndNextNull(nodep->rangep()); + puts(" "); + } else if (nodep->isRanged()) { + puts(" ["); + puts(cvtToStr(nodep->msb())); + puts(":0] "); + } } virtual void visit(AstConstDType* nodep) VL_OVERRIDE { putfs(nodep, "const "); @@ -534,7 +564,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { iterateAndNextNull(nodep->rangep()); } virtual void visit(AstNodeUOrStructDType* nodep) VL_OVERRIDE { - puts(nodep->verilogKwd()+" "); + puts(nodep->verilogKwd() + " "); if (nodep->packed()) puts("packed "); puts("\n"); iterateAndNextNull(nodep->membersp()); @@ -547,16 +577,18 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { puts("}"); } virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { - if (nodep->dotted()!="") { - putfs(nodep, nodep->dotted()); puts("."); puts(nodep->prettyName()); - } else { putfs(nodep, nodep->prettyName()); } + if (nodep->dotted() != "") { + putfs(nodep, nodep->dotted()); + puts("."); + puts(nodep->prettyName()); + } else { + putfs(nodep, nodep->prettyName()); + } puts("("); iterateAndNextNull(nodep->pinsp()); puts(")"); } - virtual void visit(AstArg* nodep) VL_OVERRIDE { - iterateAndNextNull(nodep->exprp()); - } + virtual void visit(AstArg* nodep) VL_OVERRIDE { iterateAndNextNull(nodep->exprp()); } // Terminals virtual void visit(AstVarRef* nodep) VL_OVERRIDE { if (nodep->varScopep()) { @@ -576,18 +608,19 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } // Just iterate - virtual void visit(AstTopScope* nodep) VL_OVERRIDE { - iterateChildren(nodep); - } - virtual void visit(AstScope* nodep) VL_OVERRIDE { - iterateChildren(nodep); - } + virtual void visit(AstTopScope* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstScope* nodep) VL_OVERRIDE { iterateChildren(nodep); } virtual void visit(AstVar* nodep) VL_OVERRIDE { putfs(nodep, nodep->verilogKwd()); puts(" "); - iterate(nodep->dtypep()); puts(" "); + iterate(nodep->dtypep()); + puts(" "); puts(nodep->prettyName()); - if (!m_suppressVarSemi) puts(";\n"); else puts("\n"); + if (!m_suppressVarSemi) { + puts(";\n"); + } else { + puts("\n"); + } } virtual void visit(AstActive* nodep) VL_OVERRIDE { m_sensesp = nodep->sensesp(); @@ -603,15 +636,15 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { virtual void visit(AstCell*) VL_OVERRIDE {} // Handled outside the Visit class // Default virtual void visit(AstNode* nodep) VL_OVERRIDE { - puts(string("\n???? // ")+nodep->prettyTypeName()+"\n"); + puts(string("\n???? // ") + nodep->prettyTypeName() + "\n"); iterateChildren(nodep); // Not v3fatalSrc so we keep processing - nodep->v3error("Internal: Unknown node type reached emitter: "<prettyTypeName()); + nodep->v3error("Internal: Unknown node type reached emitter: " << nodep->prettyTypeName()); } public: - bool m_suppressVarSemi; // Suppress emitting semicolon for AstVars - explicit EmitVBaseVisitor(AstSenTree* domainp=NULL) { + bool m_suppressVarSemi; // Suppress emitting semicolon for AstVars + explicit EmitVBaseVisitor(AstSenTree* domainp = NULL) { // Domain for printing one a ALWAYS under a ACTIVE m_suppressSemi = false; m_suppressVarSemi = false; @@ -625,17 +658,18 @@ public: class EmitVFileVisitor : public EmitVBaseVisitor { // MEMBERS - V3OutFile* m_ofp; + V3OutFile* m_ofp; // METHODS - V3OutFile* ofp() const { return m_ofp; } + V3OutFile* ofp() const { return m_ofp; } virtual void puts(const string& str) { ofp()->puts(str); } virtual void putbs(const string& str) { ofp()->putbs(str); } virtual void putfs(AstNode*, const string& str) { putbs(str); } virtual void putqs(AstNode*, const string& str) { putbs(str); } virtual void putsNoTracking(const string& str) { ofp()->putsNoTracking(str); } + public: - EmitVFileVisitor(AstNode* nodep, V3OutFile* ofp, bool trackText=false, - bool suppressVarSemi=false) { + EmitVFileVisitor(AstNode* nodep, V3OutFile* ofp, bool trackText = false, + bool suppressVarSemi = false) { m_ofp = ofp; m_trackText = trackText; m_suppressVarSemi = suppressVarSemi; @@ -649,13 +683,14 @@ public: class EmitVStreamVisitor : public EmitVBaseVisitor { // MEMBERS - std::ostream& m_os; + std::ostream& m_os; // METHODS - virtual void putsNoTracking(const string& str) { m_os<ascii()+":"; - m_os<ascii().length()+1)); - m_os<<" "; - m_os<ascii() + ":"; + m_os << V3OutFile::indentSpaces(m_flWidth - (m_prefixFl->ascii().length() + 1)); + m_os << " "; + m_os << m_prefix; } m_column++; - m_os<fileline(); // NETLIST's fileline instead of NULL to avoid NULL checks + m_prefixFl = v3Global.rootp() + ->fileline(); // NETLIST's fileline instead of NULL to avoid NULL checks } virtual ~EmitVPrefixedFormatter() { if (m_column) puts("\n"); @@ -707,7 +746,8 @@ public: class EmitVPrefixedVisitor : public EmitVBaseVisitor { // MEMBERS - EmitVPrefixedFormatter m_formatter; // Special verilog formatter (Way down the inheritance is another unused V3OutFormatter) + EmitVPrefixedFormatter m_formatter; // Special verilog formatter (Way down the + // inheritance is another unused V3OutFormatter) // METHODS virtual void putsNoTracking(const string& str) { m_formatter.putsNoTracking(str); } virtual void puts(const string& str) { m_formatter.puts(str); } @@ -728,7 +768,8 @@ class EmitVPrefixedVisitor : public EmitVBaseVisitor { public: EmitVPrefixedVisitor(AstNode* nodep, std::ostream& os, const string& prefix, int flWidth, AstSenTree* domainp, bool user3mark) - : EmitVBaseVisitor(domainp), m_formatter(os, prefix, flWidth) { + : EmitVBaseVisitor(domainp) + , m_formatter(os, prefix, flWidth) { if (user3mark) { AstUser3InUse::check(); } iterate(nodep); } @@ -739,13 +780,14 @@ public: // EmitV class functions void V3EmitV::emitv() { - UINFO(2,__FUNCTION__<<": "<modulesp(); modp; @@ -758,24 +800,22 @@ void V3EmitV::emitv() { } } -void V3EmitV::verilogForTree(AstNode* nodep, std::ostream& os) { - EmitVStreamVisitor(nodep, os); -} +void V3EmitV::verilogForTree(AstNode* nodep, std::ostream& os) { EmitVStreamVisitor(nodep, os); } -void V3EmitV::verilogPrefixedTree(AstNode* nodep, std::ostream& os, - const string& prefix, int flWidth, - AstSenTree* domainp, bool user3mark) { +void V3EmitV::verilogPrefixedTree(AstNode* nodep, std::ostream& os, const string& prefix, + int flWidth, AstSenTree* domainp, bool user3mark) { EmitVPrefixedVisitor(nodep, os, prefix, flWidth, domainp, user3mark); } void V3EmitV::emitvFiles() { - UINFO(2,__FUNCTION__<<": "<filesp(); filep; filep = VN_CAST(filep->nextp(), NodeFile)) { AstVFile* vfilep = VN_CAST(filep, VFile); if (vfilep && vfilep->tblockp()) { V3OutVFile of(vfilep->name()); - of.puts("// DESCR" "IPTION: Verilator generated Verilog\n"); + of.puts("// DESCR" + "IPTION: Verilator generated Verilog\n"); EmitVFileVisitor visitor(vfilep->tblockp(), &of, true, true); } } diff --git a/src/V3EmitXml.cpp b/src/V3EmitXml.cpp index 6ae7651fe..a748aecdc 100644 --- a/src/V3EmitXml.cpp +++ b/src/V3EmitXml.cpp @@ -33,18 +33,18 @@ class EmitXmlFileVisitor : public AstNVisitor { // NODE STATE - //Entire netlist: + // Entire netlist: // AstNode::user1 -> uint64_t, number to connect crossrefs // MEMBERS - V3OutFile* m_ofp; - uint64_t m_id; + V3OutFile* m_ofp; + uint64_t m_id; // METHODS VL_DEBUG_FUNC; // Declare debug() // Outfile methods - V3OutFile* ofp() const { return m_ofp; } + V3OutFile* ofp() const { return m_ofp; } virtual void puts(const string& str) { ofp()->puts(str); } virtual void putbs(const string& str) { ofp()->putbs(str); } virtual void putfs(AstNode*, const string& str) { putbs(str); } @@ -62,29 +62,42 @@ class EmitXmlFileVisitor : public AstNVisitor { // XML methods void outputId(AstNode* nodep) { if (!nodep->user1()) { nodep->user1(++m_id); } - puts("\""+cvtToStr(nodep->user1())+"\""); + puts("\"" + cvtToStr(nodep->user1()) + "\""); } void outputTag(AstNode* nodep, string tag) { - if (tag=="") tag = VString::downcase(nodep->typeName()); - puts("<"+tag+" "+nodep->fileline()->xml()); - puts(" "+nodep->fileline()->xmlDetailedLocation()); - if (VN_IS(nodep, NodeDType)) { puts(" id="); outputId(nodep); } - if (nodep->name()!="") { puts(" name="); putsQuoted(nodep->prettyName()); } - if (nodep->tag()!="") { puts(" tag="); putsQuoted(nodep->tag()); } + if (tag == "") tag = VString::downcase(nodep->typeName()); + puts("<" + tag + " " + nodep->fileline()->xml()); + puts(" " + nodep->fileline()->xmlDetailedLocation()); + if (VN_IS(nodep, NodeDType)) { + puts(" id="); + outputId(nodep); + } + if (nodep->name() != "") { + puts(" name="); + putsQuoted(nodep->prettyName()); + } + if (nodep->tag() != "") { + puts(" tag="); + putsQuoted(nodep->tag()); + } if (AstNodeDType* dtp = VN_CAST(nodep, NodeDType)) { if (dtp->subDTypep()) { - puts(" sub_dtype_id="); outputId(dtp->subDTypep()->skipRefp()); + puts(" sub_dtype_id="); + outputId(dtp->subDTypep()->skipRefp()); } } else { - if (nodep->dtypep()) { puts(" dtype_id="); outputId(nodep->dtypep()->skipRefp()); } + if (nodep->dtypep()) { + puts(" dtype_id="); + outputId(nodep->dtypep()->skipRefp()); + } } } void outputChildrenEnd(AstNode* nodep, string tag) { - if (tag=="") tag = VString::downcase(nodep->typeName()); + if (tag == "") tag = VString::downcase(nodep->typeName()); if (nodep->op1p() || nodep->op2p() || nodep->op3p() || nodep->op4p()) { puts(">\n"); iterateChildren(nodep); - puts("\n"); + puts("\n"); } else { puts("/>\n"); } @@ -97,8 +110,10 @@ class EmitXmlFileVisitor : public AstNVisitor { } virtual void visit(AstCell* nodep) VL_OVERRIDE { outputTag(nodep, "instance"); // IEEE: vpiInstance - puts(" defName="); putsQuoted(nodep->modName()); // IEEE vpiDefName - puts(" origName="); putsQuoted(nodep->origName()); + puts(" defName="); + putsQuoted(nodep->modName()); // IEEE vpiDefName + puts(" origName="); + putsQuoted(nodep->origName()); outputChildrenEnd(nodep, "instance"); } virtual void visit(AstNetlist* nodep) VL_OVERRIDE { @@ -108,8 +123,10 @@ class EmitXmlFileVisitor : public AstNVisitor { } virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { outputTag(nodep, ""); - puts(" origName="); putsQuoted(nodep->origName()); - if (nodep->level()==1 || nodep->level()==2) // ==2 because we don't add wrapper when in XML mode + puts(" origName="); + putsQuoted(nodep->origName()); + if (nodep->level() == 1 + || nodep->level() == 2) // ==2 because we don't add wrapper when in XML mode puts(" topModule=\"1\""); // IEEE vpiTopModule if (nodep->modPublic()) puts(" public=\"true\""); outputChildrenEnd(nodep, ""); @@ -120,13 +137,16 @@ class EmitXmlFileVisitor : public AstNVisitor { string vt = nodep->dtypep()->name(); outputTag(nodep, ""); if (nodep->isIO()) { - puts(" dir="); putsQuoted(kw); - puts(" vartype="); putsQuoted(!vt.empty() - ? vt : typ == AstVarType::PORT ? "port" : "unknown"); + puts(" dir="); + putsQuoted(kw); + puts(" vartype="); + putsQuoted(!vt.empty() ? vt : typ == AstVarType::PORT ? "port" : "unknown"); } else { - puts(" vartype="); putsQuoted(!vt.empty() ? vt : kw); + puts(" vartype="); + putsQuoted(!vt.empty() ? vt : kw); } - puts(" origName="); putsQuoted(nodep->origName()); + puts(" origName="); + putsQuoted(nodep->origName()); // Attributes if (nodep->attrClocker() == VVarAttrClocker::CLOCKER_YES) puts(" clocker=\"true\""); @@ -137,8 +157,10 @@ class EmitXmlFileVisitor : public AstNVisitor { if (nodep->isSigPublic()) puts(" public=\"true\""); if (nodep->isSigUserRdPublic()) puts(" public_flat_rd=\"true\""); if (nodep->isSigUserRWPublic()) puts(" public_flat_rw=\"true\""); - if (nodep->isGParam()) puts(" param=\"true\""); - else if (nodep->isParam()) puts(" localparam=\"true\""); + if (nodep->isGParam()) + puts(" param=\"true\""); + else if (nodep->isParam()) + puts(" localparam=\"true\""); if (nodep->attrScBv()) puts(" sc_bv=\"true\""); if (nodep->attrScClocked()) puts(" sc_clock=\"true\""); if (nodep->attrSFormat()) puts(" sformat=\"true\""); @@ -148,27 +170,29 @@ class EmitXmlFileVisitor : public AstNVisitor { // What we call a pin in verilator is a port in the IEEE spec. outputTag(nodep, "port"); // IEEE: vpiPort if (nodep->modVarp()->isIO()) { - puts(" direction=\""+nodep->modVarp()->direction().xmlKwd()+"\""); + puts(" direction=\"" + nodep->modVarp()->direction().xmlKwd() + "\""); } - puts(" portIndex=\""+cvtToStr(nodep->pinNum())+"\""); // IEEE: vpiPortIndex + puts(" portIndex=\"" + cvtToStr(nodep->pinNum()) + "\""); // IEEE: vpiPortIndex // Children includes vpiHighConn and vpiLowConn; we don't support port bits (yet?) outputChildrenEnd(nodep, "port"); } virtual void visit(AstSenItem* nodep) VL_OVERRIDE { outputTag(nodep, ""); - puts(" edgeType=\""+cvtToStr(nodep->edgeType().ascii())+"\""); // IEEE vpiTopModule + puts(" edgeType=\"" + cvtToStr(nodep->edgeType().ascii()) + "\""); // IEEE vpiTopModule outputChildrenEnd(nodep, ""); } virtual void visit(AstModportVarRef* nodep) VL_OVERRIDE { // Dump direction for Modport references string kw = nodep->direction().xmlKwd(); outputTag(nodep, ""); - puts(" direction="); putsQuoted(kw); + puts(" direction="); + putsQuoted(kw); outputChildrenEnd(nodep, ""); } virtual void visit(AstVarXRef* nodep) VL_OVERRIDE { outputTag(nodep, ""); - puts(" dotted="); putsQuoted(nodep->dotted()); + puts(" dotted="); + putsQuoted(nodep->dotted()); outputChildrenEnd(nodep, ""); } @@ -176,8 +200,8 @@ class EmitXmlFileVisitor : public AstNVisitor { virtual void visit(AstBasicDType* nodep) VL_OVERRIDE { outputTag(nodep, "basicdtype"); if (nodep->isRanged()) { - puts(" left=\""+cvtToStr(nodep->left())+"\""); - puts(" right=\""+cvtToStr(nodep->right())+"\""); + puts(" left=\"" + cvtToStr(nodep->left()) + "\""); + puts(" right=\"" + cvtToStr(nodep->right()) + "\""); } puts("/>\n"); } @@ -185,29 +209,36 @@ class EmitXmlFileVisitor : public AstNVisitor { string mpn; outputTag(nodep, ""); if (nodep->isModport()) mpn = nodep->modportName(); - puts(" modportname="); putsQuoted(mpn); + puts(" modportname="); + putsQuoted(mpn); outputChildrenEnd(nodep, ""); } virtual void visit(AstDisplay* nodep) VL_OVERRIDE { outputTag(nodep, ""); - puts(" displaytype="); putsQuoted(nodep->verilogKwd()); + puts(" displaytype="); + putsQuoted(nodep->verilogKwd()); outputChildrenEnd(nodep, ""); } virtual void visit(AstElabDisplay* nodep) VL_OVERRIDE { outputTag(nodep, ""); - puts(" displaytype="); putsQuoted(nodep->verilogKwd()); + puts(" displaytype="); + putsQuoted(nodep->verilogKwd()); outputChildrenEnd(nodep, ""); } virtual void visit(AstExtend* nodep) VL_OVERRIDE { outputTag(nodep, ""); - puts(" width="); putsQuoted(cvtToStr(nodep->width())); - puts(" widthminv="); putsQuoted(cvtToStr(nodep->lhsp()->widthMinV())); + puts(" width="); + putsQuoted(cvtToStr(nodep->width())); + puts(" widthminv="); + putsQuoted(cvtToStr(nodep->lhsp()->widthMinV())); outputChildrenEnd(nodep, ""); } virtual void visit(AstExtendS* nodep) VL_OVERRIDE { outputTag(nodep, ""); - puts(" width="); putsQuoted(cvtToStr(nodep->width())); - puts(" widthminv="); putsQuoted(cvtToStr(nodep->lhsp()->widthMinV())); + puts(" width="); + putsQuoted(cvtToStr(nodep->width())); + puts(" widthminv="); + putsQuoted(cvtToStr(nodep->lhsp()->widthMinV())); outputChildrenEnd(nodep, ""); } @@ -216,6 +247,7 @@ class EmitXmlFileVisitor : public AstNVisitor { outputTag(nodep, ""); outputChildrenEnd(nodep, ""); } + public: EmitXmlFileVisitor(AstNode* nodep, V3OutFile* ofp) { m_ofp = ofp; @@ -246,8 +278,7 @@ private: virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { // Only list modules and interfaces // Assumes modules and interfaces list is already sorted level wise - if (!nodep->dead() - && (VN_IS(nodep, Module) || VN_IS(nodep, Iface)) + if (!nodep->dead() && (VN_IS(nodep, Module) || VN_IS(nodep, Iface)) && m_modulesCovered.insert(nodep->fileline()->filename()).second) { m_nodeModules.push_front(nodep->fileline()); } @@ -260,18 +291,19 @@ private: public: // CONSTRUCTORS ModuleFilesXmlVisitor(AstNetlist* nodep, std::ostream& os) - : m_os(os), m_modulesCovered(), m_nodeModules() { + : m_os(os) + , m_modulesCovered() + , m_nodeModules() { // Operate on whole netlist nodep->accept(*this); // Xml output - m_os<<"\n"; - for (std::deque::iterator it = m_nodeModules.begin(); - it != m_nodeModules.end(); ++it) { - m_os<<"filenameLetters() - <<"\" filename=\""<<(*it)->filename() - <<"\" language=\""<<(*it)->language().ascii()<<"\"/>\n"; + m_os << "\n"; + for (std::deque::iterator it = m_nodeModules.begin(); it != m_nodeModules.end(); + ++it) { + m_os << "filenameLetters() << "\" filename=\"" + << (*it)->filename() << "\" language=\"" << (*it)->language().ascii() << "\"/>\n"; } - m_os<<"\n"; + m_os << "\n"; } virtual ~ModuleFilesXmlVisitor() {} }; @@ -292,42 +324,38 @@ private: // VISITORS virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { if (nodep->level() >= 0 - && nodep->level() <=2 ) { // ==2 because we don't add wrapper when in XML mode - m_os<<"\n"; - m_os<<"fileline()->xml() - <<" "<fileline()->xmlDetailedLocation() - <<" name=\""<name()<<"\"" - <<" submodname=\""<name()<<"\"" - <<" hier=\""<name()<<"\""; + && nodep->level() <= 2) { // ==2 because we don't add wrapper when in XML mode + m_os << "\n"; + m_os << "fileline()->xml() << " " + << nodep->fileline()->xmlDetailedLocation() << " name=\"" << nodep->name() << "\"" + << " submodname=\"" << nodep->name() << "\"" + << " hier=\"" << nodep->name() << "\""; m_hier = nodep->name() + "."; m_hasChildren = false; iterateChildren(nodep); if (m_hasChildren) { - m_os<<"\n"; + m_os << "\n"; } else { - m_os<<"/>\n"; + m_os << "/>\n"; } - m_os<<"\n"; + m_os << "\n"; } } virtual void visit(AstCell* nodep) VL_OVERRIDE { - if (nodep->modp()->dead()) { - return; - } - if (!m_hasChildren) m_os<<">\n"; - m_os<<"fileline()->xml() - <<" "<fileline()->xmlDetailedLocation() - <<" name=\""<name()<<"\"" - <<" submodname=\""<modName()<<"\"" - <<" hier=\""<name()<<"\""; + if (nodep->modp()->dead()) { return; } + if (!m_hasChildren) m_os << ">\n"; + m_os << "fileline()->xml() << " " + << nodep->fileline()->xmlDetailedLocation() << " name=\"" << nodep->name() << "\"" + << " submodname=\"" << nodep->modName() << "\"" + << " hier=\"" << m_hier + nodep->name() << "\""; std::string hier = m_hier; m_hier += nodep->name() + "."; m_hasChildren = false; iterateChildren(nodep->modp()); if (m_hasChildren) { - m_os<<"\n"; + m_os << "\n"; } else { - m_os<<"/>\n"; + m_os << "/>\n"; } m_hier = hier; m_hasChildren = true; @@ -338,7 +366,9 @@ private: public: // CONSTRUCTORS HierCellsXmlVisitor(AstNetlist* nodep, std::ostream& os) - : m_os(os), m_hier(""), m_hasChildren(false) { + : m_os(os) + , m_hier("") + , m_hasChildren(false) { // Operate on whole netlist nodep->accept(*this); } @@ -349,14 +379,15 @@ public: // EmitXml class functions void V3EmitXml::emitxml() { - UINFO(2,__FUNCTION__<<": "<\n"); + of.puts("\n"); of.puts("\n"); { std::stringstream sstr; @@ -365,10 +396,10 @@ void V3EmitXml::emitxml() { } { std::stringstream sstr; - ModuleFilesXmlVisitor moduleFilesVisitor (v3Global.rootp(), sstr); - HierCellsXmlVisitor cellsVisitor (v3Global.rootp(), sstr); + ModuleFilesXmlVisitor moduleFilesVisitor(v3Global.rootp(), sstr); + HierCellsXmlVisitor cellsVisitor(v3Global.rootp(), sstr); of.puts(sstr.str()); } - EmitXmlFileVisitor visitor (v3Global.rootp(), &of); + EmitXmlFileVisitor visitor(v3Global.rootp(), &of); of.puts("\n"); } diff --git a/src/V3Error.cpp b/src/V3Error.cpp index f5bed2005..e483c0699 100644 --- a/src/V3Error.cpp +++ b/src/V3Error.cpp @@ -14,12 +14,14 @@ // //************************************************************************* +// clang-format off #include "V3Error.h" #ifndef _V3ERROR_NO_GLOBAL_ # include "V3Ast.h" # include "V3Global.h" # include "V3Stats.h" #endif +// clang-format on #include @@ -43,7 +45,7 @@ V3Error::MessagesSet V3Error::s_messages; V3Error::ErrorExitCb V3Error::s_errorExitCb = NULL; struct v3errorIniter { - v3errorIniter() { V3Error::init(); } + v3errorIniter() { V3Error::init(); } }; v3errorIniter v3errorInit; @@ -52,10 +54,11 @@ v3errorIniter v3errorInit; V3ErrorCode::V3ErrorCode(const char* msgp) { // Return error encoding for given string, or ERROR, which is a bad code - for (int codei=V3ErrorCode::EC_MIN; codei20) numsp = 20; - out<<(spaces + numsp); + size_t numsp = out.str().length(); + if (numsp > 20) numsp = 20; + out << (spaces + numsp); return out.str(); } void V3Error::incErrors() { s_errCount++; if (errorCount() == errorLimit()) { // Not >= as would otherwise recurse - v3fatalExit("Exiting due to too many errors encountered; --error-limit=" + v3fatalExit("Exiting due to too many errors encountered; --error-limit=" // << errorCount() << endl); } } @@ -96,8 +100,8 @@ void V3Error::incErrors() { void V3Error::abortIfWarnings() { bool exwarn = warnFatal() && warnCount(); if (errorCount() && exwarn) { - v3fatalExit("Exiting due to " << std::dec << errorCount() << " error(s), " - << warnCount() << " warning(s)\n"); + v3fatalExit("Exiting due to " << std::dec << errorCount() << " error(s), " // + << warnCount() << " warning(s)\n"); } else if (errorCount()) { v3fatalExit("Exiting due to " << std::dec << errorCount() << " error(s)\n"); } else if (exwarn) { @@ -106,30 +110,49 @@ void V3Error::abortIfWarnings() { } bool V3Error::isError(V3ErrorCode code, bool supp) { - if (supp) return false; - else if (code == V3ErrorCode::USERINFO) return false; - else if (code == V3ErrorCode::EC_INFO) return false; - else if (code == V3ErrorCode::EC_FATAL) return true; - else if (code == V3ErrorCode::EC_FATALEXIT) return true; - else if (code == V3ErrorCode::EC_FATALSRC) return true; - else if (code == V3ErrorCode::EC_ERROR) return true; - else if (code < V3ErrorCode::EC_FIRST_WARN - || s_pretendError[code]) return true; - else return false; + if (supp) { + return false; + } else if (code == V3ErrorCode::USERINFO) { + return false; + } else if (code == V3ErrorCode::EC_INFO) { + return false; + } else if (code == V3ErrorCode::EC_FATAL) { + return true; + } else if (code == V3ErrorCode::EC_FATALEXIT) { + return true; + } else if (code == V3ErrorCode::EC_FATALSRC) { + return true; + } else if (code == V3ErrorCode::EC_ERROR) { + return true; + } else if (code < V3ErrorCode::EC_FIRST_WARN || s_pretendError[code]) { + return true; + } else { + return false; + } } string V3Error::msgPrefix() { V3ErrorCode code = s_errorCode; bool supp = s_errorSuppressed; - if (supp) return "-arning-suppressed: "; - else if (code == V3ErrorCode::USERINFO) return "-Info: "; - else if (code == V3ErrorCode::EC_INFO) return "-Info: "; - else if (code == V3ErrorCode::EC_FATAL) return "%Error: "; - else if (code == V3ErrorCode::EC_FATALEXIT) return "%Error: "; - else if (code == V3ErrorCode::EC_FATALSRC) return "%Error: Internal Error: "; - else if (code == V3ErrorCode::EC_ERROR) return "%Error: "; - else if (isError(code, supp)) return "%Error-"+string(code.ascii())+": "; - else return "%Warning-"+string(code.ascii())+": "; + if (supp) { + return "-arning-suppressed: "; + } else if (code == V3ErrorCode::USERINFO) { + return "-Info: "; + } else if (code == V3ErrorCode::EC_INFO) { + return "-Info: "; + } else if (code == V3ErrorCode::EC_FATAL) { + return "%Error: "; + } else if (code == V3ErrorCode::EC_FATALEXIT) { + return "%Error: "; + } else if (code == V3ErrorCode::EC_FATALSRC) { + return "%Error: Internal Error: "; + } else if (code == V3ErrorCode::EC_ERROR) { + return "%Error: "; + } else if (isError(code, supp)) { + return "%Error-" + string(code.ascii()) + ": "; + } else { + return "%Warning-" + string(code.ascii()) + ": "; + } } //====================================================================== @@ -137,7 +160,7 @@ string V3Error::msgPrefix() { void V3Error::vlAbort() { if (V3Error::debugDefault()) { - std::cerr<=V3ErrorCode::EC_MIN) { + if (s_errorCode >= V3ErrorCode::EC_MIN) { #ifndef _V3ERROR_NO_GLOBAL_ - V3Stats::addStatSum(string("Warnings, Suppressed ")+s_errorCode.ascii(), 1); + V3Stats::addStatSum(string("Warnings, Suppressed ") + s_errorCode.ascii(), 1); #endif s_errorSuppressed = true; } } -string V3Error::warnMore() { - return string(msgPrefix().size(), ' '); -} +string V3Error::warnMore() { return string(msgPrefix().size(), ' '); } void V3Error::v3errorEnd(std::ostringstream& sstr, const string& locationStr) { #if defined(__COVERITY__) || defined(__cppcheck__) - if (s_errorCode==V3ErrorCode::EC_FATAL) __coverity_panic__(x); + if (s_errorCode == V3ErrorCode::EC_FATAL) __coverity_panic__(x); #endif // Skip suppressed messages if (s_errorSuppressed // On debug, show only non default-off warning to prevent pages of warnings - && (!debug() || s_errorCode.defaultsOff())) return; - string msg = msgPrefix()+sstr.str(); + && (!debug() || s_errorCode.defaultsOff())) + return; + string msg = msgPrefix() + sstr.str(); if (s_errorSuppressed) { // If suppressed print only first line to reduce verbosity string::size_type pos; if ((pos = msg.find('\n')) != string::npos) { - msg.erase(pos, msg.length()-pos); + msg.erase(pos, msg.length() - pos); msg += "..."; } } @@ -180,15 +202,13 @@ void V3Error::v3errorEnd(std::ostringstream& sstr, const string& locationStr) { { msg += '\n'; // Trailing newlines generally not put on messages so add string::size_type pos; - while ((pos = msg.find("\n\n")) != string::npos) { - msg.erase(pos+1, 1); - } + while ((pos = msg.find("\n\n")) != string::npos) msg.erase(pos + 1, 1); } // Suppress duplicate messages if (s_messages.find(msg) != s_messages.end()) return; s_messages.insert(msg); if (!locationStr.empty()) { - string locationMsg = warnMore()+locationStr+"\n"; + string locationMsg = warnMore() + locationStr + "\n"; size_t pos = msg.find("\n"); msg.insert(pos + 1, locationMsg); } @@ -199,44 +219,49 @@ void V3Error::v3errorEnd(std::ostringstream& sstr, const string& locationStr) { #else true #endif - ) { + ) { std::cerr << msg; } - if (!s_errorSuppressed && !(s_errorCode==V3ErrorCode::EC_INFO - || s_errorCode==V3ErrorCode::USERINFO)) { - if (!s_describedEachWarn[s_errorCode] - && !s_pretendError[s_errorCode]) { + if (!s_errorSuppressed + && !(s_errorCode == V3ErrorCode::EC_INFO || s_errorCode == V3ErrorCode::USERINFO)) { + if (!s_describedEachWarn[s_errorCode] && !s_pretendError[s_errorCode]) { s_describedEachWarn[s_errorCode] = true; - if (s_errorCode>=V3ErrorCode::EC_FIRST_WARN && !s_describedWarnings) { - std::cerr<= V3ErrorCode::EC_FIRST_WARN && !s_describedWarnings) { + std::cerr << warnMore() << "... Use \"/* verilator lint_off " + << s_errorCode.ascii() + << " */\" and lint_on around source to disable this message." << endl; s_describedWarnings = true; } if (s_errorCode.dangerous()) { - std::cerr<(_e)) {} + explicit inline V3ErrorCode(int _e) + : m_e(static_cast(_e)) {} operator en() const { return m_e; } const char* ascii() const { + // clang-format off const char* names[] = { // Leading spaces indicate it can't be disabled. " MIN", " INFO", " FATAL", " FATALEXIT", " FATALSRC", " ERROR", @@ -159,50 +165,37 @@ public: "VARHIDDEN", "WIDTH", "WIDTHCONCAT", " MAX" }; + // clang-format on return names[m_e]; } // Warnings that default to off - bool defaultsOff() const { return ( m_e==IMPERFECTSCH || styleError()); } + bool defaultsOff() const { return (m_e == IMPERFECTSCH || styleError()); } // Warnings that warn about nasty side effects - bool dangerous() const { return ( m_e==COMBDLY ); } + bool dangerous() const { return (m_e == COMBDLY); } // Warnings we'll present to the user as errors // Later -Werror- options may make more of these. - bool pretendError() const { return ( m_e==ASSIGNIN || m_e==BLKANDNBLK - || m_e==BLKLOOPINIT - || m_e==CONTASSREG - || m_e==IMPURE - || m_e==PROCASSWIRE); } + bool pretendError() const { + return (m_e == ASSIGNIN || m_e == BLKANDNBLK || m_e == BLKLOOPINIT || m_e == CONTASSREG + || m_e == IMPURE || m_e == PROCASSWIRE); + } // Warnings to mention manual - bool mentionManual() const { return ( m_e==EC_FATALSRC || m_e==SYMRSVDWORD - || pretendError() ); } - + bool mentionManual() const { + return (m_e == EC_FATALSRC || m_e == SYMRSVDWORD || pretendError()); + } // Warnings that are lint only - bool lintError() const { return ( m_e==ALWCOMBORDER - || m_e==BSSPACE - || m_e==CASEINCOMPLETE || m_e==CASEOVERLAP - || m_e==CASEWITHX || m_e==CASEX - || m_e==CMPCONST - || m_e==COLONPLUS - || m_e==ENDLABEL - || m_e==IMPLICIT - || m_e==LITENDIAN - || m_e==PINMISSING - || m_e==REALCVT - || m_e==UNSIGNED - || m_e==WIDTH); } + bool lintError() const { + return (m_e == ALWCOMBORDER || m_e == BSSPACE || m_e == CASEINCOMPLETE + || m_e == CASEOVERLAP || m_e == CASEWITHX || m_e == CASEX || m_e == CMPCONST + || m_e == COLONPLUS || m_e == ENDLABEL || m_e == IMPLICIT || m_e == LITENDIAN + || m_e == PINMISSING || m_e == REALCVT || m_e == UNSIGNED || m_e == WIDTH); + } // Warnings that are style only - bool styleError() const { return ( m_e==ASSIGNDLY // More than style, but for backward compatibility - || m_e==BLKSEQ - || m_e==DEFPARAM - || m_e==DECLFILENAME - || m_e==IMPORTSTAR - || m_e==INCABSPATH - || m_e==PINCONNECTEMPTY - || m_e==PINNOCONNECT - || m_e==SYNCASYNCNET - || m_e==UNDRIVEN - || m_e==UNUSED - || m_e==VARHIDDEN ); } + bool styleError() const { + return (m_e == ASSIGNDLY // More than style, but for backward compatibility + || m_e == BLKSEQ || m_e == DEFPARAM || m_e == DECLFILENAME || m_e == IMPORTSTAR + || m_e == INCABSPATH || m_e == PINCONNECTEMPTY || m_e == PINNOCONNECT + || m_e == SYNCASYNCNET || m_e == UNDRIVEN || m_e == UNUSED || m_e == VARHIDDEN); + } }; inline bool operator==(const V3ErrorCode& lhs, const V3ErrorCode& rhs) { return lhs.m_e == rhs.m_e; @@ -221,28 +214,32 @@ class V3Error { typedef std::set MessagesSet; typedef void (*ErrorExitCb)(void); - private: - static bool s_describedWarnings; // Told user how to disable warns - static bool s_describedEachWarn[V3ErrorCode::_ENUM_MAX]; // Told user specifics about this warning - static bool s_pretendError[V3ErrorCode::_ENUM_MAX]; // Pretend this warning is an error - static int s_debugDefault; // Option: --debugi Default debugging level - static int s_errorLimit; // Option: --error-limit Number of errors before exit - static bool s_warnFatal; // Option: --warnFatal Warnings are fatal - static int s_errCount; // Error count - static int s_warnCount; // Warning count - static int s_tellManual; // Tell user to see manual, 0=not yet, 1=doit, 2=disable - static std::ostringstream s_errorStr; // Error string being formed - static V3ErrorCode s_errorCode; // Error string being formed will abort - static bool s_errorContexted; // Error being formed got context - static bool s_errorSuppressed; // Error being formed should be suppressed - static MessagesSet s_messages; // What errors we've outputted - static ErrorExitCb s_errorExitCb; // Callback when error occurs for dumping +private: + static bool s_describedWarnings; // Told user how to disable warns + static bool + s_describedEachWarn[V3ErrorCode::_ENUM_MAX]; // Told user specifics about this warning + static bool s_pretendError[V3ErrorCode::_ENUM_MAX]; // Pretend this warning is an error + static int s_debugDefault; // Option: --debugi Default debugging level + static int s_errorLimit; // Option: --error-limit Number of errors before exit + static bool s_warnFatal; // Option: --warnFatal Warnings are fatal + static int s_errCount; // Error count + static int s_warnCount; // Warning count + static int s_tellManual; // Tell user to see manual, 0=not yet, 1=doit, 2=disable + static std::ostringstream s_errorStr; // Error string being formed + static V3ErrorCode s_errorCode; // Error string being formed will abort + static bool s_errorContexted; // Error being formed got context + static bool s_errorSuppressed; // Error being formed should be suppressed + static MessagesSet s_messages; // What errors we've outputted + static ErrorExitCb s_errorExitCb; // Callback when error occurs for dumping - enum MaxErrors { MAX_ERRORS = 50 }; // Fatal after this may errors + enum MaxErrors { MAX_ERRORS = 50 }; // Fatal after this may errors - V3Error() { std::cerr<<("Static class"); abort(); } + V3Error() { + std::cerr << ("Static class"); + abort(); + } - public: +public: // CONSTRUCTORS // ACCESSORS static void debugDefault(int level) { s_debugDefault = level; } @@ -254,14 +251,16 @@ class V3Error { static string msgPrefix(); // returns %Error/%Warn static int errorCount() { return s_errCount; } static int warnCount() { return s_warnCount; } - static int errorOrWarnCount() { return errorCount()+warnCount(); } + static int errorOrWarnCount() { return errorCount() + warnCount(); } static bool errorContexted() { return s_errorContexted; } static void errorContexted(bool flag) { s_errorContexted = flag; } // METHODS static void incErrors(); static void incWarnings() { s_warnCount++; } static void init(); - static void abortIfErrors() { if (errorCount()) abortIfWarnings(); } + static void abortIfErrors() { + if (errorCount()) abortIfWarnings(); + } static void abortIfWarnings(); static void suppressThisWarning(); // Suppress next %Warn if user has it off static void pretendError(V3ErrorCode code, bool flag) { s_pretendError[code] = flag; } @@ -273,77 +272,109 @@ class V3Error { // When printing an error/warning, print prefix for multiline message static string warnMore(); /// When building an error, don't show context info - static string warnContextNone() { V3Error::errorContexted(true); return ""; } + static string warnContextNone() { + V3Error::errorContexted(true); + return ""; + } // Internals for v3error()/v3fatal() macros only // Error end takes the string stream to output, be careful to seek() as needed static void v3errorPrep(V3ErrorCode code) { - s_errorStr.str(""); s_errorCode = code; - s_errorContexted = false; s_errorSuppressed = false; } + s_errorStr.str(""); + s_errorCode = code; + s_errorContexted = false; + s_errorSuppressed = false; + } static std::ostringstream& v3errorStr() { return s_errorStr; } static void vlAbort(); - static void v3errorEnd(std::ostringstream& sstr, const string& locationStr = ""); // static, but often overridden in classes. + // static, but often overridden in classes. + static void v3errorEnd(std::ostringstream& sstr, const string& locationStr = ""); }; // Global versions, so that if the class doesn't define a operator, we get the functions anyways. inline int debug() { return V3Error::debugDefault(); } inline void v3errorEnd(std::ostringstream& sstr) { V3Error::v3errorEnd(sstr); } inline void v3errorEndFatal(std::ostringstream& sstr) { - V3Error::v3errorEnd(sstr); assert(0); VL_UNREACHABLE } + V3Error::v3errorEnd(sstr); + assert(0); + VL_UNREACHABLE +} // Theses allow errors using << operators: v3error("foo"<<"bar"); // Careful, you can't put () around msg, as you would in most macro definitions // Note the commas are the comma operator, not separating arguments. These are needed to ensure // evaluation order as otherwise we couldn't ensure v3errorPrep is called first. -#define v3warnCode(code,msg) \ - v3errorEnd((V3Error::v3errorPrep(code), (V3Error::v3errorStr()<= (level))) { \ - cout << "- " << V3Error::lineStr(__FILE__, __LINE__) << stmsg; } } + { \ + if (VL_UNCOVERABLE(debug() >= (level))) { \ + cout << "- " << V3Error::lineStr(__FILE__, __LINE__) << stmsg; \ + } \ + } #define UINFONL(level, stmsg) \ - { if (VL_UNCOVERABLE(debug() >= (level))) { cout << stmsg; } } + { \ + if (VL_UNCOVERABLE(debug() >= (level))) { cout << stmsg; } \ + } #ifdef VL_DEBUG -# define UDEBUGONLY(stmts) \ +#define UDEBUGONLY(stmts) \ { stmts } #else -# define UDEBUGONLY(stmts) \ - { if (false) { stmts } } +#define UDEBUGONLY(stmts) \ + { \ + if (false) { stmts } \ + } #endif // Assertion without object, generally UOBJASSERT preferred -#define UASSERT(condition,stmsg) \ - do { if (VL_UNCOVERABLE(!(condition))) { v3fatalSrc(stmsg); }} while (false) +#define UASSERT(condition, stmsg) \ + do { \ + if (VL_UNCOVERABLE(!(condition))) { v3fatalSrc(stmsg); } \ + } while (false) // Assertion with object -#define UASSERT_OBJ(condition,obj,stmsg) \ - do { if (VL_UNCOVERABLE(!(condition))) { (obj)->v3fatalSrc(stmsg); }} while (false) +#define UASSERT_OBJ(condition, obj, stmsg) \ + do { \ + if (VL_UNCOVERABLE(!(condition))) { (obj)->v3fatalSrc(stmsg); } \ + } while (false) // For use in V3Ast static functions only -#define UASSERT_STATIC(condition,stmsg) \ - do { if (VL_UNCOVERABLE(!(condition))) { \ - std::cerr<<"Internal Error: "<<__FILE__<<":"< {for each_word{ ASSIGN(WORDSEL(wide,#),WORDSEL(CONST,#))}} if (rhsp->num().isFourState()) { rhsp->v3error("Unsupported: 4-state numbers in this context"); } - for (int w=0; wwidthWords(); w++) { - addWordAssign(nodep, w, new AstConst(nodep->fileline(), - AstConst::SizedEData(), - rhsp->num().edataWord(w))); + for (int w = 0; w < nodep->widthWords(); w++) { + addWordAssign( + nodep, w, + new AstConst(nodep->fileline(), AstConst::SizedEData(), rhsp->num().edataWord(w))); } return true; } //-------- Uniops bool expandWide(AstNodeAssign* nodep, AstVarRef* rhsp) { - UINFO(8," Wordize ASSIGN(VARREF) "<widthWords(); w++) { + UINFO(8, " Wordize ASSIGN(VARREF) " << nodep << endl); + for (int w = 0; w < nodep->widthWords(); w++) { addWordAssign(nodep, w, newAstWordSelClone(rhsp, w)); } return true; } bool expandWide(AstNodeAssign* nodep, AstArraySel* rhsp) { - UINFO(8," Wordize ASSIGN(ARRAYSEL) "<dtypep()->skipRefp(), UnpackArrayDType), nodep, "ArraySel with unpacked arrays should have been removed in V3Slice"); - for (int w=0; wwidthWords(); w++) { + for (int w = 0; w < nodep->widthWords(); w++) { addWordAssign(nodep, w, newAstWordSelClone(rhsp, w)); } return true; } bool expandWide(AstNodeAssign* nodep, AstNot* rhsp) { - UINFO(8," Wordize ASSIGN(NOT) "< {for each_word{ ASSIGN(WORDSEL(wide,#),NOT(WORDSEL(lhs,#))) }} - for (int w=0; wwidthWords(); w++) { - addWordAssign(nodep, w, new AstNot(rhsp->fileline(), - newAstWordSelClone(rhsp->lhsp(), w))); + for (int w = 0; w < nodep->widthWords(); w++) { + addWordAssign(nodep, w, + new AstNot(rhsp->fileline(), newAstWordSelClone(rhsp->lhsp(), w))); } return true; } //-------- Biops bool expandWide(AstNodeAssign* nodep, AstAnd* rhsp) { - UINFO(8," Wordize ASSIGN(AND) "<widthWords(); w++) { - addWordAssign(nodep, w, new AstAnd(nodep->fileline(), - newAstWordSelClone(rhsp->lhsp(), w), - newAstWordSelClone(rhsp->rhsp(), w))); + UINFO(8, " Wordize ASSIGN(AND) " << nodep << endl); + for (int w = 0; w < nodep->widthWords(); w++) { + addWordAssign(nodep, w, + new AstAnd(nodep->fileline(), newAstWordSelClone(rhsp->lhsp(), w), + newAstWordSelClone(rhsp->rhsp(), w))); } return true; } bool expandWide(AstNodeAssign* nodep, AstOr* rhsp) { - UINFO(8," Wordize ASSIGN(OR) "<widthWords(); w++) { - addWordAssign(nodep, w, new AstOr(nodep->fileline(), - newAstWordSelClone(rhsp->lhsp(), w), - newAstWordSelClone(rhsp->rhsp(), w))); + UINFO(8, " Wordize ASSIGN(OR) " << nodep << endl); + for (int w = 0; w < nodep->widthWords(); w++) { + addWordAssign(nodep, w, + new AstOr(nodep->fileline(), newAstWordSelClone(rhsp->lhsp(), w), + newAstWordSelClone(rhsp->rhsp(), w))); } return true; } bool expandWide(AstNodeAssign* nodep, AstXor* rhsp) { - UINFO(8," Wordize ASSIGN(XOR) "<widthWords(); w++) { - addWordAssign(nodep, w, new AstXor(nodep->fileline(), - newAstWordSelClone(rhsp->lhsp(), w), - newAstWordSelClone(rhsp->rhsp(), w))); + UINFO(8, " Wordize ASSIGN(XOR) " << nodep << endl); + for (int w = 0; w < nodep->widthWords(); w++) { + addWordAssign(nodep, w, + new AstXor(nodep->fileline(), newAstWordSelClone(rhsp->lhsp(), w), + newAstWordSelClone(rhsp->rhsp(), w))); } return true; } bool expandWide(AstNodeAssign* nodep, AstXnor* rhsp) { - UINFO(8," Wordize ASSIGN(XNOR) "<widthWords(); w++) { - addWordAssign(nodep, w, new AstXnor(nodep->fileline(), - newAstWordSelClone(rhsp->lhsp(), w), - newAstWordSelClone(rhsp->rhsp(), w))); + UINFO(8, " Wordize ASSIGN(XNOR) " << nodep << endl); + for (int w = 0; w < nodep->widthWords(); w++) { + addWordAssign(nodep, w, + new AstXnor(nodep->fileline(), newAstWordSelClone(rhsp->lhsp(), w), + newAstWordSelClone(rhsp->rhsp(), w))); } return true; } //-------- Triops bool expandWide(AstNodeAssign* nodep, AstNodeCond* rhsp) { - UINFO(8," Wordize ASSIGN(COND) "<widthWords(); w++) { - addWordAssign(nodep, w, new AstCond(nodep->fileline(), - rhsp->condp()->cloneTree(true), - newAstWordSelClone(rhsp->expr1p(), w), - newAstWordSelClone(rhsp->expr2p(), w))); + UINFO(8, " Wordize ASSIGN(COND) " << nodep << endl); + for (int w = 0; w < nodep->widthWords(); w++) { + addWordAssign(nodep, w, + new AstCond(nodep->fileline(), rhsp->condp()->cloneTree(true), + newAstWordSelClone(rhsp->expr1p(), w), + newAstWordSelClone(rhsp->expr2p(), w))); } return true; } @@ -316,7 +298,7 @@ private: } else if (lhsp->isWide()) { nodep->v3fatalSrc("extending larger thing into smaller?"); } else { - UINFO(8," EXTEND(q<-l) "<fileline(), lhsp, nodep); } } else { // Long @@ -328,12 +310,12 @@ private: } } bool expandWide(AstNodeAssign* nodep, AstExtend* rhsp) { - UINFO(8," Wordize ASSIGN(EXTEND) "<lhsp()->widthWords(); w++) { + for (w = 0; w < rhsp->lhsp()->widthWords(); w++) { addWordAssign(nodep, w, newAstWordSelClone(rhsp->lhsp(), w)); } - for (; wwidthWords(); w++) { + for (; w < nodep->widthWords(); w++) { addWordAssign(nodep, w, new AstConst(rhsp->fileline(), AstConst::SizedEData(), 0)); } return true; @@ -345,33 +327,29 @@ private: // Remember, Sel's may have non-integer rhs, so need to optimize for that! UASSERT_OBJ(nodep->widthMin() == nodep->widthConst(), nodep, "Width mismatch"); if (VN_IS(nodep->backp(), NodeAssign) - && nodep==VN_CAST(nodep->backp(), NodeAssign)->lhsp()) { + && nodep == VN_CAST(nodep->backp(), NodeAssign)->lhsp()) { // Sel is an LHS assignment select } else if (nodep->isWide()) { // See under ASSIGN(WIDE) - } - else if (nodep->fromp()->isWide()) { - UINFO(8," SEL(wide) "<fromp()->isWide()) { + UINFO(8, " SEL(wide) " << nodep << endl); // Selection amounts // Check for constant shifts & save some constification work later. // Grab lowest bit(s) - AstNode* lowwordp = new AstWordSel(nodep->fromp()->fileline(), - nodep->fromp()->cloneTree(true), - newSelBitWord(nodep->lsbp(), 0)); + AstNode* lowwordp + = new AstWordSel(nodep->fromp()->fileline(), nodep->fromp()->cloneTree(true), + newSelBitWord(nodep->lsbp(), 0)); if (nodep->isQuad() && !lowwordp->isQuad()) { lowwordp = new AstCCast(nodep->fileline(), lowwordp, nodep); } - AstNode* lowp = new AstShiftR(nodep->fileline(), - lowwordp, - newSelBitBit(nodep->lsbp()), + AstNode* lowp = new AstShiftR(nodep->fileline(), lowwordp, newSelBitBit(nodep->lsbp()), nodep->width()); // If > 1 bit, we might be crossing the word boundary AstNode* midp = NULL; - V3Number zero (nodep, longOrQuadWidth(nodep)); + V3Number zero(nodep, longOrQuadWidth(nodep)); if (nodep->widthConst() > 1) { AstNode* midwordp = // SEL(from,[1+wordnum]) - new AstWordSel(nodep->fromp()->fileline(), - nodep->fromp()->cloneTree(true), + new AstWordSel(nodep->fromp()->fileline(), nodep->fromp()->cloneTree(true), newSelBitWord(nodep->lsbp(), 1)); if (nodep->isQuad() && !midwordp->isQuad()) { midwordp = new AstCCast(nodep->fileline(), midwordp, nodep); @@ -380,23 +358,19 @@ private: // get shifted << by 32 bits // else we need to form the lower word, so we << by 31 or less // nbitsfromlow <= (lsb==0) ? 64-bitbit(lsb) : 32-bitbit(lsb) - AstNode* midshiftp = new AstSub(nodep->lsbp()->fileline(), - new AstConst(nodep->lsbp()->fileline(), - VL_EDATASIZE), - newSelBitBit(nodep->lsbp())); + AstNode* midshiftp + = new AstSub(nodep->lsbp()->fileline(), + new AstConst(nodep->lsbp()->fileline(), VL_EDATASIZE), + newSelBitBit(nodep->lsbp())); if (nodep->isQuad()) { - midshiftp = - new AstCond(nodep->fileline(), - new AstEq(nodep->fileline(), - new AstConst(nodep->fileline(), 0), - newSelBitBit(nodep->lsbp())), - new AstConst(nodep->lsbp()->fileline(), VL_EDATASIZE), - midshiftp); + midshiftp = new AstCond( + nodep->fileline(), + new AstEq(nodep->fileline(), new AstConst(nodep->fileline(), 0), + newSelBitBit(nodep->lsbp())), + new AstConst(nodep->lsbp()->fileline(), VL_EDATASIZE), midshiftp); } - AstNode* midmayp = new AstShiftL(nodep->fileline(), - midwordp, - midshiftp, - nodep->width()); + AstNode* midmayp + = new AstShiftL(nodep->fileline(), midwordp, midshiftp, nodep->width()); if (nodep->isQuad()) { midp = midmayp; // Always grab from two words } else { @@ -404,35 +378,30 @@ private: new AstEq(nodep->fileline(), new AstConst(nodep->fileline(), 0), newSelBitBit(nodep->lsbp())), - new AstConst(nodep->fileline(), zero), - midmayp); + new AstConst(nodep->fileline(), zero), midmayp); } } // If > 32 bits, we might be crossing the second word boundary AstNode* hip = NULL; if (nodep->widthConst() > VL_EDATASIZE) { AstNode* hiwordp = // SEL(from,[2+wordnum]) - new AstWordSel(nodep->fromp()->fileline(), - nodep->fromp()->cloneTree(true), + new AstWordSel(nodep->fromp()->fileline(), nodep->fromp()->cloneTree(true), newSelBitWord(nodep->lsbp(), 2)); if (nodep->isQuad() && !hiwordp->isQuad()) { hiwordp = new AstCCast(nodep->fileline(), hiwordp, nodep); } - AstNode* himayp = - new AstShiftL(nodep->fileline(), - hiwordp, - // nbitsfromlow_and_mid <= 64-bitbit(lsb) - new AstSub(nodep->lsbp()->fileline(), - new AstConst(nodep->lsbp()->fileline(), 64), - newSelBitBit(nodep->lsbp())), - nodep->width()); + AstNode* himayp + = new AstShiftL(nodep->fileline(), hiwordp, + // nbitsfromlow_and_mid <= 64-bitbit(lsb) + new AstSub(nodep->lsbp()->fileline(), + new AstConst(nodep->lsbp()->fileline(), 64), + newSelBitBit(nodep->lsbp())), + nodep->width()); // if (frombit==0) then ignore, else use it hip = new AstCond(nodep->fileline(), - new AstEq(nodep->fileline(), - new AstConst(nodep->fileline(), 0), + new AstEq(nodep->fileline(), new AstConst(nodep->fileline(), 0), newSelBitBit(nodep->lsbp())), - new AstConst(nodep->fileline(), zero), - himayp); + new AstConst(nodep->fileline(), zero), himayp); } AstNode* newp = lowp; @@ -440,18 +409,16 @@ private: if (hip) newp = new AstOr(nodep->fileline(), hip, newp); newp->dtypeFrom(nodep); VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep); - } - else { // Long/Quad from Long/Quad - UINFO(8," SEL->SHIFT "<SHIFT " << nodep << endl); AstNode* fromp = nodep->fromp()->unlinkFrBack(); AstNode* lsbp = nodep->lsbp()->unlinkFrBack(); if (nodep->isQuad() && !fromp->isQuad()) { fromp = new AstCCast(nodep->fileline(), fromp, nodep); } - AstNode* newp = new AstShiftR(nodep->fileline(), - fromp, - dropCondBound(lsbp), - fromp->width()); // {large}>>32 requires 64-bit shift operation; then cast + AstNode* newp = new AstShiftR( + nodep->fileline(), fromp, dropCondBound(lsbp), + fromp->width()); // {large}>>32 requires 64-bit shift operation; then cast newp->dtypeFrom(fromp); if (!nodep->isQuad() && fromp->isQuad()) { newp = new AstCCast(newp->fileline(), newp, nodep); @@ -465,42 +432,35 @@ private: UASSERT_OBJ(nodep->widthMin() == rhsp->widthConst(), nodep, "Width mismatch"); if (VN_IS(rhsp->lsbp(), Const) && VL_BITBIT_E(rhsp->lsbConst()) == 0) { int lsb = rhsp->lsbConst(); - UINFO(8," Wordize ASSIGN(SEL,align) "<widthWords(); w++) { + UINFO(8, " Wordize ASSIGN(SEL,align) " << nodep << endl); + for (int w = 0; w < nodep->widthWords(); w++) { addWordAssign(nodep, w, newAstWordSelClone(rhsp->fromp(), w + VL_BITWORD_E(lsb))); } return true; } else { - UINFO(8," Wordize ASSIGN(EXTRACT,misalign) "<widthWords(); w++) { + UINFO(8, " Wordize ASSIGN(EXTRACT,misalign) " << nodep << endl); + for (int w = 0; w < nodep->widthWords(); w++) { // Grab lowest bits - AstNode* lowwordp = new AstWordSel(rhsp->fileline(), - rhsp->fromp()->cloneTree(true), - newSelBitWord(rhsp->lsbp(), w)); - AstNode* lowp = new AstShiftR(rhsp->fileline(), - lowwordp, - newSelBitBit(rhsp->lsbp()), - VL_EDATASIZE); + AstNode* lowwordp + = new AstWordSel(rhsp->fileline(), rhsp->fromp()->cloneTree(true), + newSelBitWord(rhsp->lsbp(), w)); + AstNode* lowp = new AstShiftR(rhsp->fileline(), lowwordp, + newSelBitBit(rhsp->lsbp()), VL_EDATASIZE); // Upper bits - V3Number zero (nodep, VL_EDATASIZE, 0); + V3Number zero(nodep, VL_EDATASIZE, 0); AstNode* midwordp = // SEL(from,[1+wordnum]) - new AstWordSel(rhsp->fromp()->fileline(), - rhsp->fromp()->cloneTree(true), - newSelBitWord(rhsp->lsbp(), w+1)); - AstNode* midshiftp = new AstSub(rhsp->lsbp()->fileline(), - new AstConst(rhsp->lsbp()->fileline(), - VL_EDATASIZE), - newSelBitBit(rhsp->lsbp())); - AstNode* midmayp = new AstShiftL(rhsp->fileline(), - midwordp, - midshiftp, - VL_EDATASIZE); - AstNode* midp = new AstCond(rhsp->fileline(), - new AstEq(rhsp->fileline(), - new AstConst(rhsp->fileline(), 0), - newSelBitBit(rhsp->lsbp())), - new AstConst(rhsp->fileline(), zero), - midmayp); + new AstWordSel(rhsp->fromp()->fileline(), rhsp->fromp()->cloneTree(true), + newSelBitWord(rhsp->lsbp(), w + 1)); + AstNode* midshiftp = new AstSub( + rhsp->lsbp()->fileline(), new AstConst(rhsp->lsbp()->fileline(), VL_EDATASIZE), + newSelBitBit(rhsp->lsbp())); + AstNode* midmayp + = new AstShiftL(rhsp->fileline(), midwordp, midshiftp, VL_EDATASIZE); + AstNode* midp + = new AstCond(rhsp->fileline(), + new AstEq(rhsp->fileline(), new AstConst(rhsp->fileline(), 0), + newSelBitBit(rhsp->lsbp())), + new AstConst(rhsp->fileline(), zero), midmayp); AstNode* newp = new AstOr(nodep->fileline(), midp, lowp); addWordAssign(nodep, w, newp); } @@ -524,99 +484,84 @@ private: AstNode* destp = lhsp->fromp()->unlinkFrBack(); int lsb = lhsp->lsbConst(); int msb = lhsp->msbConst(); - V3Number maskset (nodep, destp->widthMin()); - for (int bit=lsb; bit<(msb+1); bit++) maskset.setBit(bit, 1); - V3Number maskold (nodep, destp->widthMin()); maskold.opNot(maskset); + V3Number maskset(nodep, destp->widthMin()); + for (int bit = lsb; bit < (msb + 1); bit++) maskset.setBit(bit, 1); + V3Number maskold(nodep, destp->widthMin()); + maskold.opNot(maskset); if (destwide) { - UINFO(8," ASSIGNSEL(const,wide) "<widthWords(); w++) { + UINFO(8, " ASSIGNSEL(const,wide) " << nodep << endl); + for (int w = 0; w < destp->widthWords(); w++) { if (w >= VL_BITWORD_E(lsb) && w <= VL_BITWORD_E(msb)) { // else we would just be setting it to the same exact value AstNode* oldvalp = newAstWordSelClone(destp, w); fixCloneLvalue(oldvalp); if (!ones) { - oldvalp = new AstAnd(lhsp->fileline(), - new AstConst(lhsp->fileline(), - AstConst::SizedEData(), - maskold.edataWord(w)), - oldvalp); + oldvalp + = new AstAnd(lhsp->fileline(), + new AstConst(lhsp->fileline(), AstConst::SizedEData(), + maskold.edataWord(w)), + oldvalp); } - addWordAssign(nodep, w, - destp, - new AstOr(lhsp->fileline(), - oldvalp, - newWordGrabShift(lhsp->fileline(), w, - rhsp, lsb))); + addWordAssign(nodep, w, destp, + new AstOr(lhsp->fileline(), oldvalp, + newWordGrabShift(lhsp->fileline(), w, rhsp, lsb))); } } VL_DO_DANGLING(rhsp->deleteTree(), rhsp); VL_DO_DANGLING(destp->deleteTree(), destp); } else { - UINFO(8," ASSIGNSEL(const,narrow) "<isQuad() && !rhsp->isQuad()) { rhsp = new AstCCast(nodep->fileline(), rhsp, nodep); } AstNode* oldvalp = destp->cloneTree(true); fixCloneLvalue(oldvalp); if (!ones) { - oldvalp = new AstAnd(lhsp->fileline(), - new AstConst(lhsp->fileline(), maskold), + oldvalp = new AstAnd(lhsp->fileline(), new AstConst(lhsp->fileline(), maskold), oldvalp); } - AstNode* newp - = new AstOr(lhsp->fileline(), - oldvalp, - new AstShiftL(lhsp->fileline(), - rhsp, - new AstConst(lhsp->fileline(), lsb), - destp->width())); + AstNode* newp = new AstOr(lhsp->fileline(), oldvalp, + new AstShiftL(lhsp->fileline(), rhsp, + new AstConst(lhsp->fileline(), lsb), + destp->width())); newp = new AstAssign(nodep->fileline(), destp, newp); insertBefore(nodep, newp); } return true; - } - else { // non-const RHS - if (destwide && lhsp->widthConst()==1) { - UINFO(8," ASSIGNSEL(varlsb,wide,1bit) "<widthConst() == 1) { + UINFO(8, " ASSIGNSEL(varlsb,wide,1bit) " << nodep << endl); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); AstNode* destp = lhsp->fromp()->unlinkFrBack(); - AstNode* oldvalp = new AstWordSel(lhsp->fileline(), - destp->cloneTree(true), + AstNode* oldvalp = new AstWordSel(lhsp->fileline(), destp->cloneTree(true), newSelBitWord(lhsp->lsbp(), 0)); fixCloneLvalue(oldvalp); if (!ones) { - oldvalp = new AstAnd - (lhsp->fileline(), - new AstNot(lhsp->fileline(), - new AstShiftL - (lhsp->fileline(), - new AstConst(nodep->fileline(), 1), - // newSelBitBit may exceed the MSB of this variable. - // That's ok as we'd just AND with a larger value, - // but oldval would clip the upper bits to sanity - newSelBitBit(lhsp->lsbp()), - VL_EDATASIZE)), - oldvalp); + oldvalp = new AstAnd( + lhsp->fileline(), + new AstNot( + lhsp->fileline(), + new AstShiftL(lhsp->fileline(), new AstConst(nodep->fileline(), 1), + // newSelBitBit may exceed the MSB of this variable. + // That's ok as we'd just AND with a larger value, + // but oldval would clip the upper bits to sanity + newSelBitBit(lhsp->lsbp()), VL_EDATASIZE)), + oldvalp); } // Restrict the shift amount to 0-31, see bug804. AstNode* shiftp = new AstAnd(nodep->fileline(), lhsp->lsbp()->cloneTree(true), new AstConst(nodep->fileline(), VL_EDATASIZE - 1)); - AstNode* newp = new AstOr(lhsp->fileline(), - oldvalp, - new AstShiftL(lhsp->fileline(), - rhsp, - shiftp, - VL_EDATASIZE)); - newp = new AstAssign(nodep->fileline(), - new AstWordSel(nodep->fileline(), - destp, - newSelBitWord(lhsp->lsbp(), 0)), - newp); + AstNode* newp + = new AstOr(lhsp->fileline(), oldvalp, + new AstShiftL(lhsp->fileline(), rhsp, shiftp, VL_EDATASIZE)); + newp = new AstAssign( + nodep->fileline(), + new AstWordSel(nodep->fileline(), destp, newSelBitWord(lhsp->lsbp(), 0)), + newp); insertBefore(nodep, newp); return true; - } - else if (destwide) { - UINFO(8," ASSIGNSEL(varlsb,wide) -- NoOp -- "<dumpTree(cout, "- old: "); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); AstNode* destp = lhsp->fromp()->unlinkFrBack(); AstNode* oldvalp = destp->cloneTree(true); fixCloneLvalue(oldvalp); - V3Number maskwidth (nodep, destp->widthMin()); - for (int bit=0; bit < lhsp->widthConst(); bit++) maskwidth.setBit(bit, 1); + V3Number maskwidth(nodep, destp->widthMin()); + for (int bit = 0; bit < lhsp->widthConst(); bit++) maskwidth.setBit(bit, 1); if (destp->isQuad() && !rhsp->isQuad()) { rhsp = new AstCCast(nodep->fileline(), rhsp, nodep); } if (!ones) { - oldvalp = new AstAnd(lhsp->fileline(), - new AstNot(lhsp->fileline(), - new AstShiftL(lhsp->fileline(), - new AstConst(nodep->fileline(), - maskwidth), - lhsp->lsbp()->cloneTree(true), - destp->width())), - oldvalp); + oldvalp = new AstAnd( + lhsp->fileline(), + new AstNot(lhsp->fileline(), + new AstShiftL(lhsp->fileline(), + new AstConst(nodep->fileline(), maskwidth), + lhsp->lsbp()->cloneTree(true), destp->width())), + oldvalp); } AstNode* newp - = new AstOr(lhsp->fileline(), - oldvalp, - new AstShiftL(lhsp->fileline(), - rhsp, - lhsp->lsbp()->cloneTree(true), - destp->width())); + = new AstOr(lhsp->fileline(), oldvalp, + new AstShiftL(lhsp->fileline(), rhsp, + lhsp->lsbp()->cloneTree(true), destp->width())); newp = new AstAssign(nodep->fileline(), destp, newp); - //newp->dumpTree(cout, "- new: "); + // newp->dumpTree(cout, "- new: "); insertBefore(nodep, newp); return true; } @@ -672,7 +613,7 @@ private: if (nodep->isWide()) { // See under ASSIGN(WIDE) } else { - UINFO(8," CONCAT "<lhsp()->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); int rhsshift = rhsp->widthMin(); @@ -683,28 +624,26 @@ private: rhsp = new AstCCast(nodep->fileline(), rhsp, nodep); } AstNode* newp = new AstOr(nodep->fileline(), - new AstShiftL(nodep->fileline(), - lhsp, + new AstShiftL(nodep->fileline(), lhsp, new AstConst(nodep->fileline(), rhsshift), nodep->width()), - rhsp); + rhsp); newp->dtypeFrom(nodep); // Unsigned VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep); } } bool expandWide(AstNodeAssign* nodep, AstConcat* rhsp) { - UINFO(8," Wordize ASSIGN(CONCAT) "<rhsp()->widthMin(); // Sometimes doing the words backwards is preferable. // When we have x={x,foo} backwards is better, when x={foo,x} forward is better // However V3Subst tends to rip this up, so not worth optimizing now. - for (int w=0; wwidthWords(); w++) { + for (int w = 0; w < rhsp->widthWords(); w++) { addWordAssign(nodep, w, new AstOr(rhsp->fileline(), - newWordGrabShift(rhsp->fileline(), w, - rhsp->lhsp(), rhsshift), + newWordGrabShift(rhsp->fileline(), w, rhsp->lhsp(), rhsshift), newAstWordSelClone(rhsp->rhsp(), w))); } return true; @@ -719,11 +658,11 @@ private: AstNode* lhsp = nodep->lhsp()->unlinkFrBack(); AstNode* newp; int lhswidth = lhsp->widthMin(); - if (lhswidth==1) { - UINFO(8," REPLICATE(w1) "<fileline(), lhsp); } else { - UINFO(8," REPLICATE "<rhsp(), Const); UASSERT_OBJ(constp, nodep, "Replication value isn't a constant. Checked earlier!"); @@ -732,14 +671,13 @@ private: lhsp = new AstCCast(nodep->fileline(), lhsp, nodep); } newp = lhsp->cloneTree(true); - for (unsigned repnum=1; repnumfileline(), - new AstShiftL(nodep->fileline(), - lhsp->cloneTree(true), + new AstShiftL(nodep->fileline(), lhsp->cloneTree(true), new AstConst(nodep->fileline(), rhsshift), nodep->width()), - newp); + newp); newp->dtypeFrom(nodep); // Unsigned } VL_DO_DANGLING(lhsp->deleteTree(), lhsp); // Never used @@ -749,25 +687,24 @@ private: } } bool expandWide(AstNodeAssign* nodep, AstReplicate* rhsp) { - UINFO(8," Wordize ASSIGN(REPLICATE) "<lhsp(); int lhswidth = lhsp->widthMin(); const AstConst* constp = VN_CAST(rhsp->rhsp(), Const); UASSERT_OBJ(constp, rhsp, "Replication value isn't a constant. Checked earlier!"); uint32_t times = constp->toUInt(); - for (int w=0; wwidthWords(); w++) { + for (int w = 0; w < rhsp->widthWords(); w++) { AstNode* newp; - if (lhswidth==1) { + if (lhswidth == 1) { newp = new AstNegate(nodep->fileline(), lhsp->cloneTree(true)); newp->dtypeSetLogicSized(VL_EDATASIZE, AstNumeric::UNSIGNED); // Replicate always unsigned } else { newp = newAstWordSelClone(lhsp, w); - for (unsigned repnum=1; repnumfileline(), - newWordGrabShift(rhsp->fileline(), w, lhsp, - lhswidth*repnum), - newp); + for (unsigned repnum = 1; repnum < times; repnum++) { + newp = new AstOr( + nodep->fileline(), + newWordGrabShift(rhsp->fileline(), w, lhsp, lhswidth * repnum), newp); } } addWordAssign(nodep, w, newp); @@ -778,14 +715,13 @@ private: virtual void visit(AstChangeXor* nodep) VL_OVERRIDE { if (nodep->user1SetOnce()) return; // Process once iterateChildren(nodep); - UINFO(8," Wordize ChangeXor "< (0=={or{for each_word{WORDSEL(lhs,#)^WORDSEL(rhs,#)}}} AstNode* newp = NULL; - for (int w=0; wlhsp()->widthWords(); w++) { - AstNode* eqp = new AstXor(nodep->fileline(), - newAstWordSelClone(nodep->lhsp(), w), + for (int w = 0; w < nodep->lhsp()->widthWords(); w++) { + AstNode* eqp = new AstXor(nodep->fileline(), newAstWordSelClone(nodep->lhsp(), w), newAstWordSelClone(nodep->rhsp(), w)); - newp = (newp==NULL) ? eqp : (new AstOr(nodep->fileline(), newp, eqp)); + newp = (newp == NULL) ? eqp : (new AstOr(nodep->fileline(), newp, eqp)); } VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep); } @@ -794,23 +730,21 @@ private: if (nodep->user1SetOnce()) return; // Process once iterateChildren(nodep); if (nodep->lhsp()->isWide()) { - UINFO(8," Wordize EQ/NEQ "< (0=={or{for each_word{WORDSEL(lhs,#)^WORDSEL(rhs,#)}}} AstNode* newp = NULL; - for (int w=0; wlhsp()->widthWords(); w++) { - AstNode* eqp = new AstXor(nodep->fileline(), - newAstWordSelClone(nodep->lhsp(), w), + for (int w = 0; w < nodep->lhsp()->widthWords(); w++) { + AstNode* eqp = new AstXor(nodep->fileline(), newAstWordSelClone(nodep->lhsp(), w), newAstWordSelClone(nodep->rhsp(), w)); - newp = (newp==NULL) ? eqp : (new AstOr(nodep->fileline(), newp, eqp)); + newp = (newp == NULL) ? eqp : (new AstOr(nodep->fileline(), newp, eqp)); } if (VN_IS(nodep, Neq)) { - newp = new AstNeq(nodep->fileline(), - new AstConst(nodep->fileline(), AstConst::SizedEData(), 0), - newp); + newp + = new AstNeq(nodep->fileline(), + new AstConst(nodep->fileline(), AstConst::SizedEData(), 0), newp); } else { newp = new AstEq(nodep->fileline(), - new AstConst(nodep->fileline(), AstConst::SizedEData(), 0), - newp); + new AstConst(nodep->fileline(), AstConst::SizedEData(), 0), newp); } VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep); } @@ -822,19 +756,18 @@ private: if (nodep->user1SetOnce()) return; // Process once iterateChildren(nodep); if (nodep->lhsp()->isWide()) { - UINFO(8," Wordize REDOR "< (0!={or{for each_word{WORDSEL(lhs,#)}}} AstNode* newp = NULL; - for (int w=0; wlhsp()->widthWords(); w++) { + for (int w = 0; w < nodep->lhsp()->widthWords(); w++) { AstNode* eqp = newAstWordSelClone(nodep->lhsp(), w); - newp = (newp==NULL) ? eqp : (new AstOr(nodep->fileline(), newp, eqp)); + newp = (newp == NULL) ? eqp : (new AstOr(nodep->fileline(), newp, eqp)); } newp = new AstNeq(nodep->fileline(), - new AstConst(nodep->fileline(), AstConst::SizedEData(), 0), - newp); + new AstConst(nodep->fileline(), AstConst::SizedEData(), 0), newp); VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep); } else { - UINFO(8," REDOR->EQ "<EQ " << nodep << endl); AstNode* lhsp = nodep->lhsp()->unlinkFrBack(); AstNode* newp = new AstNeq(nodep->fileline(), new AstConst(nodep->fileline(), AstConst::WidthedValue(), @@ -847,12 +780,12 @@ private: if (nodep->user1SetOnce()) return; // Process once iterateChildren(nodep); if (nodep->lhsp()->isWide()) { - UINFO(8," Wordize REDAND "< (0!={and{for each_word{WORDSEL(lhs,#)}}} AstNode* newp = NULL; - for (int w=0; wlhsp()->widthWords(); w++) { + for (int w = 0; w < nodep->lhsp()->widthWords(); w++) { AstNode* eqp = newAstWordSelClone(nodep->lhsp(), w); - if (w==nodep->lhsp()->widthWords()-1) { + if (w == nodep->lhsp()->widthWords() - 1) { // Rather than doing a (slowish) ==##, we OR in the // bits that aren't part of the mask eqp = new AstOr(nodep->fileline(), @@ -861,18 +794,17 @@ private: // cppcheck-suppress memleak eqp); } - newp = (newp==NULL) ? eqp : (new AstAnd(nodep->fileline(), newp, eqp)); + newp = (newp == NULL) ? eqp : (new AstAnd(nodep->fileline(), newp, eqp)); } - newp = new AstEq(nodep->fileline(), - new AstConst(nodep->fileline(), AstConst::SizedEData(), - ~VL_MASK_E(0)), newp); + newp = new AstEq( + nodep->fileline(), + new AstConst(nodep->fileline(), AstConst::SizedEData(), ~VL_MASK_E(0)), newp); VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep); } else { - UINFO(8," REDAND->EQ "<EQ " << nodep << endl); AstNode* lhsp = nodep->lhsp()->unlinkFrBack(); AstNode* newp = new AstEq(nodep->fileline(), - new AstConst(nodep->fileline(), wordMask(lhsp)), - lhsp); + new AstConst(nodep->fileline(), wordMask(lhsp)), lhsp); VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep); } } @@ -880,15 +812,15 @@ private: if (nodep->user1SetOnce()) return; // Process once iterateChildren(nodep); if (nodep->lhsp()->isWide()) { - UINFO(8," Wordize REDXOR "< (0!={redxor{for each_word{XOR(WORDSEL(lhs,#))}}} AstNode* newp = NULL; - for (int w=0; wlhsp()->widthWords(); w++) { + for (int w = 0; w < nodep->lhsp()->widthWords(); w++) { AstNode* eqp = newAstWordSelClone(nodep->lhsp(), w); - newp = (newp==NULL) ? eqp : (new AstXor(nodep->fileline(), newp, eqp)); + newp = (newp == NULL) ? eqp : (new AstXor(nodep->fileline(), newp, eqp)); } newp = new AstRedXor(nodep->fileline(), newp); - UINFO(8," Wordize REDXORnew "<isWide() && ((VN_IS(nodep->lhsp(), VarRef) - || VN_IS(nodep->lhsp(), ArraySel))) + if (nodep->isWide() && ((VN_IS(nodep->lhsp(), VarRef) || VN_IS(nodep->lhsp(), ArraySel))) && !AstVar::scVarRecurse(nodep->lhsp()) // Need special function for SC && !AstVar::scVarRecurse(nodep->rhsp())) { if (AstConst* rhsp = VN_CAST(nodep->rhsp(), Const)) { @@ -943,9 +874,7 @@ private: did = expandLhs(nodep, lhsp); } // Cleanup common code - if (did) { - VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } + if (did) VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); m_stmtp = NULL; } @@ -969,9 +898,7 @@ public: // Expand class functions void V3Expand::expandAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3File.cpp b/src/V3File.cpp index dee1298f2..45527897e 100644 --- a/src/V3File.cpp +++ b/src/V3File.cpp @@ -33,6 +33,7 @@ #include #include +// clang-format off #if defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)) # define INFILTER_PIPE // Allow pipe filtering. Needs fork() #endif @@ -52,11 +53,12 @@ #if defined(_WIN32) || defined(__MINGW32__) # include // open, read, write, close #endif +// clang-format on // If change this code, run a test with the below size set very small //#define INFILTER_IPC_BUFSIZ 16 -#define INFILTER_IPC_BUFSIZ (64*1024) // For debug, try this as a small number -#define INFILTER_CACHE_MAX (64*1024) // Maximum bytes to cache if same file read twice +#define INFILTER_IPC_BUFSIZ (64 * 1024) // For debug, try this as a small number +#define INFILTER_CACHE_MAX (64 * 1024) // Maximum bytes to cache if same file read twice //###################################################################### // V3File Internal state @@ -65,13 +67,15 @@ class V3FileDependImp { // TYPES class DependFile { // A single file - bool m_target; // True if write, else read - bool m_exists; - string m_filename; // Filename - struct stat m_stat; // Stat information + bool m_target; // True if write, else read + bool m_exists; + string m_filename; // Filename + struct stat m_stat; // Stat information public: DependFile(const string& filename, bool target) - : m_target(target), m_exists(true), m_filename(filename) { + : m_target(target) + , m_exists(true) + , m_filename(filename) { m_stat.st_ctime = 0; m_stat.st_mtime = 0; } @@ -89,16 +93,16 @@ class V3FileDependImp { if (!m_stat.st_mtime) { string fn = filename(); int err = stat(fn.c_str(), &m_stat); - if (err!=0) { + if (err != 0) { memset(&m_stat, 0, sizeof(m_stat)); m_stat.st_mtime = 1; m_exists = false; // Not an error... This can occur due to `line directives in the .vpp files - UINFO(1,"-Info: File not statable: "< ofp (V3File::new_ofstream(filename)); - if (ofp->fail()) v3fatal("Can't write "< ofp(V3File::new_ofstream(filename)); + if (ofp->fail()) v3fatal("Can't write " << filename); - for (std::set::iterator iter=m_filenameList.begin(); - iter!=m_filenameList.end(); ++iter) { - if (iter->target()) { - *ofp<filename()<<" "; - } + for (std::set::iterator iter = m_filenameList.begin(); + iter != m_filenameList.end(); ++iter) { + if (iter->target()) { *ofp << iter->filename() << " "; } } - *ofp<<" : "; - *ofp<::iterator iter=m_filenameList.begin(); - iter!=m_filenameList.end(); ++iter) { - if (!iter->target()) { - *ofp<filename()<<" "; - } + for (std::set::iterator iter = m_filenameList.begin(); + iter != m_filenameList.end(); ++iter) { + if (!iter->target()) { *ofp << iter->filename() << " "; } } - *ofp<::iterator iter=m_filenameList.begin(); - iter!=m_filenameList.end(); ++iter) { - if (!iter->target()) { - *ofp<filename()<<":"<::iterator iter = m_filenameList.begin(); + iter != m_filenameList.end(); ++iter) { + if (!iter->target()) { *ofp << iter->filename() << ":" << endl; } } } } inline std::vector V3FileDependImp::getAllDeps() const { std::vector r; - for (std::set::const_iterator iter=m_filenameList.begin(); - iter!=m_filenameList.end(); ++iter) { - if (!iter->target() && iter->exists()) { - r.push_back(iter->filename()); - } + for (std::set::const_iterator iter = m_filenameList.begin(); + iter != m_filenameList.end(); ++iter) { + if (!iter->target() && iter->exists()) { r.push_back(iter->filename()); } } return r; } inline void V3FileDependImp::writeTimes(const string& filename, const string& cmdlineIn) { - const vl_unique_ptr ofp (V3File::new_ofstream(filename)); - if (ofp->fail()) v3fatal("Can't write "< ofp(V3File::new_ofstream(filename)); + if (ofp->fail()) v3fatal("Can't write " << filename); string cmdline = stripQuotes(cmdlineIn); - *ofp<<"# DESCR"<<"IPTION: Verilator output: Timestamp data for --skip-identical. Delete at will."<::iterator iter=m_filenameList.begin(); - iter!=m_filenameList.end(); ++iter) { + for (std::set::iterator iter = m_filenameList.begin(); + iter != m_filenameList.end(); ++iter) { // Read stats of files we create after we're done making them // (except for this file, of course) DependFile* dfp = const_cast(&(*iter)); @@ -204,84 +203,97 @@ inline void V3FileDependImp::writeTimes(const string& filename, const string& cm off_t showSize = iter->size(); ino_t showIno = iter->ino(); if (dfp->filename() == filename) { - showSize = 0; showIno = 0; // We're writing it, so need to ignore it + showSize = 0; + showIno = 0; // We're writing it, so need to ignore it } - *ofp<<(iter->target()?"T":"S")<<" "; - *ofp<<" "<cstime(); - *ofp<<" "<cnstime(); - *ofp<<" "<mstime(); - *ofp<<" "<mnstime(); - *ofp<<" \""<filename()<<"\""; - *ofp<target() ? "T" : "S") << " "; + *ofp << " " << std::setw(8) << showSize; + *ofp << " " << std::setw(8) << showIno; + *ofp << " " << std::setw(11) << iter->cstime(); + *ofp << " " << std::setw(11) << iter->cnstime(); + *ofp << " " << std::setw(11) << iter->mstime(); + *ofp << " " << std::setw(11) << iter->mnstime(); + *ofp << " \"" << iter->filename() << "\""; + *ofp << endl; } } inline bool V3FileDependImp::checkTimes(const string& filename, const string& cmdlineIn) { - const vl_unique_ptr ifp (V3File::new_ifstream_nodepend(filename)); + const vl_unique_ptr ifp(V3File::new_ifstream_nodepend(filename)); if (ifp->fail()) { - UINFO(2," --check-times failed: no input "<>chkDir; - char quote; *ifp>>quote; + char chkDir; + *ifp >> chkDir; + char quote; + *ifp >> quote; string chkCmdline = V3Os::getline(*ifp, '"'); string cmdline = stripQuotes(cmdlineIn); if (cmdline != chkCmdline) { - UINFO(2," --check-times failed: different command line\n"); + UINFO(2, " --check-times failed: different command line\n"); return false; } } while (!ifp->eof()) { - char chkDir; *ifp>>chkDir; - off_t chkSize; *ifp>>chkSize; - ino_t chkIno; *ifp>>chkIno; + char chkDir; + *ifp >> chkDir; + off_t chkSize; + *ifp >> chkSize; + ino_t chkIno; + *ifp >> chkIno; if (ifp->eof()) break; // Needed to read final whitespace before found eof - time_t chkCstime; *ifp>>chkCstime; - time_t chkCnstime; *ifp>>chkCnstime; - time_t chkMstime; *ifp>>chkMstime; - time_t chkMnstime; *ifp>>chkMnstime; - char quote; *ifp>>quote; + time_t chkCstime; + *ifp >> chkCstime; + time_t chkCnstime; + *ifp >> chkCnstime; + time_t chkMstime; + *ifp >> chkMstime; + time_t chkMnstime; + *ifp >> chkMnstime; + char quote; + *ifp >> quote; string chkFilename = V3Os::getline(*ifp, '"'); V3Options::fileNfsFlush(chkFilename); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) struct stat chkStat; int err = stat(chkFilename.c_str(), &chkStat); - if (err!=0) { - UINFO(2," --check-times failed: missing "< V3File::getAllDeps() { - return dependImp.getAllDeps(); -} +void V3File::addSrcDepend(const string& filename) { dependImp.addSrcDepend(filename); } +void V3File::addTgtDepend(const string& filename) { dependImp.addTgtDepend(filename); } +void V3File::writeDepend(const string& filename) { dependImp.writeDepend(filename); } +std::vector V3File::getAllDeps() { return dependImp.getAllDeps(); } void V3File::writeTimes(const string& filename, const string& cmdlineIn) { dependImp.writeTimes(filename, cmdlineIn); } @@ -313,7 +317,8 @@ bool V3File::checkTimes(const string& filename, const string& cmdlineIn) { void V3File::createMakeDirFor(const string& filename) { if (filename != VL_DEV_NULL // If doesn't start with makeDir then some output file user requested - && filename.substr(0, v3Global.opt.makeDir().length()+1) == v3Global.opt.makeDir()+"/") { + && filename.substr(0, v3Global.opt.makeDir().length() + 1) + == v3Global.opt.makeDir() + "/") { createMakeDir(); } } @@ -329,41 +334,44 @@ void V3File::createMakeDir() { // VInFilterImp class VInFilterImp { - typedef std::map FileContentsMap; + typedef std::map FileContentsMap; typedef VInFilter::StrList StrList; - FileContentsMap m_contentsMap; // Cache of file contents - bool m_readEof; // Received EOF on read + FileContentsMap m_contentsMap; // Cache of file contents + bool m_readEof; // Received EOF on read #ifdef INFILTER_PIPE - pid_t m_pid; // fork() process id + pid_t m_pid; // fork() process id #else - int m_pid; // fork() process id - always zero as disabled + int m_pid; // fork() process id - always zero as disabled #endif - bool m_pidExited; - int m_pidStatus; - int m_writeFd; // File descriptor TO filter - int m_readFd; // File descriptor FROM filter + bool m_pidExited; + int m_pidStatus; + int m_writeFd; // File descriptor TO filter + int m_readFd; // File descriptor FROM filter private: // METHODS VL_DEBUG_FUNC; // Declare debug() bool readContents(const string& filename, StrList& outl) { - if (m_pid) return readContentsFilter(filename, outl); - else return readContentsFile(filename, outl); + if (m_pid) { + return readContentsFilter(filename, outl); + } else { + return readContentsFile(filename, outl); + } } bool readContentsFile(const string& filename, StrList& outl) { int fd = open(filename.c_str(), O_RDONLY); - if (fd<0) return false; + if (fd < 0) return false; m_readEof = false; readBlocks(fd, -1, outl); close(fd); return true; } bool readContentsFilter(const string& filename, StrList& outl) { - if (filename!="" || outl.empty()) {} // Prevent unused + if (filename != "" || outl.empty()) {} // Prevent unused #ifdef INFILTER_PIPE - writeFilter("read \""+filename+"\"\n"); + writeFilter("read \"" + filename + "\"\n"); string line = readFilterLine(); if (line.find("Content-Length") != string::npos) { int len = 0; @@ -371,7 +379,7 @@ private: readBlocks(m_readFd, len, outl); return true; } else { - if (line!="") v3error("--pipe-filter protocol error, unexpected: "<sizegot)) { + while (!m_readEof && (size < 0 || size > sizegot)) { ssize_t todo = INFILTER_IPC_BUFSIZ; - if (size>0 && size 0 && size < todo) todo = size; errno = 0; ssize_t got = read(fd, buf, todo); - //UINFO(9,"RD GOT g "<< got<<" e "<0) { + // UINFO(9,"RD GOT g "<< got<<" e "< 0) { outl.push_back(string(buf, got)); sizegot += got; - } - else if (errno == EINTR || errno == EAGAIN + } else if (errno == EINTR || errno == EAGAIN #ifdef EWOULDBLOCK - || errno == EWOULDBLOCK + || errno == EWOULDBLOCK #endif - ) { - checkFilter(false); V3Os::u_sleep(1000); continue; - } else { m_readEof = true; break; } + ) { + checkFilter(false); + V3Os::u_sleep(1000); + continue; + } else { + m_readEof = true; + break; + } } return out; } // cppcheck-suppress unusedFunction unusedPrivateFunction string readFilterLine() { // Slow, but we don't need it much - UINFO(9,"readFilterLine\n"); + UINFO(9, "readFilterLine\n"); string line; while (!m_readEof) { StrList outl; @@ -427,65 +441,81 @@ private: string onechar = listString(outl); line += onechar; if (onechar == "\n") { - if (line == "\n") { line = ""; continue; } - else break; + if (line == "\n") { + line = ""; + continue; + } else { + break; + } } } - UINFO(6,"filter-line-in: "<=6) { UINFO(6,"filter-out: "<= 6) { + UINFO(6, "filter-out: " << out); + if (out[out.length() - 1] != '\n') cout << endl; + } + if (!m_pid) { + v3error("--pipe-filter: write to closed file\n"); + m_readEof = true; + stop(); + } unsigned offset = 0; - while (!m_readEof && out.length()>offset) { + while (!m_readEof && out.length() > offset) { errno = 0; - int got = write(m_writeFd, (out.c_str())+offset, out.length()-offset); - //UINFO(9,"WR GOT g "<< got<<" e "<0) offset += got; - else if (errno == EINTR || errno == EAGAIN + int got = write(m_writeFd, (out.c_str()) + offset, out.length() - offset); + // UINFO(9,"WR GOT g "<< got<<" e "< 0) { + offset += got; + } else if (errno == EINTR || errno == EAGAIN #ifdef EWOULDBLOCK - || errno == EWOULDBLOCK + || errno == EWOULDBLOCK #endif - ) { - checkFilter(false); V3Os::u_sleep(1000); continue; + ) { + checkFilter(false); + V3Os::u_sleep(1000); + continue; + } else { + break; } - else break; } } // Start the filter void start(const string& command) { - if (command=="") { + if (command == "") { m_pid = 0; // Disabled } else { startFilter(command); } } void startFilter(const string& command) { - if (command=="") {} // Prevent Unused + if (command == "") {} // Prevent Unused #ifdef INFILTER_PIPE int fd_stdin[2], fd_stdout[2]; static const int P_RD = 0; static const int P_WR = 1; if (pipe(fd_stdin) != 0 || pipe(fd_stdout) != 0) { - v3fatal("--pipe-filter: Can't pipe: "<"<"<" + << fd_stdin[P_RD] << " stdout " << fd_stdout[P_WR] + << "->" << fd_stdout[P_RD] << endl); m_pid = pid; m_pidExited = false; m_pidStatus = 0; @@ -517,7 +546,7 @@ private: flags = fcntl(m_writeFd, F_GETFL, 0); fcntl(m_writeFd, F_SETFL, flags | O_NONBLOCK); } - UINFO(6,"startFilter complete\n"); + UINFO(6, "startFilter complete\n"); #else v3fatalSrc("--pipe-filter not implemented on this platform"); #endif @@ -527,16 +556,16 @@ private: if (m_pid) stopFilter(); } void stopFilter() { - UINFO(6,"Stopping filter process\n"); + UINFO(6, "Stopping filter process\n"); #ifdef INFILTER_PIPE close(m_writeFd); checkFilter(true); - if (!WIFEXITED(m_pidStatus) || WEXITSTATUS(m_pidStatus)!=0) { + if (!WIFEXITED(m_pidStatus) || WEXITSTATUS(m_pidStatus) != 0) { v3fatal("--pipe-filter returned bad status"); } m_pid = 0; close(m_readFd); - UINFO(6,"Closed\n"); + UINFO(6, "Closed\n"); #else v3fatalSrc("--pipe-filter not implemented on this platform"); #endif @@ -562,16 +591,12 @@ protected: } size_t listSize(StrList& sl) { size_t out = 0; - for (StrList::iterator it=sl.begin(); it!=sl.end(); ++it) { - out += it->length(); - } + for (StrList::iterator it = sl.begin(); it != sl.end(); ++it) out += it->length(); return out; } string listString(StrList& sl) { string out; - for (StrList::iterator it=sl.begin(); it!=sl.end(); ++it) { - out += *it; - } + for (StrList::iterator it = sl.begin(); it != sl.end(); ++it) out += *it; return out; } // CONSTRUCTORS @@ -592,7 +617,9 @@ protected: // Just dispatch to the implementation VInFilter::VInFilter(const string& command) { m_impp = new VInFilterImp(command); } -VInFilter::~VInFilter() { if (m_impp) VL_DO_CLEAR(delete m_impp, m_impp = NULL); } +VInFilter::~VInFilter() { + if (m_impp) VL_DO_CLEAR(delete m_impp, m_impp = NULL); +} bool VInFilter::readWholefile(const string& filename, VInFilter::StrList& outl) { if (!m_impp) v3fatalSrc("readWholefile on invalid filter"); @@ -603,40 +630,46 @@ bool VInFilter::readWholefile(const string& filename, VInFilter::StrList& outl) // V3OutFormatter: A class for printing to a file, with automatic indentation of C++ code. V3OutFormatter::V3OutFormatter(const string& filename, V3OutFormatter::Language lang) - : m_filename(filename), m_lang(lang) - , m_lineno(1), m_column(0) - , m_nobreak(false), m_prependIndent(true), m_indentLevel(0), m_bracketLevel(0) { + : m_filename(filename) + , m_lang(lang) + , m_lineno(1) + , m_column(0) + , m_nobreak(false) + , m_prependIndent(true) + , m_indentLevel(0) + , m_bracketLevel(0) { m_blockIndent = v3Global.opt.decoration() ? 4 : 1; - m_commaWidth = v3Global.opt.decoration() ? 50 : 150; + m_commaWidth = v3Global.opt.decoration() ? 50 : 150; } //---------------------------------------------------------------------- const string V3OutFormatter::indentSpaces(int num) { // Indent the specified number of spaces. Use spaces. - static char str[MAXSPACE+20]; + static char str[MAXSPACE + 20]; char* cp = str; - if (num>MAXSPACE) num = MAXSPACE; - while (num>0) { + if (num > MAXSPACE) num = MAXSPACE; + while (num > 0) { *cp++ = ' '; - num --; + --num; } *cp++ = '\0'; - string st (str); + string st(str); return st; } bool V3OutFormatter::tokenStart(const char* cp, const char* cmp) { - while (*cmp == *cp) { cp++; cmp++; } + while (*cmp == *cp) { + ++cp; + ++cmp; + } if (*cmp) return false; if (*cp && !isspace(*cp)) return false; return true; } bool V3OutFormatter::tokenEnd(const char* cp) { - return (tokenStart(cp, "end") - || tokenStart(cp, "endcase") - || tokenStart(cp, "endmodule")); + return (tokenStart(cp, "end") || tokenStart(cp, "endcase") || tokenStart(cp, "endmodule")); } int V3OutFormatter::endLevels(const char* strg) { @@ -653,32 +686,26 @@ int V3OutFormatter::endLevels(const char* strg) { { // label/public/private: Deindent by 2 spaces const char* mp = cp; - for (; isalnum(*mp); mp++) ; - if (mp[0]==':' && mp[1]!=':') return (levels-m_blockIndent/2); + for (; isalnum(*mp); mp++) {} + if (mp[0] == ':' && mp[1] != ':') return (levels - m_blockIndent / 2); } } // We want "} else {" to be one level to the left of normal - for (const char* cp=strg; *cp; cp++) { + for (const char* cp = strg; *cp; cp++) { switch (*cp) { case '}': - case ')': - levels -= m_blockIndent; - break; + case ')': levels -= m_blockIndent; break; case '<': - if (m_lang==LA_XML) { + if (m_lang == LA_XML) { if (cp[1] == '/') levels -= m_blockIndent; } break; case 'e': - if (m_lang==LA_VERILOG && tokenEnd(cp)) { - levels -= m_blockIndent; - } + if (m_lang == LA_VERILOG && tokenEnd(cp)) levels -= m_blockIndent; break; case '\t': - case ' ': - break; // Continue - default: - return levels; // Letter + case ' ': break; // Continue + default: return levels; // Letter } } return levels; @@ -691,28 +718,26 @@ void V3OutFormatter::puts(const char* strg) { } bool wordstart = true; bool equalsForBracket = false; // Looking for "= {" - for (const char* cp=strg; *cp; cp++) { + for (const char* cp = strg; *cp; cp++) { putcNoTracking(*cp); switch (*cp) { case '\n': m_lineno++; wordstart = true; - if (cp[1]=='\0') { - m_prependIndent = true; // Add the indent later, may be a indentInc/indentDec called between now and then + if (cp[1] == '\0') { + // Add the indent later, may be a indentInc/indentDec + // called between now and then + m_prependIndent = true; } else { m_prependIndent = false; - putsNoTracking(indentSpaces(endLevels(cp+1))); + putsNoTracking(indentSpaces(endLevels(cp + 1))); } break; - case ' ': - wordstart = true; - break; - case '\t': - wordstart = true; - break; + case ' ': wordstart = true; break; + case '\t': wordstart = true; break; case '/': - if (m_lang==LA_C || m_lang==LA_VERILOG) { - if (cp>strg && cp[-1]=='/') { + if (m_lang == LA_C || m_lang == LA_VERILOG) { + if (cp > strg && cp[-1] == '/') { // Output ignoring contents to EOL cp++; while (*cp && cp[1] && cp[1] != '\n') putcNoTracking(*cp++); @@ -721,15 +746,16 @@ void V3OutFormatter::puts(const char* strg) { } break; case '{': - if (m_lang==LA_C && (equalsForBracket || m_bracketLevel)) { + if (m_lang == LA_C && (equalsForBracket || m_bracketLevel)) { // Break up large code inside "= { ..." - m_parenVec.push(m_indentLevel*m_blockIndent); // Line up continuation with block+1 + m_parenVec.push(m_indentLevel + * m_blockIndent); // Line up continuation with block+1 ++m_bracketLevel; } indentInc(); break; case '}': - if (m_bracketLevel>0) { + if (m_bracketLevel > 0) { m_parenVec.pop(); --m_bracketLevel; } @@ -738,9 +764,11 @@ void V3OutFormatter::puts(const char* strg) { case '(': indentInc(); if (v3Global.opt.decoration()) { - m_parenVec.push(m_column); // Line up continuation with open paren, plus one indent + // Line up continuation with open paren, plus one indent + m_parenVec.push(m_column); } else { - m_parenVec.push(m_indentLevel*m_blockIndent); // Line up continuation with block+1 + // Line up continuation with block+1 + m_parenVec.push(m_indentLevel * m_blockIndent); } break; case ')': @@ -748,59 +776,50 @@ void V3OutFormatter::puts(const char* strg) { indentDec(); break; case '<': - if (m_lang==LA_XML) { - if (cp[1] == '/') {} // Zero as the > will result in net decrease by one - else if (cp[1] == '!' || cp[1] == '?') { indentInc(); } // net same indent - else { indentInc(); indentInc(); } // net increase by one + if (m_lang == LA_XML) { + if (cp[1] == '/') { + // Zero as the > will result in net decrease by one + } else if (cp[1] == '!' || cp[1] == '?') { + indentInc(); // net same indent + } else { + indentInc(); // net increase by one + indentInc(); + } } break; case '>': - if (m_lang==LA_XML) { + if (m_lang == LA_XML) { indentDec(); - if (cp>strg && cp[-1]=='/') indentDec(); // < ..... /> stays same level + if (cp > strg && cp[-1] == '/') indentDec(); // < ..... /> stays same level } break; case 'b': - if (wordstart && m_lang==LA_VERILOG && tokenStart(cp, "begin")) { - indentInc(); - } + 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") + 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(); - } + 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: + if (wordstart && m_lang == LA_VERILOG && tokenStart(cp, "module")) { indentInc(); } wordstart = false; break; + default: wordstart = false; break; } switch (*cp) { - case '=': - equalsForBracket = true; - break; - case ' ': - break; - default: - equalsForBracket = false; - break; + case '=': equalsForBracket = true; break; + case ' ': break; + default: equalsForBracket = false; break; } } } @@ -812,7 +831,7 @@ void V3OutFormatter::putBreakExpr() { // Add a line break if too wide void V3OutFormatter::putBreak() { if (!m_nobreak) { - //char s[1000]; sprintf(s, "{%d,%d}", m_column, m_parenVec.top()); putsNoTracking(s); + // char s[1000]; sprintf(s, "{%d,%d}", m_column, m_parenVec.top()); putsNoTracking(s); if (exceededWidth()) { putcNoTracking('\n'); if (!m_parenVec.empty()) putsNoTracking(indentSpaces(m_parenVec.top())); @@ -825,16 +844,14 @@ void V3OutFormatter::putsQuoted(const string& strg) { // Don't use to quote a filename for #include - #include doesn't \ escape. putcNoTracking('"'); string quoted = quoteNameControls(strg); - for (string::const_iterator cp=quoted.begin(); cp!=quoted.end(); ++cp) { + for (string::const_iterator cp = quoted.begin(); cp != quoted.end(); ++cp) { putcNoTracking(*cp); } putcNoTracking('"'); } void V3OutFormatter::putsNoTracking(const string& strg) { // Don't track {}'s, probably because it's a $display format string - for (string::const_iterator cp=strg.begin(); cp!=strg.end(); ++cp) { - putcNoTracking(*cp); - } + for (string::const_iterator cp = strg.begin(); cp != strg.end(); ++cp) putcNoTracking(*cp); } void V3OutFormatter::putcNoTracking(char chr) { @@ -844,15 +861,11 @@ void V3OutFormatter::putcNoTracking(char chr) { m_column = 0; m_nobreak = true; break; - case '\t': - m_column = ((m_column + 9)/8)*8; - break; + case '\t': m_column = ((m_column + 9) / 8) * 8; break; case ' ': case '(': case '|': - case '&': - m_column++; - break; + case '&': m_column++; break; default: m_column++; m_nobreak = false; @@ -865,43 +878,45 @@ string V3OutFormatter::quoteNameControls(const string& namein, V3OutFormatter::L // Encode control chars into output-appropriate escapes // Reverse is V3Parse::deQuote string out; - if (lang==LA_XML) { + if (lang == LA_XML) { // Encode chars into XML string - for (string::const_iterator pos=namein.begin(); pos!=namein.end(); ++pos) { - if (pos[0]=='"') { + for (string::const_iterator pos = namein.begin(); pos != namein.end(); ++pos) { + if (pos[0] == '"') { out += string("""); - } else if (pos[0]=='\'') { + } else if (pos[0] == '\'') { out += string("'"); - } else if (pos[0]=='<') { + } else if (pos[0] == '<') { out += string("<"); - } else if (pos[0]=='>') { + } else if (pos[0] == '>') { out += string(">"); - } else if (pos[0]=='&') { + } else if (pos[0] == '&') { out += string("&"); } else if (isprint(pos[0])) { out += pos[0]; } else { - char decimal[10]; sprintf(decimal, "&#%u;", (unsigned char)pos[0]); + char decimal[10]; + sprintf(decimal, "&#%u;", (unsigned char)pos[0]); out += decimal; } } } else { // Encode control chars into C style escapes - for (string::const_iterator pos=namein.begin(); pos!=namein.end(); ++pos) { - if (pos[0]=='\\' || pos[0]=='"') { - out += string("\\")+pos[0]; - } else if (pos[0]=='\n') { + for (string::const_iterator pos = namein.begin(); pos != namein.end(); ++pos) { + if (pos[0] == '\\' || pos[0] == '"') { + out += string("\\") + pos[0]; + } else if (pos[0] == '\n') { out += "\\n"; - } else if (pos[0]=='\r') { + } else if (pos[0] == '\r') { out += "\\r"; - } else if (pos[0]=='\t') { + } else if (pos[0] == '\t') { out += "\\t"; } else if (isprint(pos[0])) { out += pos[0]; } else { // This will also cover \a etc // Can't use %03o as messes up when signed - char octal[10]; sprintf(octal, "\\%o%o%o", (pos[0]>>6)&3, (pos[0]>>3)&7, pos[0]&7); + char octal[10]; + sprintf(octal, "\\%o%o%o", (pos[0] >> 6) & 3, (pos[0] >> 3) & 7, pos[0] & 7); out += octal; } } @@ -926,9 +941,7 @@ void V3OutFormatter::printf(const char* fmt...) { V3OutFile::V3OutFile(const string& filename, V3OutFormatter::Language lang) : V3OutFormatter(filename, lang) { - if ((m_fp = V3File::new_fopen_w(filename)) == NULL) { - v3fatal("Cannot write "< IdMap; + typedef std::map IdMap; IdMap m_nameMap; // Map of old name into new name typedef vl_unordered_set IdSet; IdSet m_newIdSet; // Which new names exist protected: // CONSTRUCTORS friend class VIdProtect; - static VIdProtectImp& singleton() { static VIdProtectImp s; return s; } + static VIdProtectImp& singleton() { + static VIdProtectImp s; + return s; + } + public: VIdProtectImp() { passthru("this"); @@ -981,10 +998,9 @@ public: IdMap::iterator it = m_nameMap.find(old); if (it != m_nameMap.end()) { // No way to go back and correct the older crypt name - UASSERT(old == it->second, "Passthru request for '" - +old+"' after already --protect-ids of it."); - } - else { + UASSERT(old == it->second, + "Passthru request for '" + old + "' after already --protect-ids of it."); + } else { m_nameMap.insert(make_pair(old, old)); m_newIdSet.insert(old); } @@ -993,19 +1009,20 @@ public: string protectIf(const string& old, bool doIt) { if (!v3Global.opt.protectIds() || old.empty() || !doIt) return old; IdMap::iterator it = m_nameMap.find(old); - if (it != m_nameMap.end()) return it->second; + if (it != m_nameMap.end()) + return it->second; else { string out; if (v3Global.opt.debugProtect()) { // This lets us see the symbol being protected to debug cases // where e.g. the definition is protect() but reference is // missing a protect() - out = "PS"+old; + out = "PS" + old; } else { - VHashSha256 digest (v3Global.opt.protectKeyDefaulted()); + VHashSha256 digest(v3Global.opt.protectKeyDefaulted()); digest.insert(old); // Add "PS" prefix (Protect Symbols) as cannot start symbol with number - out = "PS"+digest.digestSymbol(); + out = "PS" + digest.digestSymbol(); // See if we can shrink the digest symbol to something smaller for (size_t len = 6; len < out.size() - 3; len += 3) { string tryout = out.substr(0, len); @@ -1030,28 +1047,30 @@ public: // When C++11, use find_if and lambda string::size_type pos = string::npos; string separator; - trySep(old, start, " ", pos/*ref*/, separator/*ref*/); - trySep(old, start, ".", pos/*ref*/, separator/*ref*/); - trySep(old, start, "->", pos/*ref*/, separator/*ref*/); + trySep(old, start, " ", pos /*ref*/, separator /*ref*/); + trySep(old, start, ".", pos /*ref*/, separator /*ref*/); + trySep(old, start, "->", pos /*ref*/, separator /*ref*/); if (pos == string::npos) break; - out += protectIf(old.substr(start, pos-start), true) + separator; + out += protectIf(old.substr(start, pos - start), true) + separator; start = pos + separator.length(); } out += protectIf(old.substr(start), true); return out; } void writeMapFile(const string& filename) const { - V3OutXmlFile of (filename); + V3OutXmlFile of(filename); of.putsHeader(); - of.puts("\n"); + of.puts("\n"); of.puts("\n"); { for (IdMap::const_iterator it = m_nameMap.begin(); it != m_nameMap.end(); ++it) { - of.puts("second+"\" to=\""+it->first+"\"/>\n"); + of.puts("second + "\" to=\"" + it->first + "\"/>\n"); } } of.puts("\n"); } + private: void trySep(const string& old, string::size_type start, const string& trySep, string::size_type& posr, string& separatorr) { diff --git a/src/V3File.h b/src/V3File.h index c5cb7fe2f..dcbb7672e 100644 --- a/src/V3File.h +++ b/src/V3File.h @@ -40,11 +40,11 @@ public: static std::ifstream* new_ifstream_nodepend(const string& filename) { return new std::ifstream(filename.c_str()); } - static std::ofstream* new_ofstream(const string& filename, bool append=false) { + static std::ofstream* new_ofstream(const string& filename, bool append = false) { addTgtDepend(filename); return new_ofstream_nodepend(filename, append); } - static std::ofstream* new_ofstream_nodepend(const string& filename, bool append=false) { + static std::ofstream* new_ofstream_nodepend(const string& filename, bool append = false) { createMakeDirFor(filename); if (append) { return new std::ofstream(filename.c_str(), std::ios::app); @@ -86,6 +86,7 @@ private: // CONSTRUCTORS VL_UNCOPYABLE(VInFilter); + public: explicit VInFilter(const string& command); ~VInFilter(); @@ -100,12 +101,9 @@ public: class V3OutFormatter { // TYPES - enum MiscConsts { - MAXSPACE = 80}; // After this indent, stop indenting more + enum MiscConsts { MAXSPACE = 80 }; // After this indent, stop indenting more public: - enum AlignClass { - AL_AUTO = 0, - AL_STATIC = 1}; + enum AlignClass { AL_AUTO = 0, AL_STATIC = 1 }; enum Language { LA_C = 0, LA_VERILOG = 1, @@ -115,17 +113,17 @@ public: private: // MEMBERS - string m_filename; - Language m_lang; // Indenting Verilog code - int m_blockIndent; // Characters per block indent - int m_commaWidth; // Width after which to break at ,'s - int m_lineno; - int m_column; - int m_nobreak; // Basic operator or begin paren, don't break next - bool m_prependIndent; - int m_indentLevel; // Current {} indentation + string m_filename; + Language m_lang; // Indenting Verilog code + int m_blockIndent; // Characters per block indent + int m_commaWidth; // Width after which to break at ,'s + int m_lineno; + int m_column; + int m_nobreak; // Basic operator or begin paren, don't break next + bool m_prependIndent; + int m_indentLevel; // Current {} indentation std::stack m_parenVec; // Stack of columns where last ( was - int m_bracketLevel; // Intenting = { block, indicates number of {'s seen. + int m_bracketLevel; // Intenting = { block, indicates number of {'s seen. int endLevels(const char* strg); void putcNoTracking(char chr); @@ -146,18 +144,26 @@ public: void putsQuoted(const string& strg); void putBreak(); // Print linebreak if line is too wide void putBreakExpr(); // Print linebreak in expression if line is too wide - void putbs(const char* strg) { putBreakExpr(); puts(strg); } - void putbs(const string& strg) { putBreakExpr(); puts(strg); } + void putbs(const char* strg) { + putBreakExpr(); + puts(strg); + } + void putbs(const string& strg) { + putBreakExpr(); + puts(strg); + } bool exceededWidth() const { return m_column > m_commaWidth; } bool tokenStart(const char* cp, const char* cmp); bool tokenEnd(const char* cp); void indentInc() { m_indentLevel += m_blockIndent; } void indentDec() { m_indentLevel -= m_blockIndent; - UASSERT(m_indentLevel>=0, ": "<= 0, ": " << m_filename << ": Underflow of indentation"); } void blockInc() { m_parenVec.push(m_indentLevel + m_blockIndent); } - void blockDec() { if (!m_parenVec.empty()) m_parenVec.pop(); } + void blockDec() { + if (!m_parenVec.empty()) m_parenVec.pop(); + } // STATIC METHODS static const string indentSpaces(int num); // Add escaped characters to strings @@ -172,11 +178,13 @@ public: class V3OutFile : public V3OutFormatter { // MEMBERS - FILE* m_fp; + FILE* m_fp; + public: V3OutFile(const string& filename, V3OutFormatter::Language lang); virtual ~V3OutFile(); void putsForceIncs(); + private: // CALLBACKS virtual void putcOutput(char chr) { fputc(chr, m_fp); } @@ -213,7 +221,8 @@ public: class V3OutScFile : public V3OutCFile { public: - explicit V3OutScFile(const string& filename) : V3OutCFile(filename) {} + explicit V3OutScFile(const string& filename) + : V3OutCFile(filename) {} virtual ~V3OutScFile() {} virtual void putsHeader() { puts("// Verilated -*- SystemC -*-\n"); } virtual void putsIntTopInclude() { @@ -262,9 +271,9 @@ public: // METHODS // Rename to a new encoded string (unless earlier passthru'ed) static string protect(const string& old) { return protectIf(old, true); } - static string protectIf(const string& old, bool doIt=true); + static string protectIf(const string& old, bool doIt = true); // Rename words to a new encoded string - static string protectWordsIf(const string& old, bool doIt=true); + static string protectWordsIf(const string& old, bool doIt = true); // Write map of renames to output file static void writeMapFile(const string& filename); }; diff --git a/src/V3FileLine.cpp b/src/V3FileLine.cpp index 85324f015..2fce3e34b 100644 --- a/src/V3FileLine.cpp +++ b/src/V3FileLine.cpp @@ -17,6 +17,7 @@ #include "config_build.h" #include "verilatedos.h" +// clang-format off #include "V3Error.h" #include "V3FileLine.h" #include "V3String.h" @@ -27,6 +28,7 @@ # include "V3Config.h" # include "V3File.h" #endif +// clang-format on #include #include @@ -39,11 +41,11 @@ const string FileLineSingleton::filenameLetters(int fileno) { const int size = 1 + (64 / 4); // Each letter retires more than 4 bits of a > 64 bit number char out[size]; - char* op = out+size-1; + char* op = out + size - 1; *--op = '\0'; // We build backwards int num = fileno; do { - *--op = 'a'+num%26; + *--op = 'a' + num % 26; num /= 26; } while (num); return op; @@ -70,13 +72,13 @@ int FileLineSingleton::nameToNumber(const string& filename) { //! Support XML output //! Experimental. Updated to also put out the language. void FileLineSingleton::fileNameNumMapDumpXml(std::ostream& os) { - os<<"\n"; + os << "\n"; for (FileNameNumMap::const_iterator it = m_namemap.begin(); it != m_namemap.end(); ++it) { - os<<"second) - <<"\" filename=\""<first, V3OutFormatter::LA_XML) - <<"\" language=\""<second).ascii()<<"\"/>\n"; + os << "second) << "\" filename=\"" + << V3OutFormatter::quoteNameControls(it->first, V3OutFormatter::LA_XML) + << "\" language=\"" << numberToLang(it->second).ascii() << "\"/>\n"; } - os<<"\n"; + os << "\n"; } //###################################################################### @@ -95,17 +97,18 @@ void VFileContent::pushText(const string& text) { } // Any leftover text is stored on largest line (might be "") - string leftover = m_lines.back() + text; m_lines.pop_back(); + string leftover = m_lines.back() + text; + m_lines.pop_back(); // Insert line-by-line string::size_type line_start = 0; while (true) { string::size_type line_end = leftover.find('\n', line_start); if (line_end != string::npos) { - string oneline (leftover, line_start, line_end-line_start+1); + string oneline(leftover, line_start, line_end - line_start + 1); m_lines.push_back(oneline); // Keeps newline - UINFO(9, "PushStream[ct"<= (int)m_lines.size())) { if (debug() || v3Global.opt.debugCheck()) { - return ("%Error-internal-contents-bad-ct"+cvtToStr(m_id) - +"-ln"+cvtToStr(lineno)); - } else return ""; + return ("%Error-internal-contents-bad-ct" + cvtToStr(m_id) + "-ln" + cvtToStr(lineno)); + } else { + return ""; + } } string text = m_lines[lineno]; - UINFO(9, "Get Stream[ct"<ascii(); + if (!contentp) { + os << "ct0"; + } else { + os << contentp->ascii(); + } return os; } @@ -149,7 +156,7 @@ FileLine::FileLine(FileLine::EmptySecret) { m_parent = NULL; m_warnOn = 0; - for (int codei=V3ErrorCode::EC_MIN; codei= 3) fail = true; @@ -219,7 +229,7 @@ void FileLine::lineDirective(const char* textp, int& enterExitRef) { v3error("`line was not properly formed with '`line number \"filename\" level'\n"); } - //printf ("PPLINE %d '%s'\n", s_lineno, s_filename.c_str()); + // printf ("PPLINE %d '%s'\n", s_lineno, s_filename.c_str()); } void FileLine::forwardToken(const char* textp, size_t size, bool trackLines) { @@ -254,50 +264,46 @@ FileLine* FileLine::copyOrSameFileLine() { const string FileLine::filebasename() const { string name = filename(); string::size_type pos; - if ((pos = name.rfind('/')) != string::npos) { - name.erase(0, pos+1); - } + if ((pos = name.rfind('/')) != string::npos) name.erase(0, pos + 1); return name; } const string FileLine::filebasenameNoExt() const { string name = filebasename(); string::size_type pos; - if ((pos = name.find('.')) != string::npos) { - name = name.substr(0, pos); - } + if ((pos = name.find('.')) != string::npos) name = name.substr(0, pos); return name; } const string FileLine::profileFuncname() const { // Return string that is OK as a function name - for profiling - string name = filebasenameNoExt(); + string name = filebasenameNoExt(); string::size_type pos; - while ((pos = name.find_first_not_of("abcdefghijlkmnopqrstuvwxyzABCDEFGHIJLKMNOPQRSTUVWXYZ0123456789_")) + while ((pos = name.find_first_not_of( + "abcdefghijlkmnopqrstuvwxyzABCDEFGHIJLKMNOPQRSTUVWXYZ0123456789_")) != string::npos) { name.replace(pos, 1, "_"); } - name += "__l"+cvtToStr(lastLineno()); + name += "__l" + cvtToStr(lastLineno()); return name; } string FileLine::asciiLineCol() const { - return (cvtToStr(firstLineno())+"-"+cvtToStr(lastLineno()) - +":"+cvtToStr(firstColumn())+"-"+cvtToStr(lastColumn()) - +"["+(m_contentp ? m_contentp->ascii() : "ct0") - +"+"+cvtToStr(m_contentLineno)+"]"); + return (cvtToStr(firstLineno()) + "-" + cvtToStr(lastLineno()) + ":" + cvtToStr(firstColumn()) + + "-" + cvtToStr(lastColumn()) + "[" + (m_contentp ? m_contentp->ascii() : "ct0") + "+" + + cvtToStr(m_contentLineno) + "]"); } string FileLine::ascii() const { // For most errors especially in the parser the lastLineno is more accurate than firstLineno return filename() + ":" + cvtToStr(lastLineno()) + ":" + cvtToStr(firstColumn()); } std::ostream& operator<<(std::ostream& os, FileLine* fileline) { - os <ascii()<<": "<ascii() << ": " << std::hex; + return (os); } bool FileLine::warnOff(const string& msg, bool flag) { - V3ErrorCode code (msg.c_str()); + V3ErrorCode code(msg.c_str()); if (code < V3ErrorCode::EC_FIRST_WARN) { return false; #ifndef _V3ERROR_NO_GLOBAL_ @@ -312,14 +318,14 @@ bool FileLine::warnOff(const string& msg, bool flag) { } void FileLine::warnLintOff(bool flag) { - for (int codei=V3ErrorCode::EC_MIN; codeiwarnIsOff(code)) { warnOff(code, true); } } @@ -345,31 +352,33 @@ void FileLine::modifyStateInherit(const FileLine* fromp) { void FileLine::v3errorEnd(std::ostringstream& sstr, const string& locationStr) { std::ostringstream nsstr; - if (lastLineno()) nsstr<= static_cast(lastColumn() - 1)) { string linestr = cvtToStr(firstLineno()); - while (linestr.size() < 5) - linestr = ' ' + linestr; + while (linestr.size() < 5) linestr = ' ' + linestr; out += linestr + " | " + sourceLine + "\n"; out += std::string(linestr.size(), ' ') + " | "; out += string((firstColumn() - 1), ' ') + '^'; @@ -458,7 +466,7 @@ void FileLine::deleteAllRemaining() { // only when leak checking we'll track them all and cleanup. while (true) { FileLineCheckSet::iterator it = fileLineLeakChecks.begin(); - if (it==fileLineLeakChecks.end()) break; + if (it == fileLineLeakChecks.end()) break; delete *it; // Operator delete will remove the iterated object from the list. // Eventually the list will be empty and terminate the loop. diff --git a/src/V3FileLine.h b/src/V3FileLine.h index de09fc0f1..d5d1833cd 100644 --- a/src/V3FileLine.h +++ b/src/V3FileLine.h @@ -39,22 +39,27 @@ class FileLine; //! source file (each with its own unique filename number). class FileLineSingleton { // TYPES - typedef std::map FileNameNumMap; - typedef std::map FileLangNumMap; + typedef std::map FileNameNumMap; + typedef std::map FileLangNumMap; // MEMBERS - FileNameNumMap m_namemap; // filenameno for each filename - std::deque m_names; // filename text for each filenameno + FileNameNumMap m_namemap; // filenameno for each filename + std::deque m_names; // filename text for each filenameno std::deque m_languages; // language for each filenameno // CONSTRUCTORS - FileLineSingleton() { } - ~FileLineSingleton() { } + FileLineSingleton() {} + ~FileLineSingleton() {} + protected: friend class FileLine; int nameToNumber(const string& filename); const string numberToName(int filenameno) const { return m_names[filenameno]; } const V3LangCode numberToLang(int filenameno) const { return m_languages[filenameno]; } void numberToLang(int filenameno, const V3LangCode& l) { m_languages[filenameno] = l; } - void clear() { m_namemap.clear(); m_names.clear(); m_languages.clear(); } + void clear() { + m_namemap.clear(); + m_names.clear(); + m_languages.clear(); + } void fileNameNumMapDumpXml(std::ostream& os); static const string filenameLetters(int fileno); }; @@ -65,12 +70,15 @@ class VFileContent { int m_id; // Content ID number std::deque m_lines; // Source text lines public: - VFileContent() { static int s_id = 0; m_id = ++s_id; } - ~VFileContent() { } + VFileContent() { + static int s_id = 0; + m_id = ++s_id; + } + ~VFileContent() {} // METHODS void pushText(const string& text); // Add arbitrary text (need not be line-by-line) string getLine(int lineno) const; - string ascii() const { return "ct"+cvtToStr(m_id); } + string ascii() const { return "ct" + cvtToStr(m_id); } static int debug(); }; std::ostream& operator<<(std::ostream& os, VFileContent* contentp); @@ -104,6 +112,7 @@ protected: friend class V3PreLex; friend class V3PreProcImp; friend class V3PreShellImp; + private: // CONSTRUCTORS static FileLineSingleton& singleton() { @@ -114,6 +123,7 @@ private: static FileLine* defFilelinep = new FileLine(FileLine::EmptySecret()); return *defFilelinep; } + public: explicit FileLine(const string& filename) : m_firstLineno(0) @@ -139,24 +149,33 @@ public: explicit FileLine(EmptySecret); FileLine* copyOrSameFileLine(); static void deleteAllRemaining(); - ~FileLine() { } + ~FileLine() {} #ifdef VL_LEAK_CHECKS static void* operator new(size_t size); static void operator delete(void* obj, size_t size); #endif // METHODS void newContent(); - void lineno(int num) { m_firstLineno = num; m_lastLineno = num; - m_firstColumn = m_lastColumn = 1; } + void lineno(int num) { + m_firstLineno = num; + m_lastLineno = num; + m_firstColumn = m_lastColumn = 1; + } void language(V3LangCode lang) { singleton().numberToLang(m_filenameno, lang); } void filename(const string& name) { m_filenameno = singleton().nameToNumber(name); } void parent(FileLine* fileline) { m_parent = fileline; } void lineDirective(const char* textp, int& enterExitRef); - void linenoInc() { m_lastLineno++; m_lastColumn = 1; m_contentLineno++; } - void startToken() { m_firstLineno = m_lastLineno; - m_firstColumn = m_lastColumn; } + void linenoInc() { + m_lastLineno++; + m_lastColumn = 1; + m_contentLineno++; + } + void startToken() { + m_firstLineno = m_lastLineno; + m_firstColumn = m_lastColumn; + } // Advance last line/column based on given text - void forwardToken(const char* textp, size_t size, bool trackLines=true); + void forwardToken(const char* textp, size_t size, bool trackLines = true); int firstLineno() const { return m_firstLineno; } int firstColumn() const { return m_firstColumn; } int lastLineno() const { return m_lastLineno; } @@ -172,13 +191,16 @@ public: string ascii() const; string asciiLineCol() const; const string filename() const { return singleton().numberToName(m_filenameno); } - bool filenameIsGlobal() const { return (filename() == commandLineFilename() - || filename() == builtInFilename()); } + bool filenameIsGlobal() const { + return (filename() == commandLineFilename() || filename() == builtInFilename()); + } const string filenameLetters() const { return singleton().filenameLetters(m_filenameno); } const string filebasename() const; const string filebasenameNoExt() const; const string profileFuncname() const; - const string xml() const { return "fl=\""+filenameLetters()+cvtToStr(lastLineno())+"\""; } + const string xml() const { + return "fl=\"" + filenameLetters() + cvtToStr(lastLineno()) + "\""; + } const string xmlDetailedLocation() const; string lineDirectiveStrg(int enterExit) const; @@ -202,16 +224,15 @@ public: // and match what GCC outputs static string commandLineFilename() { return ""; } static string builtInFilename() { return ""; } - static void globalWarnLintOff(bool flag) { - defaultFileLine().warnLintOff(flag); } - static void globalWarnStyleOff(bool flag) { - defaultFileLine().warnStyleOff(flag); } + static void globalWarnLintOff(bool flag) { defaultFileLine().warnLintOff(flag); } + static void globalWarnStyleOff(bool flag) { defaultFileLine().warnStyleOff(flag); } static void globalWarnOff(V3ErrorCode code, bool flag) { - defaultFileLine().warnOff(code, flag); } + defaultFileLine().warnOff(code, flag); + } static bool globalWarnOff(const string& code, bool flag) { - return defaultFileLine().warnOff(code, flag); } - static void fileNameNumMapDumpXml(std::ostream& os) { - singleton().fileNameNumMapDumpXml(os); } + return defaultFileLine().warnOff(code, flag); + } + static void fileNameNumMapDumpXml(std::ostream& os) { singleton().fileNameNumMapDumpXml(os); } // METHODS - Called from netlist // Merge warning disables from another fileline @@ -237,13 +258,11 @@ public: /// Simplified information vs warnContextPrimary() to make dump clearer string warnContextSecondary() const { return warnContext(true); } bool operator==(const FileLine& rhs) const { - return (m_firstLineno == rhs.m_firstLineno - && m_firstColumn == rhs.m_firstColumn - && m_lastLineno == rhs.m_lastLineno - && m_lastColumn == rhs.m_lastColumn - && m_filenameno == rhs.m_filenameno - && m_warnOn == rhs.m_warnOn); + return (m_firstLineno == rhs.m_firstLineno && m_firstColumn == rhs.m_firstColumn + && m_lastLineno == rhs.m_lastLineno && m_lastColumn == rhs.m_lastColumn + && m_filenameno == rhs.m_filenameno && m_warnOn == rhs.m_warnOn); } + private: void v3errorEndFatalGuts(std::ostringstream& str); string warnContext(bool secondary) const; @@ -251,7 +270,9 @@ private: std::ostream& operator<<(std::ostream& os, FileLine* fileline); inline void FileLine::v3errorEndFatal(std::ostringstream& str) { - v3errorEnd(str); assert(0); VL_UNREACHABLE + v3errorEnd(str); + assert(0); + VL_UNREACHABLE } #endif // Guard diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index 117145039..6f9128d94 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -42,7 +42,7 @@ typedef std::list GateVarRefList; -#define GATE_DEDUP_MAX_DEPTH 20 +#define GATE_DEDUP_MAX_DEPTH 20 //###################################################################### @@ -70,40 +70,43 @@ public: // Support classes class GateEitherVertex : public V3GraphVertex { - AstScope* m_scopep; // Scope vertex refers to - bool m_reducible; // True if this node should be able to be eliminated - bool m_dedupable; // True if this node should be able to be deduped - bool m_consumed; // Output goes to something meaningful + AstScope* m_scopep; // Scope vertex refers to + bool m_reducible; // True if this node should be able to be eliminated + bool m_dedupable; // True if this node should be able to be deduped + bool m_consumed; // Output goes to something meaningful public: GateEitherVertex(V3Graph* graphp, AstScope* scopep) - : V3GraphVertex(graphp), m_scopep(scopep), m_reducible(true) - , m_dedupable(true), m_consumed(false) {} + : V3GraphVertex(graphp) + , m_scopep(scopep) + , m_reducible(true) + , m_dedupable(true) + , m_consumed(false) {} virtual ~GateEitherVertex() {} // ACCESSORS - virtual string dotStyle() const { return m_consumed?"":"dotted"; } + virtual string dotStyle() const { return m_consumed ? "" : "dotted"; } AstScope* scopep() const { return m_scopep; } bool reducible() const { return m_reducible; } bool dedupable() const { return m_dedupable; } void setConsumed(const char* consumedReason) { m_consumed = true; - //UINFO(0,"\t\tSetConsumed "<inNextp()) { ret = dynamic_cast(edgep->fromp())->accept(v, vu); @@ -114,7 +117,7 @@ public: // Note: This behaves differently than iterateInEdges() in that it will traverse // all edges that exist when it is initially called, whereas // iterateInEdges() will stop traversing edges if one is deleted - VNUser iterateCurrentOutEdges(GateGraphBaseVisitor& v, VNUser vu=VNUser(0)) { + VNUser iterateCurrentOutEdges(GateGraphBaseVisitor& v, VNUser vu = VNUser(0)) { VNUser ret = VNUser(0); V3GraphEdge* next_edgep = NULL; for (V3GraphEdge* edgep = outBeginp(); edgep; edgep = next_edgep) { @@ -128,23 +131,30 @@ public: class GateVarVertex : public GateEitherVertex { AstVarScope* m_varScp; - bool m_isTop; - bool m_isClock; - AstNode* m_rstSyncNodep; // Used as reset and not in SenItem, in clocked always - AstNode* m_rstAsyncNodep; // Used as reset and in SenItem, in clocked always + bool m_isTop; + bool m_isClock; + AstNode* m_rstSyncNodep; // Used as reset and not in SenItem, in clocked always + AstNode* m_rstAsyncNodep; // Used as reset and in SenItem, in clocked always public: GateVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) - : GateEitherVertex(graphp, scopep), m_varScp(varScp), m_isTop(false) - , m_isClock(false), m_rstSyncNodep(NULL), m_rstAsyncNodep(NULL) {} + : GateEitherVertex(graphp, scopep) + , m_varScp(varScp) + , m_isTop(false) + , m_isClock(false) + , m_rstSyncNodep(NULL) + , m_rstAsyncNodep(NULL) {} virtual ~GateVarVertex() {} // ACCESSORS AstVarScope* varScp() const { return m_varScp; } - virtual string name() const { return (cvtToHex(m_varScp)+" "+varScp()->name()); } + virtual string name() const { return (cvtToHex(m_varScp) + " " + varScp()->name()); } virtual string dotColor() const { return "blue"; } bool isTop() const { return m_isTop; } void setIsTop() { m_isTop = true; } bool isClock() const { return m_isClock; } - void setIsClock() { m_isClock = true; setConsumed("isclk"); } + void setIsClock() { + m_isClock = true; + setConsumed("isclk"); + } AstNode* rstSyncNodep() const { return m_rstSyncNodep; } void rstSyncNodep(AstNode* nodep) { m_rstSyncNodep = nodep; } AstNode* rstAsyncNodep() const { return m_rstAsyncNodep; } @@ -158,26 +168,29 @@ public: setIsClock(); } } - VNUser accept(GateGraphBaseVisitor& v, VNUser vu=VNUser(0)) { return v.visit(this, vu); } + VNUser accept(GateGraphBaseVisitor& v, VNUser vu = VNUser(0)) { return v.visit(this, vu); } }; class GateLogicVertex : public GateEitherVertex { - AstNode* m_nodep; - AstActive* m_activep; // Under what active; NULL is ok (under cfunc or such) - bool m_slow; // In slow block + AstNode* m_nodep; + AstActive* m_activep; // Under what active; NULL is ok (under cfunc or such) + bool m_slow; // In slow block public: - GateLogicVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep, - AstActive* activep, bool slow) - : GateEitherVertex(graphp ,scopep), m_nodep(nodep), m_activep(activep), m_slow(slow) {} + GateLogicVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep, AstActive* activep, + bool slow) + : GateEitherVertex(graphp, scopep) + , m_nodep(nodep) + , m_activep(activep) + , m_slow(slow) {} virtual ~GateLogicVertex() {} // ACCESSORS - virtual string name() const { return (cvtToHex(m_nodep)+"@"+scopep()->prettyName()); } + virtual string name() const { return (cvtToHex(m_nodep) + "@" + scopep()->prettyName()); } virtual string dotColor() const { return "purple"; } virtual FileLine* fileline() const { return nodep()->fileline(); } AstNode* nodep() const { return m_nodep; } AstActive* activep() const { return m_activep; } - bool slow() const { return m_slow; } - VNUser accept(GateGraphBaseVisitor& v, VNUser vu=VNUser(0)) { return v.visit(this, vu); } + bool slow() const { return m_slow; } + VNUser accept(GateGraphBaseVisitor& v, VNUser vu = VNUser(0)) { return v.visit(this, vu); } }; //###################################################################### @@ -186,20 +199,20 @@ public: class GateOkVisitor : public GateBaseVisitor { private: // RETURN STATE - bool m_isSimple; // Set false when we know it isn't simple - GateVarRefList m_rhsVarRefs; // VarRefs on rhs of assignment - AstNode* m_substTreep; // What to replace the variable with + bool m_isSimple; // Set false when we know it isn't simple + GateVarRefList m_rhsVarRefs; // VarRefs on rhs of assignment + AstNode* m_substTreep; // What to replace the variable with // STATE - bool m_buffersOnly; // Set when we only allow simple buffering, no equations (for clocks) - AstNodeVarRef* m_lhsVarRef; // VarRef on lhs of assignment (what we're replacing) - bool m_dedupe; // Set when we use isGateDedupable instead of isGateOptimizable - int m_ops; // Operation count + bool m_buffersOnly; // Set when we only allow simple buffering, no equations (for clocks) + AstNodeVarRef* m_lhsVarRef; // VarRef on lhs of assignment (what we're replacing) + bool m_dedupe; // Set when we use isGateDedupable instead of isGateOptimizable + int m_ops; // Operation count // METHODS void clearSimple(const char* because) { if (m_isSimple) { m_isSimple = false; - UINFO(9, "Clear simple "<rhsp(), Not) && VN_IS(VN_CAST(nodep->rhsp(), Not)->lhsp(), VarRef) - && VN_CAST(VN_CAST(nodep->rhsp(), Not)->lhsp(), VarRef)->varp()->isUsedClock()) - )) { + && VN_CAST(VN_CAST(nodep->rhsp(), Not)->lhsp(), VarRef) + ->varp() + ->isUsedClock()))) { clearSimple("Not a buffer (goes to a clock)"); } } @@ -252,16 +266,14 @@ private: virtual void visit(AstNode* nodep) VL_OVERRIDE { // *** Special iterator if (!m_isSimple) return; // Fastpath - if (++m_ops > v3Global.opt.gateStmts()) { - clearSimple("--gate-stmts exceeded"); - } - if (!(m_dedupe ? nodep->isGateDedupable() : nodep->isGateOptimizable()) - || !nodep->isPure() - || nodep->isBrancher()) { - UINFO(5, "Non optimizable type: "< v3Global.opt.gateStmts()) { clearSimple("--gate-stmts exceeded"); } + if (!(m_dedupe ? nodep->isGateDedupable() : nodep->isGateOptimizable()) // + || !nodep->isPure() || nodep->isBrancher()) { + UINFO(5, "Non optimizable type: " << nodep << endl); clearSimple("Non optimizable type"); + } else { + iterateChildren(nodep); } - else iterateChildren(nodep); } public: @@ -276,26 +288,20 @@ public: // Iterate iterate(nodep); // Check results - if (!m_substTreep) { - clearSimple("No assignment found\n"); - } - for (GateVarRefList::const_iterator it = m_rhsVarRefs.begin(); - it != m_rhsVarRefs.end(); ++it) { + if (!m_substTreep) { clearSimple("No assignment found\n"); } + for (GateVarRefList::const_iterator it = m_rhsVarRefs.begin(); it != m_rhsVarRefs.end(); + ++it) { if (m_lhsVarRef && m_lhsVarRef->varScopep() == (*it)->varScopep()) { clearSimple("Circular logic\n"); // Oh my, we'll get a UNOPTFLAT much later. } } - if (debug()>=9 && !m_isSimple) { - nodep->dumpTree(cout, " gate!Ok: "); - } + if (debug() >= 9 && !m_isSimple) nodep->dumpTree(cout, " gate!Ok: "); } virtual ~GateOkVisitor() {} // PUBLIC METHODS bool isSimple() const { return m_isSimple; } AstNode* substTree() const { return m_substTreep; } - const GateVarRefList& rhsVarRefs() const { - return m_rhsVarRefs; - } + const GateVarRefList& rhsVarRefs() const { return m_rhsVarRefs; } }; //###################################################################### @@ -304,39 +310,41 @@ public: class GateVisitor : public GateBaseVisitor { private: // NODE STATE - //Entire netlist: + // Entire netlist: // AstVarScope::user1p -> GateVarVertex* for usage var, 0=not set yet // {statement}Node::user1p -> GateLogicVertex* for this statement // AstVarScope::user2 -> bool: Signal used in SenItem in *this* always statement // AstVar::user2 -> bool: Warned about SYNCASYNCNET // AstNodeVarRef::user2 -> bool: ConcatOffset visited - AstUser1InUse m_inuser1; - AstUser2InUse m_inuser2; + AstUser1InUse m_inuser1; + AstUser2InUse m_inuser2; // STATE - V3Graph m_graph; // Scoreboard of var usages/dependencies - GateLogicVertex* m_logicVertexp; // Current statement being tracked, NULL=ignored - AstScope* m_scopep; // Current scope being processed - AstNodeModule* m_modp; // Current module - AstActive* m_activep; // Current active - bool m_activeReducible; // Is activation block reducible? - bool m_inSenItem; // Underneath AstSenItem; any varrefs are clocks - bool m_inSlow; // Inside a slow structure - VDouble0 m_statSigs; // Statistic tracking - VDouble0 m_statRefs; // Statistic tracking - VDouble0 m_statDedupLogic; // Statistic tracking - VDouble0 m_statAssignMerged; // Statistic tracking + V3Graph m_graph; // Scoreboard of var usages/dependencies + GateLogicVertex* m_logicVertexp; // Current statement being tracked, NULL=ignored + AstScope* m_scopep; // Current scope being processed + AstNodeModule* m_modp; // Current module + AstActive* m_activep; // Current active + bool m_activeReducible; // Is activation block reducible? + bool m_inSenItem; // Underneath AstSenItem; any varrefs are clocks + bool m_inSlow; // Inside a slow structure + VDouble0 m_statSigs; // Statistic tracking + VDouble0 m_statRefs; // Statistic tracking + VDouble0 m_statDedupLogic; // Statistic tracking + VDouble0 m_statAssignMerged; // Statistic tracking // METHODS - void iterateNewStmt(AstNode* nodep, const char* nonReducibleReason, const char* consumeReason) { + void iterateNewStmt(AstNode* nodep, const char* nonReducibleReason, + const char* consumeReason) { if (m_scopep) { - UINFO(5," STMT "<clearReducibleAndDedupable(nonReducibleReason); } else if (!m_activeReducible) { - m_logicVertexp->clearReducible("Block Unreducible"); // Sequential logic is dedupable + // Sequential logic is dedupable + m_logicVertexp->clearReducible("Block Unreducible"); } if (consumeReason) m_logicVertexp->setConsumed(consumeReason); if (VN_IS(nodep, SenItem)) m_logicVertexp->setConsumed("senItem"); @@ -348,7 +356,7 @@ private: GateVarVertex* makeVarVertex(AstVarScope* varscp) { GateVarVertex* vertexp = reinterpret_cast(varscp->user1p()); if (!vertexp) { - UINFO(6,"New vertex "<user1p(vertexp); if (varscp->varp()->isSigPublic()) { @@ -362,7 +370,7 @@ private: vertexp->clearReducibleAndDedupable("isTop"); vertexp->setConsumed("isTop"); } - if (varscp->varp()->isUsedClock()) vertexp->setConsumed("clock"); + if (varscp->varp()->isUsedClock()) vertexp->setConsumed("clock"); } return vertexp; } @@ -382,15 +390,15 @@ private: // VISITORS virtual void visit(AstNetlist* nodep) VL_OVERRIDE { iterateChildren(nodep); - //if (debug()>6) m_graph.dump(); - if (debug()>6) m_graph.dumpDotFilePrefixed("gate_pre"); + // if (debug() > 6) m_graph.dump(); + if (debug() > 6) m_graph.dumpDotFilePrefixed("gate_pre"); warnSignals(); // Before loss of sync/async pointers // Decompose clock vectors -- need to do this before removing redundant edges decomposeClkVectors(); m_graph.removeRedundantEdgesSum(&V3GraphEdge::followAlwaysTrue); m_graph.dumpDotFilePrefixed("gate_simp"); // Find gate interconnect and optimize - m_graph.userClearVertices(); // vertex->user(): bool. True indicates we've set it as consumed + m_graph.userClearVertices(); // vertex->user(): bool. Indicates we've set it as consumed // Get rid of buffers first, optimizeSignals(false); // Then propagate more complicated equations @@ -421,7 +429,7 @@ private: m_modp = origModp; } virtual void visit(AstScope* nodep) VL_OVERRIDE { - UINFO(4," SCOPE "<hasClocked()); // Seq logic outputs aren't reducible m_activep = nodep; AstNode::user2ClearTree(); @@ -444,13 +452,12 @@ private: AstVarScope* varscp = nodep->varScopep(); UASSERT_OBJ(varscp, nodep, "Var didn't get varscoped in V3Scope.cpp"); GateVarVertex* vvertexp = makeVarVertex(varscp); - UINFO(5," VARREF to "<setIsClock(); // For SYNCASYNCNET varscp->user2(true); - } - else if (m_activep && m_activep->hasClocked() && !nodep->lvalue()) { + } else if (m_activep && m_activep->hasClocked() && !nodep->lvalue()) { if (varscp->user2()) { if (!vvertexp->rstAsyncNodep()) vvertexp->rstAsyncNodep(nodep); } else { @@ -467,7 +474,7 @@ private: } } virtual void visit(AstAlways* nodep) VL_OVERRIDE { - iterateNewStmt(nodep, (nodep->isJustOneBodyStmt()?NULL:"Multiple Stmts"), NULL); + iterateNewStmt(nodep, (nodep->isJustOneBodyStmt() ? NULL : "Multiple Stmts"), NULL); } virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE { bool lastslow = m_inSlow; @@ -497,13 +504,13 @@ private: virtual void visit(AstInitial* nodep) VL_OVERRIDE { bool lastslow = m_inSlow; m_inSlow = true; - iterateNewStmt(nodep, (nodep->isJustOneBodyStmt()?NULL:"Multiple Stmts"), NULL); + iterateNewStmt(nodep, (nodep->isJustOneBodyStmt() ? NULL : "Multiple Stmts"), NULL); m_inSlow = lastslow; } - virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { + virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { // iterateNewStmt(nodep, NULL, NULL); } - virtual void visit(AstAssignW* nodep) VL_OVERRIDE { + virtual void visit(AstAssignW* nodep) VL_OVERRIDE { // iterateNewStmt(nodep, NULL, NULL); } virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE { @@ -517,7 +524,7 @@ private: } virtual void visit(AstConcat* nodep) VL_OVERRIDE { UASSERT_OBJ(!(VN_IS(nodep->backp(), NodeAssign) - && VN_CAST(nodep->backp(), NodeAssign)->lhsp()==nodep), + && VN_CAST(nodep->backp(), NodeAssign)->lhsp() == nodep), nodep, "Concat on LHS of assignment; V3Const should have deleted it"); iterateChildren(nodep); } @@ -552,36 +559,36 @@ public: //---------------------------------------------------------------------- void GateVisitor::optimizeSignals(bool allowMultiIn) { - for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) { + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { if (GateVarVertex* vvertexp = dynamic_cast(itp)) { if (vvertexp->inEmpty()) { vvertexp->clearReducibleAndDedupable("inEmpty"); // Can't deal with no sources if (!vvertexp->isTop() // Ok if top inputs are driverless && !vvertexp->varScp()->varp()->valuep() && !vvertexp->varScp()->varp()->isSigPublic()) { - UINFO(4, "No drivers "<varScp()<varScp() << endl); if (false) { // If we warned here after constant propagation, what the user considered // reasonable logic may have disappeared. Issuing a warning would // thus be confusing. V3Undriven now handles this. - vvertexp->varScp()->varp()->v3warn - (UNDRIVEN, "Signal has no drivers: '" - <scopep()->prettyName()<<"." - <varScp()->varp()->prettyName()<<"'"); + vvertexp->varScp()->varp()->v3warn( + UNDRIVEN, "Signal has no drivers: '" + << vvertexp->scopep()->prettyName() << "." + << vvertexp->varScp()->varp()->prettyName() << "'"); } } - } - else if (!vvertexp->inSize1()) { - vvertexp->clearReducibleAndDedupable("size!1"); // Can't deal with more than one src + } else if (!vvertexp->inSize1()) { + // Can't deal with more than one src + vvertexp->clearReducibleAndDedupable("size!1"); } // Reduce it? if (!vvertexp->reducible()) { - UINFO(8, "SigNotRed "<name()<name() << endl); } else { - UINFO(8, "Sig "<name()< - (vvertexp->inBeginp()->fromp()); - UINFO(8, " From "<name()<name() << endl); + GateLogicVertex* logicVertexp + = dynamic_cast(vvertexp->inBeginp()->fromp()); + UINFO(8, " From " << logicVertexp->name() << endl); AstNode* logicp = logicVertexp->nodep(); if (logicVertexp->reducible()) { // Can we eliminate? @@ -593,8 +600,8 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) { if (!allowMultiIn) doit = false; // Doit if one input, or not used, or used only once, ignoring traces int n = 0; - for (V3GraphEdge* edgep = vvertexp->outBeginp(); - edgep; edgep = edgep->outNextp()) { + for (V3GraphEdge* edgep = vvertexp->outBeginp(); edgep; + edgep = edgep->outNextp()) { GateLogicVertex* consumeVertexp = dynamic_cast(edgep->top()); if (!consumeVertexp->slow()) { // Not tracing or other slow path junk @@ -602,7 +609,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) { n += edgep->weight(); } } - if (n>1) { + if (n > 1) { doit = false; break; } @@ -610,40 +617,39 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) { } // Process it if (!doit) { - if (allowMultiIn && (debug()>=9)) { - UINFO(9, "Not ok simp"<outBeginp() - <<" on"<<(vvertexp->outBeginp()?vvertexp->outBeginp()->outNextp():0) - <<" "<name() - <outBeginp(); - edgep; edgep = edgep->outNextp()) { + if (allowMultiIn && (debug() >= 9)) { + UINFO(9, "Not ok simp" << okVisitor.isSimple() << " mi" << multiInputs + << " ob" << vvertexp->outBeginp() << " on" + << (vvertexp->outBeginp() + ? vvertexp->outBeginp()->outNextp() + : 0) + << " " << vvertexp->name() << endl); + for (V3GraphEdge* edgep = vvertexp->outBeginp(); edgep; + edgep = edgep->outNextp()) { GateLogicVertex* consumeVertexp = dynamic_cast(edgep->top()); - UINFO(9, " edge "<nodep()<nodep() + << endl); } - for (V3GraphEdge* edgep = vvertexp->inBeginp(); - edgep; edgep = edgep->inNextp()) { + for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; + edgep = edgep->inNextp()) { GateLogicVertex* consumeVertexp = dynamic_cast(edgep->fromp()); - UINFO(9, " edge "<nodep()<nodep() << endl); } } - } - else { + } else { AstNode* substp = okVisitor.substTree(); - if (debug()>=5) logicp->dumpTree(cout, " elimVar: "); - if (debug()>=5) substp->dumpTree(cout, " subst: "); + if (debug() >= 5) logicp->dumpTree(cout, " elimVar: "); + if (debug() >= 5) substp->dumpTree(cout, " subst: "); ++m_statSigs; bool removedAllUsages = true; - for (V3GraphEdge* edgep = vvertexp->outBeginp(); - edgep; ) { + for (V3GraphEdge* edgep = vvertexp->outBeginp(); edgep;) { GateLogicVertex* consumeVertexp = dynamic_cast(edgep->top()); AstNode* consumerp = consumeVertexp->nodep(); - if (!elimLogicOkOutputs(consumeVertexp, okVisitor/*ref*/)) { + if (!elimLogicOkOutputs(consumeVertexp, okVisitor /*ref*/)) { // Cannot optimize this replacement removedAllUsages = false; edgep = edgep->outNextp(); @@ -655,7 +661,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) { for (GateVarRefList::const_iterator it = rhsVarRefs.begin(); it != rhsVarRefs.end(); ++it) { AstVarScope* newvarscp = (*it)->varScopep(); - UINFO(9," Point-to-new vertex "<varScopep(); varscopes.insert(vscp); } @@ -711,7 +716,7 @@ bool GateVisitor::elimLogicOkOutputs(GateLogicVertex* consumeVertexp, GateVarVertex* consVVertexp = dynamic_cast(edgep->top()); AstVarScope* vscp = consVVertexp->varScp(); if (varscopes.find(vscp) != varscopes.end()) { - UINFO(9," Block-unopt, insertion generates input vscp "<verticesNextp()) { + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { if (GateVarVertex* vvertexp = dynamic_cast(itp)) { // Take the Comments/assigns that were moved to the VarScope and change them to a // simple value assignment AstVarScope* vscp = vvertexp->varScp(); if (vscp->valuep() && !VN_IS(vscp->valuep(), NodeMath)) { - //if (debug()>9) vscp->dumpTree(cout, "-vscPre: "); + // if (debug() > 9) vscp->dumpTree(cout, "-vscPre: "); while (AstNode* delp = VN_CAST(vscp->valuep(), Comment)) { VL_DO_DANGLING(delp->unlinkFrBack()->deleteTree(), delp); } @@ -747,9 +752,8 @@ void GateVisitor::replaceAssigns() { delp->replaceWith(rhsp); VL_DO_DANGLING(delp->deleteTree(), delp); } - //if (debug()>9) {vscp->dumpTree(cout, "-vscDone: "); cout<valuep(), NodeMath) - || vscp->valuep()->nextp()) { + // if (debug() > 9) {vscp->dumpTree(cout, "-vscDone: "); cout<valuep(), NodeMath) || vscp->valuep()->nextp()) { vscp->dumpTree(std::cerr, "vscStrange: "); vscp->v3fatalSrc("Value of varscope not mathematical"); } @@ -763,12 +767,10 @@ void GateVisitor::replaceAssigns() { void GateVisitor::consumedMark() { // Propagate consumed signals backwards to all producers into a consumed node m_graph.userClearVertices(); - for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); - vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp; + vertexp = vertexp->verticesNextp()) { GateEitherVertex* evertexp = static_cast(vertexp); - if (!evertexp->user() && evertexp->consumed()) { - consumedMarkRecurse(evertexp); - } + if (!evertexp->user() && evertexp->consumed()) consumedMarkRecurse(evertexp); } } @@ -786,11 +788,11 @@ void GateVisitor::consumedMarkRecurse(GateEitherVertex* vertexp) { void GateVisitor::consumedMove() { // Remove unused logic (logic that doesn't hit a combo block or a display statement) // We need the "usually" block logic to do a better job at this - for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); - vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp; + vertexp = vertexp->verticesNextp()) { if (GateVarVertex* vvertexp = dynamic_cast(vertexp)) { if (!vvertexp->consumed() && !vvertexp->user()) { - UINFO(8, "Unconsumed "<varScp()<varScp() << endl); } } if (GateLogicVertex* lvertexp = dynamic_cast(vertexp)) { @@ -799,7 +801,7 @@ void GateVisitor::consumedMove() { if (!lvertexp->consumed() && oldactp) { // Eventually: Move the statement to a new active block // with "tracing-on" sensitivity - UINFO(8," Remove unconsumed "<unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); } @@ -811,7 +813,7 @@ void GateVisitor::consumedMove() { void GateVisitor::warnSignals() { AstNode::user2ClearTree(); - for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) { + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { if (GateVarVertex* vvertexp = dynamic_cast(itp)) { AstVarScope* vscp = vvertexp->varScp(); AstNode* sp = vvertexp->rstSyncNodep(); @@ -823,15 +825,15 @@ void GateVisitor::warnSignals() { // Instead we'll disable if any disabled if (!vscp->fileline()->warnIsOff(V3ErrorCode::SYNCASYNCNET) && !ap->fileline()->warnIsOff(V3ErrorCode::SYNCASYNCNET) - && !sp->fileline()->warnIsOff(V3ErrorCode::SYNCASYNCNET) - ) { + && !sp->fileline()->warnIsOff(V3ErrorCode::SYNCASYNCNET)) { vscp->varp()->user2(true); // Warn only once per signal - vscp->v3warn(SYNCASYNCNET, "Signal flopped as both synchronous and async: " - <prettyNameQ()<warnOther()<<"... Location of async usage"<warnContextPrimary()<warnOther()<<"... Location of sync usage"<warnContextSecondary()); + vscp->v3warn(SYNCASYNCNET, + "Signal flopped as both synchronous and async: " + << vscp->prettyNameQ() << endl + << ap->warnOther() << "... Location of async usage" << endl + << ap->warnContextPrimary() << endl + << sp->warnOther() << "... Location of sync usage" << endl + << sp->warnContextSecondary()); } } } @@ -847,10 +849,10 @@ class GateElimVisitor : public GateBaseVisitor { private: // NODE STATE // STATE - AstVarScope* m_elimVarScp; // Variable being eliminated - AstNode* m_replaceTreep; // What to replace the variable with - bool m_didReplace; // Did we do any replacements - GateDedupeVarVisitor* m_varVisp; // Callback to keep hash up to date + AstVarScope* m_elimVarScp; // Variable being eliminated + AstNode* m_replaceTreep; // What to replace the variable with + bool m_didReplace; // Did we do any replacements + GateDedupeVarVisitor* m_varVisp; // Callback to keep hash up to date // METHODS void hashReplace(AstNode* oldp, AstNode* newp); @@ -865,11 +867,10 @@ private: UASSERT_OBJ(!nodep->lvalue(), nodep, "Can't replace lvalue assignments with const var"); AstNode* substp = m_replaceTreep->cloneTree(false); - UASSERT_OBJ(!(VN_IS(nodep, NodeVarRef) - && VN_IS(substp, NodeVarRef) - && nodep->same(substp)), - // Prevent an infinite loop... - substp, "Replacing node with itself; perhaps circular logic?"); + UASSERT_OBJ( + !(VN_IS(nodep, NodeVarRef) && VN_IS(substp, NodeVarRef) && nodep->same(substp)), + // Prevent an infinite loop... + substp, "Replacing node with itself; perhaps circular logic?"); // Which fileline() to use? // If replacing with logic, an error/warning is likely to want to point to the logic // IE what we're replacing with. @@ -903,14 +904,14 @@ public: }; void GateVisitor::optimizeElimVar(AstVarScope* varscp, AstNode* substp, AstNode* consumerp) { - if (debug()>=5) consumerp->dumpTree(cout, " elimUsePre: "); - GateElimVisitor elimVisitor (consumerp, varscp, substp, NULL); + if (debug() >= 5) consumerp->dumpTree(cout, " elimUsePre: "); + GateElimVisitor elimVisitor(consumerp, varscp, substp, NULL); if (elimVisitor.didReplace()) { - if (debug()>=9) consumerp->dumpTree(cout, " elimUseCns: "); - //Caution: Can't let V3Const change our handle to consumerp, such as by + if (debug() >= 9) consumerp->dumpTree(cout, " elimUseCns: "); + // Caution: Can't let V3Const change our handle to consumerp, such as by // optimizing away this assignment, etc. consumerp = V3Const::constifyEdit(consumerp); - if (debug()>=5) consumerp->dumpTree(cout, " elimUseDne: "); + if (debug() >= 5) consumerp->dumpTree(cout, " elimUseDne: "); // Some previous input edges may have disappeared, perhaps all of them. // If we remove the edges we can further optimize // See e.g t_var_overzero.v. @@ -934,32 +935,29 @@ private: // Set to NULL if this assign's tree was later replaced // AstUser1InUse m_inuser1; (Allocated for use in GateVisitor) // AstUser2InUse m_inuser2; (Allocated for use in GateVisitor) - AstUser3InUse m_inuser3; + AstUser3InUse m_inuser3; // AstUser4InUse m_inuser4; (Allocated for use in V3Hashed) - AstUser5InUse m_inuser5; + AstUser5InUse m_inuser5; - V3Hashed m_hashed; // Hash, contains rhs of assigns - NodeSet m_nodeDeleteds; // Any node in this hash was deleted + V3Hashed m_hashed; // Hash, contains rhs of assigns + NodeSet m_nodeDeleteds; // Any node in this hash was deleted VL_DEBUG_FUNC; // Declare debug() void hash(AstNode* nodep) { // !NULL && the object is hashable - if (nodep && !nodep->sameHash().isIllegal()) { - m_hashed.hash(nodep); - } + if (nodep && !nodep->sameHash().isIllegal()) m_hashed.hash(nodep); } bool sameHash(AstNode* node1p, AstNode* node2p) { - return (node1p && node2p - && !node1p->sameHash().isIllegal() - && !node2p->sameHash().isIllegal() - && m_hashed.sameNodes(node1p, node2p)); + return (node1p && node2p && !node1p->sameHash().isIllegal() + && !node2p->sameHash().isIllegal() && m_hashed.sameNodes(node1p, node2p)); } bool same(AstNode* node1p, AstNode* node2p) { return node1p == node2p || sameHash(node1p, node2p); } + public: - GateDedupeHash() { } + GateDedupeHash() {} ~GateDedupeHash() { if (v3Global.opt.debugCheck()) check(); } @@ -968,7 +966,7 @@ public: // This might be a variable on the lhs of the duplicate tree, // or could be a rhs variable in a tree we're not replacing (or not yet anyways) void hashReplace(AstNode* oldp, AstNode* newp) { - UINFO(9,"replacing "<<(void*)oldp<<" with "<<(void*)newp<user3p(), node2p->user3p()) - && same(node1p->user5p(), node2p->user5p()) - && node1p->user2p()->type() == node2p->user2p()->type(); + return same(node1p->user3p(), node2p->user3p()) && same(node1p->user5p(), node2p->user5p()) + && node1p->user2p()->type() == node2p->user2p()->type(); } AstNodeAssign* hashAndFindDupe(AstNodeAssign* assignp, AstNode* extra1p, AstNode* extra2p) { // Legal for extra1p/2p to be NULL, we'll compare with other assigns with extras also NULL - AstNode *rhsp = assignp->rhsp(); + AstNode* rhsp = assignp->rhsp(); rhsp->user2p(assignp); rhsp->user3p(extra1p); rhsp->user5p(extra2p); @@ -1029,10 +1026,10 @@ public: if (!isReplaced(nodep)) { // This class won't break if activep isn't an active, or // ifVar isn't a var, but this is checking the caller's construction. - UASSERT_OBJ(!activep || (!VN_DELETED(activep) && VN_IS(activep, Active)), - nodep, "V3Hashed check failed, lost active pointer"); - UASSERT_OBJ(!condVarp || !VN_DELETED(condVarp), - nodep, "V3Hashed check failed, lost if pointer"); + UASSERT_OBJ(!activep || (!VN_DELETED(activep) && VN_IS(activep, Active)), nodep, + "V3Hashed check failed, lost active pointer"); + UASSERT_OBJ(!condVarp || !VN_DELETED(condVarp), nodep, + "V3Hashed check failed, lost if pointer"); } } } @@ -1054,11 +1051,11 @@ class GateDedupeVarVisitor : public GateBaseVisitor { // Any other ordering or node type, except for an AstComment, makes it not dedupable private: // STATE - GateDedupeHash m_ghash; // Hash used to find dupes of rhs of assign - AstNodeAssign* m_assignp; // Assign found for dedupe - AstNode* m_ifCondp; // IF condition that assign is under - bool m_always; // Assign is under an always - bool m_dedupable; // Determined the assign to be dedupable + GateDedupeHash m_ghash; // Hash used to find dupes of rhs of assign + AstNodeAssign* m_assignp; // Assign found for dedupe + AstNode* m_ifCondp; // IF condition that assign is under + bool m_always; // Assign is under an always + bool m_dedupable; // Determined the assign to be dedupable // VISITORS virtual void visit(AstNodeAssign* assignp) VL_OVERRIDE { @@ -1088,7 +1085,8 @@ private: // foo = ...; // or foo <= ...; virtual void visit(AstNodeIf* ifp) VL_OVERRIDE { if (m_dedupable) { - if (m_always && !m_ifCondp && !ifp->elsesp()) { //we're under an always, this is the first IF, and there's no else + if (m_always && !m_ifCondp && !ifp->elsesp()) { + // we're under an always, this is the first IF, and there's no else m_ifCondp = ifp->condp(); iterateAndNextNull(ifp->ifsp()); } else { @@ -1099,8 +1097,7 @@ private: virtual void visit(AstComment*) VL_OVERRIDE {} // NOP //-------------------- - // Default - virtual void visit(AstNode*) VL_OVERRIDE { + virtual void visit(AstNode*) VL_OVERRIDE { // m_dedupable = false; } @@ -1112,7 +1109,7 @@ public: m_always = false; m_dedupable = true; } - ~GateDedupeVarVisitor() { } + ~GateDedupeVarVisitor() {} // PUBLIC METHODS AstNodeVarRef* findDupe(AstNode* nodep, AstVarScope* consumerVarScopep, AstActive* activep) { m_assignp = NULL; @@ -1124,8 +1121,8 @@ public: AstNode* lhsp = m_assignp->lhsp(); // Possible todo, handle more complex lhs expressions if (AstNodeVarRef* lhsVarRefp = VN_CAST(lhsp, NodeVarRef)) { - UASSERT_OBJ(lhsVarRefp->varScopep() == consumerVarScopep, - consumerVarScopep, "Consumer doesn't match lhs of assign"); + UASSERT_OBJ(lhsVarRefp->varScopep() == consumerVarScopep, consumerVarScopep, + "Consumer doesn't match lhs of assign"); if (AstNodeAssign* dup = m_ghash.hashAndFindDupe(m_assignp, activep, m_ifCondp)) { return static_cast(dup->lhsp()); } @@ -1133,18 +1130,14 @@ public: } return NULL; } - void hashReplace(AstNode* oldp, AstNode* newp) { - m_ghash.hashReplace(oldp, newp); - } + void hashReplace(AstNode* oldp, AstNode* newp) { m_ghash.hashReplace(oldp, newp); } }; //###################################################################### void GateElimVisitor::hashReplace(AstNode* oldp, AstNode* newp) { - UINFO(9,"hashReplace "<<(void*)oldp<<" -> "<<(void*)newp<hashReplace(oldp, newp); - } + UINFO(9, "hashReplace " << (void*)oldp << " -> " << (void*)newp << endl); + if (m_varVisp) m_varVisp->hashReplace(oldp, newp); } //###################################################################### @@ -1155,46 +1148,52 @@ private: // NODE STATE // AstVarScope::user2p -> bool: already visited // AstUser2InUse m_inuser2; (Allocated for use in GateVisitor) - VDouble0 m_numDeduped; // Statistic tracking - GateDedupeVarVisitor m_varVisitor; // Looks for a dupe of the logic - int m_depth; // Iteration depth + VDouble0 m_numDeduped; // Statistic tracking + GateDedupeVarVisitor m_varVisitor; // Looks for a dupe of the logic + int m_depth; // Iteration depth virtual VNUser visit(GateVarVertex* vvertexp, VNUser) { // Check that we haven't been here before - if (m_depth > GATE_DEDUP_MAX_DEPTH) return VNUser(0); // Break loops; before user2 set so hit this vertex later + if (m_depth > GATE_DEDUP_MAX_DEPTH) + return VNUser(0); // Break loops; before user2 set so hit this vertex later if (vvertexp->varScp()->user2()) return VNUser(0); vvertexp->varScp()->user2(true); m_depth++; if (vvertexp->inSize1()) { - AstNodeVarRef* dupVarRefp = static_cast - (vvertexp->iterateInEdges(*this, VNUser(vvertexp)).toNodep()); + AstNodeVarRef* dupVarRefp = static_cast( + vvertexp->iterateInEdges(*this, VNUser(vvertexp)).toNodep()); if (dupVarRefp) { // visit(GateLogicVertex*...) returned match V3GraphEdge* edgep = vvertexp->inBeginp(); GateLogicVertex* lvertexp = static_cast(edgep->fromp()); UASSERT_OBJ(vvertexp->dedupable(), vvertexp->varScp(), - "GateLogicVertex* visit should have returned NULL if consumer var vertex is not dedupable."); + "GateLogicVertex* visit should have returned NULL " + "if consumer var vertex is not dedupable."); GateOkVisitor okVisitor(lvertexp->nodep(), false, true); if (okVisitor.isSimple()) { AstVarScope* dupVarScopep = dupVarRefp->varScopep(); GateVarVertex* dupVvertexp = reinterpret_cast(dupVarScopep->user1p()); - UINFO(4,"replacing " << vvertexp << " with " << dupVvertexp << endl); + UINFO(4, "replacing " << vvertexp << " with " << dupVvertexp << endl); ++m_numDeduped; // Replace all of this varvertex's consumers with dupVarRefp - for (V3GraphEdge* outedgep = vvertexp->outBeginp(); outedgep; ) { + for (V3GraphEdge* outedgep = vvertexp->outBeginp(); outedgep;) { GateLogicVertex* consumeVertexp = dynamic_cast(outedgep->top()); AstNode* consumerp = consumeVertexp->nodep(); m_graphp->dumpDotFilePrefixed("gate_preelim"); - UINFO(9, "elim src vtx"<nodep()<varScp()<nodep() << endl); + UINFO(9, + "elim cons vtx" << consumeVertexp << " node " << consumerp << endl); + UINFO(9, "elim var vtx " << vvertexp << " node " << vvertexp->varScp() + << endl); + UINFO(9, "replace with " << dupVarRefp << endl); if (lvertexp == consumeVertexp) { UINFO(9, "skipping as self-recirculates\n"); } else { - GateElimVisitor elimVisitor(consumerp, vvertexp->varScp(), dupVarRefp, &m_varVisitor); + GateElimVisitor elimVisitor(consumerp, vvertexp->varScp(), dupVarRefp, + &m_varVisitor); } outedgep = outedgep->relinkFromp(dupVvertexp); } @@ -1251,17 +1250,15 @@ void GateVisitor::dedupe() { AstNode::user2ClearTree(); GateDedupeGraphVisitor deduper(&m_graph); // Traverse starting from each of the clocks - UINFO(9,"Gate dedupe() clocks:\n"); - for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) { + UINFO(9, "Gate dedupe() clocks:\n"); + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { if (GateVarVertex* vvertexp = dynamic_cast(itp)) { - if (vvertexp->isClock()) { - deduper.dedupeTree(vvertexp); - } + if (vvertexp->isClock()) deduper.dedupeTree(vvertexp); } } // Traverse starting from each of the outputs - UINFO(9,"Gate dedupe() outputs:\n"); - for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) { + UINFO(9, "Gate dedupe() outputs:\n"); + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { if (GateVarVertex* vvertexp = dynamic_cast(itp)) { if (vvertexp->isTop() && vvertexp->varScp()->varp()->isWritable()) { deduper.dedupeTree(vvertexp); @@ -1271,7 +1268,6 @@ void GateVisitor::dedupe() { m_statDedupLogic += deduper.numDeduped(); } - //###################################################################### // Recurse through the graph, try to merge assigns @@ -1279,10 +1275,9 @@ class GateMergeAssignsGraphVisitor : public GateGraphBaseVisitor { private: // NODE STATE AstNodeAssign* m_assignp; - AstActive* m_activep; + AstActive* m_activep; GateLogicVertex* m_logicvp; - VDouble0 m_numMergedAssigns; // Statistic tracking - + VDouble0 m_numMergedAssigns; // Statistic tracking // assemble two Sel into one if possible AstSel* merge(AstSel* pre, AstSel* cur) { @@ -1296,22 +1291,24 @@ private: const AstConst* cstart = VN_CAST(cur->lsbp(), Const); const AstConst* cwidth = VN_CAST(cur->widthp(), Const); if (!pstart || !pwidth || !cstart || !cwidth) return NULL; // too complicated - if (cur->lsbConst()+cur->widthConst() == pre->lsbConst()) { + if (cur->lsbConst() + cur->widthConst() == pre->lsbConst()) { return new AstSel(curVarRefp->fileline(), curVarRefp->cloneTree(false), - cur->lsbConst(), pre->widthConst()+cur->widthConst()); - } else return NULL; + cur->lsbConst(), pre->widthConst() + cur->widthConst()); + } else { + return NULL; + } } - virtual VNUser visit(GateVarVertex *vvertexp, VNUser) { - for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; ) { + virtual VNUser visit(GateVarVertex* vvertexp, VNUser) { + for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep;) { V3GraphEdge* oldedgep = edgep; edgep = edgep->inNextp(); // for recursive since the edge could be deleted if (GateLogicVertex* lvertexp = dynamic_cast(oldedgep->fromp())) { if (AstNodeAssign* assignp = VN_CAST(lvertexp->nodep(), NodeAssign)) { - //if (lvertexp->outSize1() && VN_IS(assignp->lhsp(), Sel)) { + // if (lvertexp->outSize1() && VN_IS(assignp->lhsp(), Sel)) { if (VN_IS(assignp->lhsp(), Sel) && lvertexp->outSize1()) { UINFO(9, "assing to the nodep[" - <lhsp(), Sel)->lsbConst()<<"]"<lhsp(), Sel)->lsbConst() << "]" << endl); // first assign with Sel-lhs if (!m_activep) m_activep = lvertexp->activep(); if (!m_logicvp) m_logicvp = lvertexp; @@ -1330,28 +1327,29 @@ private: if (!preselp || !curselp) continue; if (AstSel* newselp = merge(preselp, curselp)) { - UINFO(5, "assemble to new sel: "<replaceWith(newselp); VL_DO_DANGLING(preselp->deleteTree(), preselp); // create new rhs for pre assignment - AstNode* newrhsp = new AstConcat( - m_assignp->rhsp()->fileline(), m_assignp->rhsp()->cloneTree(false), - assignp->rhsp()->cloneTree(false)); + AstNode* newrhsp = new AstConcat(m_assignp->rhsp()->fileline(), + m_assignp->rhsp()->cloneTree(false), + assignp->rhsp()->cloneTree(false)); AstNode* oldrhsp = m_assignp->rhsp(); oldrhsp->replaceWith(newrhsp); VL_DO_DANGLING(oldrhsp->deleteTree(), oldrhsp); - m_assignp->dtypeChgWidthSigned(m_assignp->width()+assignp->width(), - m_assignp->width()+assignp->width(), + m_assignp->dtypeChgWidthSigned(m_assignp->width() + assignp->width(), + m_assignp->width() + assignp->width(), AstNumeric::SIGNED); // don't need to delete, will be handled - //assignp->unlinkFrBack(); VL_DO_DANGLING(assignp->deleteTree(), assignp); + // assignp->unlinkFrBack(); VL_DO_DANGLING(assignp->deleteTree(), + // assignp); // update the graph { // delete all inedges to lvertexp if (!lvertexp->inEmpty()) { - for (V3GraphEdge* ledgep = lvertexp->inBeginp(); ledgep; ) { + for (V3GraphEdge* ledgep = lvertexp->inBeginp(); ledgep;) { V3GraphEdge* oedgep = ledgep; ledgep = ledgep->inNextp(); GateEitherVertex* fromvp @@ -1374,8 +1372,7 @@ private: } return VNUser(0); } - - virtual VNUser visit(GateLogicVertex* lvertexp, VNUser vu) { + virtual VNUser visit(GateLogicVertex* lvertexp, VNUser vu) { // return VNUser(0); } @@ -1388,19 +1385,16 @@ public: m_numMergedAssigns = 0; m_graphp = graphp; } - void mergeAssignsTree(GateVarVertex* vvertexp) { - vvertexp->accept(*this); - } + void mergeAssignsTree(GateVarVertex* vvertexp) { vvertexp->accept(*this); } VDouble0 numMergedAssigns() { return m_numMergedAssigns; } }; - //---------------------------------------------------------------------- void GateVisitor::mergeAssigns() { UINFO(6, "mergeAssigns\n"); GateMergeAssignsGraphVisitor merger(&m_graph); - for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) { + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { if (GateVarVertex* vvertexp = dynamic_cast(itp)) { merger.mergeAssignsTree(vvertexp); } @@ -1414,26 +1408,26 @@ void GateVisitor::mergeAssigns() { class GateConcatVisitor : public GateBaseVisitor { private: // STATE - AstVarScope* m_vscp; // Varscope we're trying to find - int m_offset; // Current offset of varscope - int m_found_offset; // Found offset of varscope - bool m_found; // Offset found + AstVarScope* m_vscp; // Varscope we're trying to find + int m_offset; // Current offset of varscope + int m_found_offset; // Found offset of varscope + bool m_found; // Offset found // VISITORS virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE { - UINFO(9,"CLK DECOMP Concat search var (off = "<varScopep() == m_vscp && !nodep->user2() && !m_found) { // A concatenation may use the same var multiple times // But the graph will initially have an edge per instance nodep->user2(true); m_found_offset = m_offset; m_found = true; - UINFO(9,"CLK DECOMP Concat found var (off = "<dtypep()->width(); } virtual void visit(AstConcat* nodep) VL_OVERRIDE { - UINFO(9,"CLK DECOMP Concat search (off = "<rhsp()); iterate(nodep->lhsp()); } @@ -1456,8 +1450,9 @@ public: m_found = false; // Iterate iterate(concatp); - UINFO(9,"CLK DECOMP Concat Offset (found = "< bool: already visited - int m_seen_clk_vectors; - AstVarScope* m_clk_vsp; - GateVarVertex* m_clk_vvertexp; - GateConcatVisitor m_concat_visitor; - int m_total_seen_clk_vectors; - int m_total_decomposed_clk_vectors; + int m_seen_clk_vectors; + AstVarScope* m_clk_vsp; + GateVarVertex* m_clk_vvertexp; + GateConcatVisitor m_concat_visitor; + int m_total_seen_clk_vectors; + int m_total_decomposed_clk_vectors; virtual VNUser visit(GateVarVertex* vvertexp, VNUser vu) { // Check that we haven't been here before AstVarScope* vsp = vvertexp->varScp(); if (vsp->user2SetOnce()) return VNUser(0); - UINFO(9,"CLK DECOMP Var - "<varp()->width() > 1) { m_seen_clk_vectors++; m_total_seen_clk_vectors++; @@ -1500,9 +1495,7 @@ private: GateClkDecompState* currState = reinterpret_cast(vu.c()); GateClkDecompState nextState(currState->m_offset, vsp); vvertexp->iterateCurrentOutEdges(*this, VNUser(&nextState)); - if (vsp->varp()->width() > 1) { - m_seen_clk_vectors--; - } + if (vsp->varp()->width() > 1) --m_seen_clk_vectors; vsp->user2(false); return VNUser(0); } @@ -1511,14 +1504,14 @@ private: GateClkDecompState* currState = reinterpret_cast(vu.c()); int clk_offset = currState->m_offset; if (const AstAssignW* assignp = VN_CAST(lvertexp->nodep(), AssignW)) { - UINFO(9,"CLK DECOMP Logic (off = "<rhsp(), Sel)) { if (VN_IS(rselp->lsbp(), Const) && VN_IS(rselp->widthp(), Const)) { if (clk_offset < rselp->lsbConst() || clk_offset > rselp->msbConst()) { - UINFO(9,"CLK DECOMP Sel [ "<msbConst() - <<" : "<lsbConst()<<" ] dropped clock (" - <msbConst() << " : " + << rselp->lsbConst() << " ] dropped clock (" + << clk_offset << ")" << endl); return VNUser(0); } clk_offset -= rselp->lsbConst(); @@ -1526,7 +1519,7 @@ private: return VNUser(0); } } else if (AstConcat* catp = VN_CAST(assignp->rhsp(), Concat)) { - UINFO(9,"CLK DECOMP Concat searching - "<lhsp()<lhsp() << endl); int concat_offset; if (!m_concat_visitor.concatOffset(catp, currState->m_last_vsp, concat_offset)) { return VNUser(0); @@ -1542,13 +1535,14 @@ private: } else if (const AstVarRef* vrp = VN_CAST(assignp->lhsp(), VarRef)) { if (vrp->dtypep()->width() == 1 && m_seen_clk_vectors) { if (clk_offset != 0) { - UINFO(9,"Should only make it here with clk_offset = 0"<lhsp()<<" <-> "<lhsp() << " <-> " << m_clk_vsp + << endl); AstNode* rhsp = assignp->rhsp(); rhsp->replaceWith(new AstVarRef(rhsp->fileline(), m_clk_vsp, false)); - for (V3GraphEdge* edgep = lvertexp->inBeginp(); edgep; ) { + for (V3GraphEdge* edgep = lvertexp->inBeginp(); edgep;) { VL_DO_DANGLING(edgep->unlinkDelete(), edgep); } new V3GraphEdge(m_graphp, m_clk_vvertexp, lvertexp, 1); @@ -1572,10 +1566,11 @@ public: } virtual ~GateClkDecompGraphVisitor() { V3Stats::addStat("Optimizations, Clocker seen vectors", m_total_seen_clk_vectors); - V3Stats::addStat("Optimizations, Clocker decomposed vectors", m_total_decomposed_clk_vectors); + V3Stats::addStat("Optimizations, Clocker decomposed vectors", + m_total_decomposed_clk_vectors); } void clkDecomp(GateVarVertex* vvertexp) { - UINFO(9,"CLK DECOMP Starting Var - "<varScp(); m_clk_vvertexp = vvertexp; @@ -1585,17 +1580,17 @@ public: }; void GateVisitor::decomposeClkVectors() { - UINFO(9,"Starting clock decomposition"<verticesNextp()) { + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { if (GateVarVertex* vertp = dynamic_cast(itp)) { AstVarScope* vsp = vertp->varScp(); if (vsp->varp()->attrClocker() == VVarAttrClocker::CLOCKER_YES) { if (vsp->varp()->width() > 1) { - UINFO(9,"Clocker > 1 bit, not decomposing: "< 1 bit, not decomposing: " << vsp << endl); } else { - UINFO(9,"CLK DECOMP - "<valuep(), NodeAssign)) { - UINFO(5," Removeassign "<rhsp(); valuep->unlinkFrBack(); assp->replaceWith(valuep); @@ -1626,9 +1620,7 @@ private: public: // CONSTRUCTORS - explicit GateDeassignVisitor(AstNode* nodep) { - iterate(nodep); - } + explicit GateDeassignVisitor(AstNode* nodep) { iterate(nodep); } virtual ~GateDeassignVisitor() {} }; @@ -1636,10 +1628,10 @@ public: // Gate class functions void V3Gate::gateAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3GenClk.cpp b/src/V3GenClk.cpp index 8d7d53614..5cef03170 100644 --- a/src/V3GenClk.cpp +++ b/src/V3GenClk.cpp @@ -45,13 +45,13 @@ private: // Cleared on top scope // AstVarScope::user2() -> AstVarScope*. Signal replacing activation with // AstVarRef::user3() -> bool. Signal is replaced activation (already done) - AstUser2InUse m_inuser2; - AstUser3InUse m_inuser3; + AstUser2InUse m_inuser2; + AstUser3InUse m_inuser3; // STATE - AstActive* m_activep; // Inside activate statement - AstNodeModule* m_topModp; // Top module - AstScope* m_scopetopp; // Scope under TOPSCOPE + AstActive* m_activep; // Inside activate statement + AstNodeModule* m_topModp; // Top module + AstScope* m_scopetopp; // Scope under TOPSCOPE // METHODS AstVarScope* genInpClk(AstVarScope* vscp) { @@ -59,18 +59,19 @@ private: return VN_CAST(vscp->user2p(), VarScope); } else { AstVar* varp = vscp->varp(); - string newvarname = "__VinpClk__"+vscp->scopep()->nameDotless()+"__"+varp->name(); + string newvarname + = "__VinpClk__" + vscp->scopep()->nameDotless() + "__" + varp->name(); // Create: VARREF(inpclk) // ... // ASSIGN(VARREF(inpclk), VARREF(var)) - AstVar* newvarp = new AstVar(varp->fileline(), - AstVarType::MODULETEMP, newvarname, varp); + AstVar* newvarp + = new AstVar(varp->fileline(), AstVarType::MODULETEMP, newvarname, varp); m_topModp->addStmtp(newvarp); AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopetopp, newvarp); m_scopetopp->addVarp(newvscp); - AstAssign* asninitp = new AstAssign(vscp->fileline(), - new AstVarRef(vscp->fileline(), newvscp, true), - new AstVarRef(vscp->fileline(), vscp, false)); + AstAssign* asninitp + = new AstAssign(vscp->fileline(), new AstVarRef(vscp->fileline(), newvscp, true), + new AstVarRef(vscp->fileline(), vscp, false)); m_scopetopp->addFinalClkp(asninitp); // vscp->user2p(newvscp); @@ -96,7 +97,7 @@ private: if (m_activep && !nodep->user3()) { nodep->user3(true); if (vscp->isCircular()) { - UINFO(8," VarActReplace "<fileline(), newvscp, nodep->lvalue()); @@ -112,9 +113,7 @@ private: m_activep = NULL; iterateChildren(nodep); } - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { - iterateChildren(nodep); - } + virtual void visit(AstCFunc* nodep) VL_OVERRIDE { iterateChildren(nodep); } //----- virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } @@ -138,13 +137,13 @@ private: // NODE STATE // Cleared on top scope // AstVarScope::user() -> bool. Set when the var has been used as clock - AstUser1InUse m_inuser1; + AstUser1InUse m_inuser1; // STATE - AstActive* m_activep; // Inside activate statement - bool m_tracingCall; // Iterating into a call to a cfunc - AstNodeAssign* m_assignp; // Inside assigndly statement - AstNodeModule* m_topModp; // Top module + AstActive* m_activep; // Inside activate statement + bool m_tracingCall; // Iterating into a call to a cfunc + AstNodeAssign* m_assignp; // Inside assigndly statement + AstNodeModule* m_topModp; // Top module // VISITORS virtual void visit(AstTopScope* nodep) VL_OVERRIDE { @@ -153,7 +152,7 @@ private: { // Make the new clock signals and replace any activate references // See rename, it does some AstNode::userClearTree()'s - GenClkRenameVisitor visitor (nodep, m_topModp); + GenClkRenameVisitor visitor(nodep, m_topModp); } } virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { @@ -188,24 +187,24 @@ private: AstVarScope* vscp = nodep->varScopep(); UASSERT_OBJ(vscp, nodep, "Scope not assigned"); if (m_activep) { - UINFO(8," VarAct "<user1(true); } if (m_assignp && nodep->lvalue() && vscp->user1()) { // Variable was previously used as a clock, and is now being set // Thus a unordered generated clock... - UINFO(8," VarSetAct "<circular(true); } } virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { - //UINFO(8,"ASS "<sensesp(), nodep, "Unlinked"); iterateChildren(nodep->sensesp()); // iterateAndNext? @@ -233,9 +232,7 @@ public: // GenClk class functions void V3GenClk::genClkAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Graph.cpp b/src/V3Graph.cpp index 108acd9ca..fc2cc08f5 100644 --- a/src/V3Graph.cpp +++ b/src/V3Graph.cpp @@ -34,13 +34,17 @@ int V3Graph::debug() { return std::max(V3Error::debugDefault(), s_debug); } // Vertices V3GraphVertex::V3GraphVertex(V3Graph* graphp, const V3GraphVertex& old) - : m_fanout(old.m_fanout), m_color(old.m_color), m_rank(old.m_rank) { + : m_fanout(old.m_fanout) + , m_color(old.m_color) + , m_rank(old.m_rank) { m_userp = NULL; verticesPushBack(graphp); } V3GraphVertex::V3GraphVertex(V3Graph* graphp) - : m_fanout(0), m_color(0), m_rank(0) { + : m_fanout(0) + , m_color(0) + , m_rank(0) { m_userp = NULL; verticesPushBack(graphp); } @@ -68,13 +72,13 @@ void V3GraphVertex::unlinkDelete(V3Graph* graphp) { // Unlink from vertex list m_vertices.unlink(graphp->m_vertices, this); // Delete - delete this; //this=NULL; + delete this; // this=NULL; } void V3GraphVertex::rerouteEdges(V3Graph* graphp) { // Make new edges for each from/to pair - for (V3GraphEdge* iedgep = inBeginp(); iedgep; iedgep=iedgep->inNextp()) { - for (V3GraphEdge* oedgep = outBeginp(); oedgep; oedgep=oedgep->outNextp()) { + for (V3GraphEdge* iedgep = inBeginp(); iedgep; iedgep = iedgep->inNextp()) { + for (V3GraphEdge* oedgep = outBeginp(); oedgep; oedgep = oedgep->outNextp()) { new V3GraphEdge(graphp, iedgep->fromp(), oedgep->top(), std::min(iedgep->weight(), oedgep->weight()), iedgep->cutable() && oedgep->cutable()); @@ -84,13 +88,8 @@ void V3GraphVertex::rerouteEdges(V3Graph* graphp) { unlinkEdges(graphp); } -bool V3GraphVertex::inSize1() const { - return !inEmpty() && inBeginp()->inNextp()==NULL; -} - -bool V3GraphVertex::outSize1() const { - return !outEmpty() && outBeginp()->outNextp()==NULL; -} +bool V3GraphVertex::inSize1() const { return !inEmpty() && !inBeginp()->inNextp(); } +bool V3GraphVertex::outSize1() const { return !outEmpty() && !outBeginp()->outNextp(); } uint32_t V3GraphVertex::inHash() const { // We want the same hash ignoring the order of edges. @@ -98,7 +97,7 @@ uint32_t V3GraphVertex::inHash() const { // However with XOR multiple edges to the same source will cancel out, // so we use ADD. (Generally call this only after removing duplicates though) uint32_t hash = 0; - for (V3GraphEdge* edgep = this->inBeginp(); edgep; edgep=edgep->inNextp()) { + for (V3GraphEdge* edgep = this->inBeginp(); edgep; edgep = edgep->inNextp()) { hash += cvtToHash(edgep->fromp()); } return hash; @@ -106,14 +105,13 @@ uint32_t V3GraphVertex::inHash() const { uint32_t V3GraphVertex::outHash() const { uint32_t hash = 0; - for (V3GraphEdge* edgep = this->outBeginp(); edgep; edgep=edgep->outNextp()) { + for (V3GraphEdge* edgep = this->outBeginp(); edgep; edgep = edgep->outNextp()) { hash += cvtToHash(edgep->top()); } return hash; } -V3GraphEdge* V3GraphVertex::findConnectingEdgep(GraphWay way, - const V3GraphVertex* waywardp) { +V3GraphEdge* V3GraphVertex::findConnectingEdgep(GraphWay way, const V3GraphVertex* waywardp) { // O(edges) linear search. Searches search both nodes' edge lists in // parallel. The lists probably aren't _both_ huge, so this is // unlikely to blow up even on fairly nasty graphs. @@ -131,10 +129,10 @@ V3GraphEdge* V3GraphVertex::findConnectingEdgep(GraphWay way, void V3GraphVertex::v3errorEnd(std::ostringstream& str) const { std::ostringstream nsstr; - nsstr<rank(); - if (vertexp->fanout()!=0.0) os<<" f"<fanout(); - if (vertexp->color()) os<<" c"<color(); + os << " VERTEX=" << vertexp->name(); + if (vertexp->rank()) os << " r" << vertexp->rank(); + if (vertexp->fanout() != 0.0) os << " f" << vertexp->fanout(); + if (vertexp->color()) os << " c" << vertexp->color(); return os; } @@ -158,8 +158,7 @@ std::ostream& operator<<(std::ostream& os, V3GraphVertex* vertexp) { //###################################################################### // Edges -void V3GraphEdge::init(V3Graph* graphp, - V3GraphVertex* fromp, V3GraphVertex* top, int weight, +void V3GraphEdge::init(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight, bool cutable) { UASSERT(fromp, "Null from pointer"); UASSERT(top, "Null to pointer"); @@ -174,7 +173,7 @@ void V3GraphEdge::init(V3Graph* graphp, } V3GraphEdge* V3GraphEdge::relinkFromp(V3GraphVertex* newFromp) { - V3GraphEdge *oldNxt = outNextp(); + V3GraphEdge* oldNxt = outNextp(); m_outs.unlink(m_fromp->m_outs, this); m_fromp = newFromp; outPushBack(); @@ -187,7 +186,7 @@ void V3GraphEdge::unlinkDelete() { // Unlink to side m_ins.unlink(m_top->m_ins, this); // Delete - delete this; //this=NULL; + delete this; // this=NULL; } void V3GraphEdge::outPushBack() { @@ -210,14 +209,12 @@ V3Graph::V3Graph() { verticesUnlink(); } -V3Graph::~V3Graph() { - clear(); -} +V3Graph::~V3Graph() { clear(); } void V3Graph::clear() { // Empty it of all points, as if making a new object // Delete the old edges - for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) { for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; /*BELOW*/) { V3GraphEdge* nextp = edgep->outNextp(); VL_DO_DANGLING(delete edgep, edgep); @@ -241,7 +238,7 @@ void V3Graph::userClearVertices() { // the graph pointer given a vertex.) For now we don't call this often, and // the extra code on each read of user() would probably slow things // down more than help. - for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) { vertexp->user(0); vertexp->userp(NULL); // Its a union, but might be different size than user() } @@ -249,8 +246,8 @@ void V3Graph::userClearVertices() { void V3Graph::userClearEdges() { // Clear user() in all of tree - for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { - for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { + for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) { + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { edgep->user(0); edgep->userp(NULL); // Its a union, but might be different size than user() } @@ -259,7 +256,7 @@ void V3Graph::userClearEdges() { void V3Graph::clearColors() { // Reset colors - for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) { vertexp->m_color = 0; } } @@ -268,72 +265,70 @@ void V3Graph::clearColors() { // Dumping void V3Graph::loopsMessageCb(V3GraphVertex* vertexp) { - vertexp->v3fatalSrc("Loops detected in graph: "<v3fatalSrc("Loops detected in graph: " << vertexp); } void V3Graph::loopsVertexCb(V3GraphVertex* vertexp) { // Needed here as V3GraphVertex<< isn't defined until later in header - if (debug()) std::cerr<<"-Info-Loop: "<verticesNextp()) { - os<<"\tNode: "<name(); - if (vertexp->color()) os<<" color="<color(); - os<verticesNextp()) { + os << "\tNode: " << vertexp->name(); + if (vertexp->color()) os << " color=" << vertexp->color(); + os << endl; // Print edges - for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep=edgep->inNextp()) { + for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { dumpEdge(os, vertexp, edgep); } - for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { dumpEdge(os, vertexp, edgep); } } } void V3Graph::dumpEdge(std::ostream& os, V3GraphVertex* vertexp, V3GraphEdge* edgep) { - if (edgep->weight() - && (edgep->fromp() == vertexp - || edgep->top() == vertexp)) { - os<<"\t\t"; - if (edgep->fromp() == vertexp) os << "-> "<top()->name(); - if (edgep->top() == vertexp) os << "<- "<fromp()->name(); - if (edgep->cutable()) os<<" [CUTABLE]"; - os<weight() && (edgep->fromp() == vertexp || edgep->top() == vertexp)) { + os << "\t\t"; + if (edgep->fromp() == vertexp) os << "-> " << edgep->top()->name(); + if (edgep->top() == vertexp) os << "<- " << edgep->fromp()->name(); + if (edgep->cutable()) os << " [CUTABLE]"; + os << endl; } } void V3Graph::dumpDotFilePrefixed(const string& nameComment, bool colorAsSubgraph) const { if (v3Global.opt.dumpTree()) { - dumpDotFile(v3Global.debugFilename(nameComment)+".dot", colorAsSubgraph); + dumpDotFile(v3Global.debugFilename(nameComment) + ".dot", colorAsSubgraph); } } //! Variant of dumpDotFilePrefixed without --dump option check void V3Graph::dumpDotFilePrefixedAlways(const string& nameComment, bool colorAsSubgraph) const { - dumpDotFile(v3Global.debugFilename(nameComment)+".dot", colorAsSubgraph); + dumpDotFile(v3Global.debugFilename(nameComment) + ".dot", colorAsSubgraph); } void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) const { // This generates a file used by graphviz, https://www.graphviz.org // "hardcoded" parameters: - const vl_unique_ptr logp (V3File::new_ofstream(filename)); - if (logp->fail()) v3fatal("Can't write "< logp(V3File::new_ofstream(filename)); + if (logp->fail()) v3fatal("Can't write " << filename); // Header - *logp<<"digraph v3graph {\n"; - *logp<<"\tgraph\t[label=\""< SubgraphMmap; + typedef std::multimap SubgraphMmap; SubgraphMmap subgraphs; - for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) { string vertexSubgraph = (colorAsSubgraph && vertexp->color()) ? cvtToStr(vertexp->color()) : ""; subgraphs.insert(make_pair(vertexSubgraph, vertexp)); @@ -341,7 +336,7 @@ void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) const { // We use a map here, as we don't want to corrupt anything (userp) in the graph, // and we don't care if this is slow. - std::map numMap; + std::map numMap; // Print vertices int n = 0; @@ -351,42 +346,41 @@ void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) const { V3GraphVertex* vertexp = it->second; numMap[vertexp] = n; if (subgr != vertexSubgraph) { - if (subgr!="") *logp<<"\t};\n"; + if (subgr != "") *logp << "\t};\n"; subgr = vertexSubgraph; - if (subgr!="") *logp<<"\tsubgraph cluster_"<dotName()<<(n++) - <<"\t[fontsize=8 " - <<"label=\""<<(vertexp->name()!="" ? vertexp->name() : "\\N"); - if (vertexp->rank()) *logp<<" r"<rank(); - if (vertexp->fanout()!=0.0) *logp<<" f"<fanout(); - if (vertexp->color()) *logp<<"\\n c"<color(); - *logp<<"\""; - *logp<<", color="<dotColor(); - if (vertexp->dotStyle()!="") *logp<<", style="<dotStyle(); - if (vertexp->dotShape()!="") *logp<<", shape="<dotShape(); - *logp<<"];\n"; + if (subgr != "") *logp << "\t"; + *logp << "\tn" << vertexp->dotName() << (n++) << "\t[fontsize=8 " + << "label=\"" << (vertexp->name() != "" ? vertexp->name() : "\\N"); + if (vertexp->rank()) *logp << " r" << vertexp->rank(); + if (vertexp->fanout() != 0.0) *logp << " f" << vertexp->fanout(); + if (vertexp->color()) *logp << "\\n c" << vertexp->color(); + *logp << "\""; + *logp << ", color=" << vertexp->dotColor(); + if (vertexp->dotStyle() != "") *logp << ", style=" << vertexp->dotStyle(); + if (vertexp->dotShape() != "") *logp << ", shape=" << vertexp->dotShape(); + *logp << "];\n"; } - if (subgr!="") *logp<<"\t};\n"; + if (subgr != "") *logp << "\t};\n"; // Print edges - for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { - for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { + for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) { + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { if (edgep->weight()) { int fromVnum = numMap[edgep->fromp()]; - int toVnum = numMap[edgep->top()]; - *logp<<"\tn"<fromp()->dotName()< n"<top()->dotName()<name()!="" ? edgep->name() : "\\E")<<"\"" - <<"fontsize=8 label=\"" - <<(edgep->dotLabel()!="" ? edgep->dotLabel() : "")<<"\"" - <<" weight="<weight() - <<" color="<dotColor(); - if (edgep->dotStyle()!="") *logp<<" style="<dotStyle(); - //if (edgep->cutable()) { *logp<<",constraint=false"; } // to rank without following edges - *logp<<"];\n"; + int toVnum = numMap[edgep->top()]; + *logp << "\tn" << edgep->fromp()->dotName() << fromVnum << " -> n" + << edgep->top()->dotName() << toVnum + << " [" + //<<"fontsize=8 label=\""<<(edgep->name()!="" ? edgep->name() : "\\E")<<"\"" + << "fontsize=8 label=\"" + << (edgep->dotLabel() != "" ? edgep->dotLabel() : "") << "\"" + << " weight=" << edgep->weight() << " color=" << edgep->dotColor(); + if (edgep->dotStyle() != "") *logp << " style=" << edgep->dotStyle(); + // if (edgep->cutable()) { *logp<<",constraint=false"; } // to rank without + // following edges + *logp << "];\n"; } } } @@ -396,5 +390,5 @@ void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) const { *logp << "}\n"; logp->close(); - cout << "dot -Tpdf -o ~/a.pdf "< m_work; // List of vertices with optimization work left - uint32_t m_storedRank; // Rank held until commit to edge placement - bool m_onWorkList; // True if already on list of work to do - bool m_deleted; // True if deleted + V3ListEnt m_work; // List of vertices with optimization work left + uint32_t m_storedRank; // Rank held until commit to edge placement + bool m_onWorkList; // True if already on list of work to do + bool m_deleted; // True if deleted public: - GraphAcycVertex(V3Graph* graphp, V3GraphVertex* origVertexp) - : V3GraphVertex(graphp), m_origVertexp(origVertexp) - , m_storedRank(0), m_onWorkList(false), m_deleted(false) { - } + : V3GraphVertex(graphp) + , m_origVertexp(origVertexp) + , m_storedRank(0) + , m_onWorkList(false) + , m_deleted(false) {} virtual ~GraphAcycVertex() {} V3GraphVertex* origVertexp() const { return m_origVertexp; } void setDelete() { m_deleted = true; } @@ -60,25 +61,25 @@ class GraphAcycEdge : public V3GraphEdge { // userp() is always used to point to the head original graph edge private: typedef std::list OrigEdgeList; // List of orig edges, see also GraphAcyc's decl - V3GraphEdge* origEdgep() const { + V3GraphEdge* origEdgep() const { OrigEdgeList* oEListp = static_cast(userp()); - if (!oEListp) v3fatalSrc("No original edge associated with acyc edge "<front()); } + public: - GraphAcycEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, - int weight, bool cutable=false) - : V3GraphEdge(graphp, fromp, top, weight, cutable) { - } + GraphAcycEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight, + bool cutable = false) + : V3GraphEdge(graphp, fromp, top, weight, cutable) {} virtual ~GraphAcycEdge() {} // yellow=we might still cut it, else oldEdge: yellowGreen=made uncutable, red=uncutable - virtual string dotColor() const { return (cutable()?"yellow":origEdgep()->dotColor()); } + virtual string dotColor() const { return (cutable() ? "yellow" : origEdgep()->dotColor()); } }; //-------------------------------------------------------------------- struct GraphAcycEdgeCmp { - inline bool operator() (const V3GraphEdge* lhsp, const V3GraphEdge* rhsp) const { + inline bool operator()(const V3GraphEdge* lhsp, const V3GraphEdge* rhsp) const { if (lhsp->weight() > rhsp->weight()) return 1; // LHS goes first if (lhsp->weight() < rhsp->weight()) return 0; // RHS goes first return 0; @@ -90,7 +91,8 @@ struct GraphAcycEdgeCmp { // CLASSES class GraphAcyc { private: - typedef std::list OrigEdgeList; // List of orig edges, see also GraphAcycEdge's decl + typedef std::list + OrigEdgeList; // List of orig edges, see also GraphAcycEdge's decl // GRAPH USERS // origGraph // GraphVertex::user() GraphAycVerted* New graph node @@ -98,12 +100,12 @@ private: // GraphEdge::user() OrigEdgeList* Old graph edges // GraphVertex::user bool Detection of loops in simplifyDupIterate // MEMBERS - V3Graph* m_origGraphp; // Original graph - V3Graph m_breakGraph; // Graph with only breakable edges represented - V3List m_work; // List of vertices with optimization work left + V3Graph* m_origGraphp; // Original graph + V3Graph m_breakGraph; // Graph with only breakable edges represented + V3List m_work; // List of vertices with optimization work left std::vector m_origEdgeDelp; // List of deletions to do when done - V3EdgeFuncP m_origEdgeFuncp; // Function that says we follow this edge (in original graph) - uint32_t m_placeStep; // Number that user() must be equal to to indicate processing + V3EdgeFuncP m_origEdgeFuncp; // Function that says we follow this edge (in original graph) + uint32_t m_placeStep; // Number that user() must be equal to to indicate processing static int debug() { return V3Graph::debug(); } @@ -127,8 +129,8 @@ private: } V3GraphEdge* edgeFromEdge(V3GraphEdge* oldedgep, V3GraphVertex* fromp, V3GraphVertex* top) { // Make new breakGraph edge, with old edge as a template - GraphAcycEdge* newEdgep = new GraphAcycEdge(&m_breakGraph, fromp, top, - oldedgep->weight(), oldedgep->cutable()); + GraphAcycEdge* newEdgep = new GraphAcycEdge(&m_breakGraph, fromp, top, oldedgep->weight(), + oldedgep->cutable()); newEdgep->userp(oldedgep->userp()); // Keep pointer to OrigEdgeList return newEdgep; } @@ -153,16 +155,18 @@ private: } void cutOrigEdge(V3GraphEdge* breakEdgep, const char* why) { // From the break edge, cut edges in original graph it represents - UINFO(8,why<<" CUT "<fromp()<fromp() << endl); breakEdgep->cut(); OrigEdgeList* oEListp = static_cast(breakEdgep->userp()); - if (!oEListp) v3fatalSrc("No original edge associated with cutting edge " - <begin(); it != oEListp->end(); ++it) { V3GraphEdge* origEdgep = *it; origEdgep->cut(); - UINFO(8," "<fromp()<<" ->"<top()<fromp() << " ->" << origEdgep->top() << endl); } } // Work Queue @@ -178,7 +182,9 @@ private: void workPop() { GraphAcycVertex* avertexp = workBeginp(); avertexp->m_onWorkList = false; - avertexp->m_work.unlink(m_work, avertexp); } + avertexp->m_work.unlink(m_work, avertexp); + } + public: // CONSTRUCTORS GraphAcyc(V3Graph* origGraphp, V3EdgeFuncP edgeFuncp) { @@ -205,8 +211,8 @@ void GraphAcyc::buildGraph(V3Graph* origGraphp) { // For each old node, make a new graph node for optimization origGraphp->userClearVertices(); origGraphp->userClearEdges(); - for (V3GraphVertex* overtexp = origGraphp->verticesBeginp(); - overtexp; overtexp = overtexp->verticesNextp()) { + for (V3GraphVertex* overtexp = origGraphp->verticesBeginp(); overtexp; + overtexp = overtexp->verticesNextp()) { if (overtexp->color()) { GraphAcycVertex* avertexp = new GraphAcycVertex(&m_breakGraph, overtexp); overtexp->userp(avertexp); // Stash so can look up later @@ -214,8 +220,8 @@ void GraphAcyc::buildGraph(V3Graph* origGraphp) { } // Build edges between logic vertices - for (V3GraphVertex* overtexp = origGraphp->verticesBeginp(); - overtexp; overtexp = overtexp->verticesNextp()) { + for (V3GraphVertex* overtexp = origGraphp->verticesBeginp(); overtexp; + overtexp = overtexp->verticesNextp()) { if (overtexp->color()) { GraphAcycVertex* avertexp = static_cast(overtexp->userp()); buildGraphIterate(overtexp, avertexp); @@ -225,15 +231,15 @@ void GraphAcyc::buildGraph(V3Graph* origGraphp) { void GraphAcyc::buildGraphIterate(V3GraphVertex* overtexp, GraphAcycVertex* avertexp) { // Make new edges - for (V3GraphEdge* edgep = overtexp->outBeginp(); edgep; edgep=edgep->outNextp()) { + for (V3GraphEdge* edgep = overtexp->outBeginp(); edgep; edgep = edgep->outNextp()) { if (origFollowEdge(edgep)) { // not cut V3GraphVertex* toVertexp = edgep->top(); if (toVertexp->color()) { GraphAcycVertex* toAVertexp = static_cast(toVertexp->userp()); // Replicate the old edge into the new graph // There may be multiple edges between same pairs of vertices - V3GraphEdge* breakEdgep = new GraphAcycEdge - (&m_breakGraph, avertexp, toAVertexp, edgep->weight(), edgep->cutable()); + V3GraphEdge* breakEdgep = new GraphAcycEdge(&m_breakGraph, avertexp, toAVertexp, + edgep->weight(), edgep->cutable()); addOrigEdgep(breakEdgep, edgep); // So can find original edge } } @@ -242,8 +248,8 @@ void GraphAcyc::buildGraphIterate(V3GraphVertex* overtexp, GraphAcycVertex* aver void GraphAcyc::simplify(bool allowCut) { // Add all nodes to list of work to do - for (V3GraphVertex* vertexp = m_breakGraph.verticesBeginp(); - vertexp; vertexp = vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = m_breakGraph.verticesBeginp(); vertexp; + vertexp = vertexp->verticesNextp()) { workPush(vertexp); } // Optimize till everything finished @@ -267,7 +273,8 @@ void GraphAcyc::simplify(bool allowCut) { void GraphAcyc::deleteMarked() { // Delete nodes marked for removal - for (V3GraphVertex* nextp, *vertexp = m_breakGraph.verticesBeginp(); vertexp; vertexp=nextp) { + for (V3GraphVertex *nextp, *vertexp = m_breakGraph.verticesBeginp(); vertexp; + vertexp = nextp) { nextp = vertexp->verticesNextp(); GraphAcycVertex* avertexp = static_cast(vertexp); if (avertexp->isDelete()) { @@ -281,18 +288,18 @@ void GraphAcyc::simplifyNone(GraphAcycVertex* avertexp) { // Likewise, vertices with no outputs if (avertexp->isDelete()) return; if (avertexp->inEmpty() || avertexp->outEmpty()) { - UINFO(9," SimplifyNoneRemove "<setDelete(); // Mark so we won't delete it twice // Remove edges while (V3GraphEdge* edgep = avertexp->outBeginp()) { V3GraphVertex* otherVertexp = edgep->top(); - //UINFO(9," out "<unlinkDelete(), edgep); workPush(otherVertexp); } while (V3GraphEdge* edgep = avertexp->inBeginp()) { V3GraphVertex* otherVertexp = edgep->fromp(); - //UINFO(9," in "<unlinkDelete(), edgep); workPush(otherVertexp); } @@ -309,23 +316,25 @@ void GraphAcyc::simplifyOne(GraphAcycVertex* avertexp) { V3GraphVertex* outVertexp = outEdgep->top(); // The in and out may be the same node; we'll make a loop // The in OR out may be THIS node; we can't delete it then. - if (inVertexp!=avertexp && outVertexp!=avertexp) { - UINFO(9," SimplifyOneRemove "<setDelete(); // Mark so we won't delete it twice // Make a new edge connecting the two vertices directly // If both are breakable, we pick the one with less weight, else it's arbitrary // We can forget about the origEdge list for the "non-selected" set of edges, // as we need to break only one set or the other set of edges, not both. // (This is why we must give preference to the cutable set.) - V3GraphEdge* templateEdgep = ( (inEdgep->cutable() - && (!outEdgep->cutable() - || inEdgep->weight()weight() )) - ? inEdgep : outEdgep); + V3GraphEdge* templateEdgep + = ((inEdgep->cutable() + && (!outEdgep->cutable() || inEdgep->weight() < outEdgep->weight())) + ? inEdgep + : outEdgep); // cppcheck-suppress leakReturnValNotUsed edgeFromEdge(templateEdgep, inVertexp, outVertexp); // Remove old edge VL_DO_DANGLING(inEdgep->unlinkDelete(), inEdgep); - VL_DO_DANGLING(outEdgep->unlinkDelete(), outEdgep); VL_DANGLING(templateEdgep); + VL_DO_DANGLING(outEdgep->unlinkDelete(), outEdgep); + VL_DANGLING(templateEdgep); workPush(inVertexp); workPush(outVertexp); } @@ -340,16 +349,17 @@ void GraphAcyc::simplifyOut(GraphAcycVertex* avertexp) { V3GraphEdge* outEdgep = avertexp->outBeginp(); if (!outEdgep->cutable()) { V3GraphVertex* outVertexp = outEdgep->top(); - UINFO(9," SimplifyOutRemove "<setDelete(); // Mark so we won't delete it twice - for (V3GraphEdge* nextp, *inEdgep = avertexp->inBeginp(); inEdgep; inEdgep=nextp) { + for (V3GraphEdge *nextp, *inEdgep = avertexp->inBeginp(); inEdgep; inEdgep = nextp) { nextp = inEdgep->inNextp(); V3GraphVertex* inVertexp = inEdgep->fromp(); if (inVertexp == avertexp) { - if (debug()) v3error("Non-cutable edge forms a loop, vertex="<reportLoops(&V3GraphEdge::followNotCutable, - avertexp->origVertexp()); // calls OrderGraph::loopsVertexCb + m_origGraphp->reportLoops( + &V3GraphEdge::followNotCutable, + avertexp->origVertexp()); // calls OrderGraph::loopsVertexCb // Things are unlikely to end well at this point, // but we'll try something to get to further errors... inEdgep->cutable(true); @@ -372,11 +382,11 @@ void GraphAcyc::simplifyDup(GraphAcycVertex* avertexp) { // Remove redundant edges if (avertexp->isDelete()) return; // Clear marks - for (V3GraphEdge* edgep = avertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { + for (V3GraphEdge* edgep = avertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { edgep->top()->userp(NULL); } // Mark edges and detect duplications - for (V3GraphEdge* nextp, *edgep = avertexp->outBeginp(); edgep; edgep=nextp) { + for (V3GraphEdge *nextp, *edgep = avertexp->outBeginp(); edgep; edgep = nextp) { nextp = edgep->outNextp(); V3GraphVertex* outVertexp = edgep->top(); V3GraphEdge* prevEdgep = static_cast(outVertexp->userp()); @@ -384,16 +394,16 @@ void GraphAcyc::simplifyDup(GraphAcycVertex* avertexp) { if (!prevEdgep->cutable()) { // !cutable duplicates prev !cutable: we can ignore it, redundant // cutable duplicates prev !cutable: know it's not a relevant loop, ignore it - UINFO(8," DelDupEdge "< "<top()< " << edgep->top() << endl); VL_DO_DANGLING(edgep->unlinkDelete(), edgep); } else if (!edgep->cutable()) { // !cutable duplicates prev cutable: delete the earlier cutable - UINFO(8," DelDupPrev "< "<top()< " << prevEdgep->top() << endl); VL_DO_DANGLING(prevEdgep->unlinkDelete(), prevEdgep); outVertexp->userp(edgep); } else { // cutable duplicates prev cutable: combine weights - UINFO(8," DelDupComb "< "<top()< " << edgep->top() << endl); prevEdgep->weight(prevEdgep->weight() + edgep->weight()); addOrigEdgep(prevEdgep, edgep); VL_DO_DANGLING(edgep->unlinkDelete(), edgep); @@ -410,9 +420,9 @@ void GraphAcyc::simplifyDup(GraphAcycVertex* avertexp) { void GraphAcyc::cutBasic(GraphAcycVertex* avertexp) { // Detect and cleanup any loops from node to itself if (avertexp->isDelete()) return; - for (V3GraphEdge* nextp, *edgep = avertexp->outBeginp(); edgep; edgep=nextp) { + for (V3GraphEdge *nextp, *edgep = avertexp->outBeginp(); edgep; edgep = nextp) { nextp = edgep->outNextp(); - if (edgep->cutable() && edgep->top()==avertexp) { + if (edgep->cutable() && edgep->top() == avertexp) { cutOrigEdge(edgep, " Cut Basic"); VL_DO_DANGLING(edgep->unlinkDelete(), edgep); workPush(avertexp); @@ -424,14 +434,14 @@ void GraphAcyc::cutBackward(GraphAcycVertex* avertexp) { // If a cutable edge is from A->B, and there's a non-cutable edge B->A, then must cut! if (avertexp->isDelete()) return; // Clear marks - for (V3GraphEdge* edgep = avertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { + for (V3GraphEdge* edgep = avertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { edgep->top()->user(false); } - for (V3GraphEdge* edgep = avertexp->inBeginp(); edgep; edgep=edgep->inNextp()) { + for (V3GraphEdge* edgep = avertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { if (!edgep->cutable()) edgep->fromp()->user(true); } // Detect duplications - for (V3GraphEdge* nextp, *edgep = avertexp->outBeginp(); edgep; edgep=nextp) { + for (V3GraphEdge *nextp, *edgep = avertexp->outBeginp(); edgep; edgep = nextp) { nextp = edgep->outNextp(); if (edgep->cutable() && edgep->top()->user()) { cutOrigEdge(edgep, " Cut A->B->A"); @@ -446,25 +456,22 @@ void GraphAcyc::place() { // Make a list of all cutable edges in the graph int numEdges = 0; - for (V3GraphVertex* vertexp = m_breakGraph.verticesBeginp(); - vertexp; vertexp = vertexp->verticesNextp()) { - for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { - if (edgep->weight() && edgep->cutable()) { - numEdges++; - } + for (V3GraphVertex* vertexp = m_breakGraph.verticesBeginp(); vertexp; + vertexp = vertexp->verticesNextp()) { + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { + if (edgep->weight() && edgep->cutable()) ++numEdges; } } - UINFO(4, " Cutable edges = "<weight()<<" "<fromp()<weight() << " " << edgep->fromp() + << endl); // Make the edge uncutable so we detect it in placement edgep->cutable(false); // Vertex::m_user begin: number indicates this edge was completed // Try to assign ranks, presuming this edge is in place // If we come across user()==placestep, we've detected a loop and must back out - bool loop = placeIterate(static_cast(edgep->top()), - edgep->fromp()->rank()+1); + bool loop + = placeIterate(static_cast(edgep->top()), edgep->fromp()->rank() + 1); if (!loop) { // No loop, we can keep it as uncutable // Commit the new ranks we calculated // Just cleanup the list. If this is slow, we can add another set of // user counters to avoid cleaning up the list. - while (workBeginp()) { - workPop(); - } + while (workBeginp()) workPop(); } else { // Adding this edge would cause a loop, kill it edgep->cutable(true); // So graph still looks pretty @@ -526,9 +532,9 @@ bool GraphAcyc::placeIterate(GraphAcycVertex* vertexp, uint32_t currentRank) { } vertexp->rank(currentRank); // Follow all edges and increase their ranks - for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { if (edgep->weight() && !edgep->cutable()) { - if (placeIterate(static_cast(edgep->top()), currentRank+1)) { + if (placeIterate(static_cast(edgep->top()), currentRank + 1)) { // We don't need to reset user(); we'll use a different placeStep for the next edge return true; // Loop detected } @@ -551,33 +557,33 @@ void GraphAcyc::main() { // edges (and thus can't represent loops - if we did the unbreakable // marking right, anyways) buildGraph(m_origGraphp); - if (debug()>=6) m_breakGraph.dumpDotFilePrefixed("acyc_pre"); + if (debug() >= 6) m_breakGraph.dumpDotFilePrefixed("acyc_pre"); // Perform simple optimizations before any cuttings simplify(false); - if (debug()>=5) m_breakGraph.dumpDotFilePrefixed("acyc_simp"); + if (debug() >= 5) m_breakGraph.dumpDotFilePrefixed("acyc_simp"); UINFO(4, " Cutting trivial loops\n"); simplify(true); - if (debug()>=6) m_breakGraph.dumpDotFilePrefixed("acyc_mid"); + if (debug() >= 6) m_breakGraph.dumpDotFilePrefixed("acyc_mid"); UINFO(4, " Ranking\n"); m_breakGraph.rank(&V3GraphEdge::followNotCutable); - if (debug()>=6) m_breakGraph.dumpDotFilePrefixed("acyc_rank"); + if (debug() >= 6) m_breakGraph.dumpDotFilePrefixed("acyc_rank"); UINFO(4, " Placement\n"); place(); - if (debug()>=6) m_breakGraph.dumpDotFilePrefixed("acyc_place"); + if (debug() >= 6) m_breakGraph.dumpDotFilePrefixed("acyc_place"); UINFO(4, " Final Ranking\n"); // Only needed to assert there are no loops in completed graph m_breakGraph.rank(&V3GraphEdge::followAlwaysTrue); - if (debug()>=6) m_breakGraph.dumpDotFilePrefixed("acyc_done"); + if (debug() >= 6) m_breakGraph.dumpDotFilePrefixed("acyc_done"); } void V3Graph::acyclic(V3EdgeFuncP edgeFuncp) { UINFO(4, "Acyclic\n"); - GraphAcyc acyc (this, edgeFuncp); + GraphAcyc acyc(this, edgeFuncp); acyc.main(); UINFO(4, "Acyclic done\n"); } diff --git a/src/V3GraphAlg.cpp b/src/V3GraphAlg.cpp index 9120f8f98..95db5be4f 100644 --- a/src/V3GraphAlg.cpp +++ b/src/V3GraphAlg.cpp @@ -36,15 +36,15 @@ void V3Graph::deleteCutableOnlyEdges() { // Vertex::m_user begin: indicates can be deleted // Pass 1, mark those. Don't delete now, as we don't want to rip out whole trees - for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) { vertexp->user(true); - for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep=edgep->inNextp()) { + for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { if (!edgep->cutable()) { vertexp->user(false); // Can't delete it break; } } - for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { if (!edgep->cutable()) { vertexp->user(false); // Can't delete it break; @@ -54,10 +54,10 @@ void V3Graph::deleteCutableOnlyEdges() { // Pass 2, delete those marked // Rather than doing a delete() we set the weight to 0 which disconnects the edge. - for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) { if (vertexp->user()) { - //UINFO(7,"Disconnect "<name()<outBeginp(); edgep; edgep=edgep->outNextp()) { + // UINFO(7, "Disconnect " << vertexp->name() << endl); + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { edgep->cut(); } } @@ -71,21 +71,21 @@ void V3Graph::deleteCutableOnlyEdges() { // Algorithms - weakly connected components class GraphRemoveRedundant : GraphAlg<> { - bool m_sumWeights; ///< Sum, rather then maximize weights + bool m_sumWeights; ///< Sum, rather then maximize weights private: void main() { - for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); - vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp; + vertexp = vertexp->verticesNextp()) { vertexIterate(vertexp); } } void vertexIterate(V3GraphVertex* vertexp) { // Clear marks - for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { edgep->top()->userp(NULL); } // Mark edges and detect duplications - for (V3GraphEdge* nextp, *edgep = vertexp->outBeginp(); edgep; edgep=nextp) { + for (V3GraphEdge *nextp, *edgep = vertexp->outBeginp(); edgep; edgep = nextp) { nextp = edgep->outNextp(); if (followEdge(edgep)) { V3GraphVertex* outVertexp = edgep->top(); @@ -100,7 +100,8 @@ private: saveOld = true; // old !cutable more important than new } else { saveOld = true; - if (!m_sumWeights && (prevEdgep->weight() < edgep->weight())) { // Keep max weight + if (!m_sumWeights + && (prevEdgep->weight() < edgep->weight())) { // Keep max weight prevEdgep->weight(edgep->weight()); } } @@ -116,9 +117,11 @@ private: } } } + public: GraphRemoveRedundant(V3Graph* graphp, V3EdgeFuncP edgeFuncp, bool sumWeights) - : GraphAlg<>(graphp, edgeFuncp), m_sumWeights(sumWeights) { + : GraphAlg<>(graphp, edgeFuncp) + , m_sumWeights(sumWeights) { main(); } ~GraphRemoveRedundant() {} @@ -141,33 +144,26 @@ public: : GraphAlg<>(graphp, NULL) {} void go() { GraphPathChecker checker(m_graphp); - for (V3GraphVertex* vxp = m_graphp->verticesBeginp(); - vxp; vxp = vxp->verticesNextp()) { + for (V3GraphVertex* vxp = m_graphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) { V3GraphEdge* deletep = NULL; - for (V3GraphEdge* edgep = vxp->outBeginp(); - edgep; edgep = edgep->outNextp()) { + for (V3GraphEdge* edgep = vxp->outBeginp(); edgep; edgep = edgep->outNextp()) { if (deletep) VL_DO_CLEAR(deletep->unlinkDelete(), deletep = NULL); // It should be safe to modify the graph, despite using // the GraphPathChecker, as none of the modifications will // change what can be reached from what, nor should they // change the rank or CP of any node. - if (checker.isTransitiveEdge(edgep)) { - deletep = edgep; - } - } - if (deletep) { - VL_DO_DANGLING(deletep->unlinkDelete(), deletep); + if (checker.isTransitiveEdge(edgep)) deletep = edgep; } + if (deletep) VL_DO_DANGLING(deletep->unlinkDelete(), deletep); } } + private: VL_DEBUG_FUNC; // Declare debug() VL_UNCOPYABLE(GraphAlgRemoveTransitiveEdges); }; -void V3Graph::removeTransitiveEdges() { - GraphAlgRemoveTransitiveEdges(this).go(); -} +void V3Graph::removeTransitiveEdges() { GraphAlgRemoveTransitiveEdges(this).go(); } //###################################################################### //###################################################################### @@ -180,9 +176,9 @@ private: m_graphp->clearColors(); // Color graph uint32_t currentColor = 0; - for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); - vertexp; vertexp=vertexp->verticesNextp()) { - currentColor ++; + for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp; + vertexp = vertexp->verticesNextp()) { + currentColor++; vertexIterate(vertexp, currentColor); } } @@ -192,17 +188,14 @@ private: // then visit each of its edges, giving them the same color if (vertexp->color()) return; // Already colored it vertexp->color(currentColor); - for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { - if (followEdge(edgep)) { - vertexIterate(edgep->top(), currentColor); - } + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { + if (followEdge(edgep)) vertexIterate(edgep->top(), currentColor); } - for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep=edgep->inNextp()) { - if (followEdge(edgep)) { - vertexIterate(edgep->fromp(), currentColor); - } + for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { + if (followEdge(edgep)) vertexIterate(edgep->fromp(), currentColor); } } + public: GraphAlgWeakly(V3Graph* graphp, V3EdgeFuncP edgeFuncp) : GraphAlg<>(graphp, edgeFuncp) { @@ -211,9 +204,7 @@ public: ~GraphAlgWeakly() {} }; -void V3Graph::weaklyConnected(V3EdgeFuncP edgeFuncp) { - GraphAlgWeakly(this, edgeFuncp); -} +void V3Graph::weaklyConnected(V3EdgeFuncP edgeFuncp) { GraphAlgWeakly(this, edgeFuncp); } //###################################################################### //###################################################################### @@ -231,14 +222,14 @@ private: // Vertex::color // Output subtree number (fully processed) // Clear info - for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); - vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp; + vertexp = vertexp->verticesNextp()) { vertexp->color(0); vertexp->user(0); } // Color graph - for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); - vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp; + vertexp = vertexp->verticesNextp()) { if (!vertexp->user()) { m_currentDfs++; vertexIterate(vertexp); @@ -246,10 +237,10 @@ private: } // If there's a single vertex of a color, it doesn't need a subgraph // This simplifies the consumer's code, and reduces graph debugging clutter - for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); - vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp; + vertexp = vertexp->verticesNextp()) { bool onecolor = true; - for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { if (followEdge(edgep)) { if (vertexp->color() == edgep->top()->color()) { onecolor = false; @@ -265,7 +256,7 @@ private: uint32_t thisDfsNum = m_currentDfs++; vertexp->user(thisDfsNum); vertexp->color(0); - for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { if (followEdge(edgep)) { V3GraphVertex* top = edgep->top(); if (!top->user()) { // Dest not computed yet @@ -291,6 +282,7 @@ private: m_callTrace.push_back(vertexp); } } + public: GraphAlgStrongly(V3Graph* graphp, V3EdgeFuncP edgeFuncp) : GraphAlg<>(graphp, edgeFuncp) { @@ -300,9 +292,7 @@ public: ~GraphAlgStrongly() {} }; -void V3Graph::stronglyConnected(V3EdgeFuncP edgeFuncp) { - GraphAlgStrongly(this, edgeFuncp); -} +void V3Graph::stronglyConnected(V3EdgeFuncP edgeFuncp) { GraphAlgStrongly(this, edgeFuncp); } //###################################################################### //###################################################################### @@ -314,16 +304,14 @@ private: // Rank each vertex, ignoring cutable edges // Vertex::m_user begin: 1 indicates processing, 2 indicates completed // Clear existing ranks - for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); - vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp; + vertexp = vertexp->verticesNextp()) { vertexp->rank(0); vertexp->user(0); } - for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); - vertexp; vertexp=vertexp->verticesNextp()) { - if (!vertexp->user()) { - vertexIterate(vertexp, 1); - } + for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp; + vertexp = vertexp->verticesNextp()) { + if (!vertexp->user()) { vertexIterate(vertexp, 1); } } } @@ -339,13 +327,14 @@ private: if (vertexp->rank() >= currentRank) return; // Already processed it vertexp->user(1); vertexp->rank(currentRank); - for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { if (followEdge(edgep)) { vertexIterate(edgep->top(), currentRank + vertexp->rankAdder()); } } vertexp->user(2); } + public: GraphAlgRank(V3Graph* graphp, V3EdgeFuncP edgeFuncp) : GraphAlg<>(graphp, edgeFuncp) { @@ -354,13 +343,9 @@ public: ~GraphAlgRank() {} }; -void V3Graph::rank() { - GraphAlgRank(this, &V3GraphEdge::followAlwaysTrue); -} +void V3Graph::rank() { GraphAlgRank(this, &V3GraphEdge::followAlwaysTrue); } -void V3Graph::rank(V3EdgeFuncP edgeFuncp) { - GraphAlgRank(this, edgeFuncp); -} +void V3Graph::rank(V3EdgeFuncP edgeFuncp) { GraphAlgRank(this, edgeFuncp); } //###################################################################### //###################################################################### @@ -389,7 +374,7 @@ private: m_callTrace[currentRank++] = vertexp; if (vertexp->user() == 1) { - for (unsigned i=0; iloopsVertexCb(m_callTrace[i]); } m_done = true; @@ -397,13 +382,12 @@ private: } if (vertexp->user() == 2) return; // Already processed it vertexp->user(1); - for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { - if (followEdge(edgep)) { - vertexIterate(edgep->top(), currentRank); - } + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { + if (followEdge(edgep)) vertexIterate(edgep->top(), currentRank); } vertexp->user(2); } + public: GraphAlgRLoops(V3Graph* graphp, V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp) : GraphAlg<>(graphp, edgeFuncp) { @@ -417,7 +401,6 @@ void V3Graph::reportLoops(V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp) { GraphAlgRLoops(this, edgeFuncp, vertexp); } - //###################################################################### //###################################################################### // Algorithms - subtrees @@ -434,14 +417,12 @@ private: newVertexp = vertexp->clone(m_loopGraphp); vertexp->userp(newVertexp); - for (V3GraphEdge* edgep = vertexp->outBeginp(); - edgep; edgep=edgep->outNextp()) { + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { if (followEdge(edgep)) { V3GraphEdge* newEdgep = static_cast(edgep->userp()); if (!newEdgep) { V3GraphVertex* newTop = vertexIterateAll(edgep->top()); - newEdgep = edgep->clone(m_loopGraphp, newVertexp, - newTop); + newEdgep = edgep->clone(m_loopGraphp, newVertexp, newTop); edgep->userp(newEdgep); } } @@ -451,21 +432,21 @@ private: } public: - GraphAlgSubtrees(V3Graph* graphp, V3Graph* loopGraphp, - V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp) - : GraphAlg<>(graphp, edgeFuncp), m_loopGraphp(loopGraphp) { + GraphAlgSubtrees(V3Graph* graphp, V3Graph* loopGraphp, V3EdgeFuncP edgeFuncp, + V3GraphVertex* vertexp) + : GraphAlg<>(graphp, edgeFuncp) + , m_loopGraphp(loopGraphp) { // Vertex::m_userp - New vertex if we have seen this vertex already // Edge::m_userp - New edge if we have seen this edge already m_graphp->userClearVertices(); m_graphp->userClearEdges(); - (void) vertexIterateAll(vertexp); + (void)vertexIterateAll(vertexp); } ~GraphAlgSubtrees() {} }; //! Report the entire connected graph with a loop or loops -void V3Graph::subtreeLoops(V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp, - V3Graph* loopGraphp) { +void V3Graph::subtreeLoops(V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp, V3Graph* loopGraphp) { GraphAlgSubtrees(this, loopGraphp, edgeFuncp, vertexp); } @@ -474,7 +455,7 @@ void V3Graph::subtreeLoops(V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp, // Algorithms - make non cutable void V3Graph::makeEdgesNonCutable(V3EdgeFuncP edgeFuncp) { - for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) { // Only need one direction, we'll always see the other at some point... for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { if (edgep->cutable() && edgep->weight() && (edgeFuncp)(edgep)) { @@ -489,12 +470,12 @@ void V3Graph::makeEdgesNonCutable(V3EdgeFuncP edgeFuncp) { // Algorithms - sorting struct GraphSortVertexCmp { - inline bool operator() (const V3GraphVertex* lhsp, const V3GraphVertex* rhsp) const { + inline bool operator()(const V3GraphVertex* lhsp, const V3GraphVertex* rhsp) const { return lhsp->sortCmp(rhsp) < 0; } }; struct GraphSortEdgeCmp { - inline bool operator() (const V3GraphEdge* lhsp, const V3GraphEdge* rhsp) const { + inline bool operator()(const V3GraphEdge* lhsp, const V3GraphEdge* rhsp) const { return lhsp->sortCmp(rhsp) < 0; } }; @@ -502,12 +483,12 @@ struct GraphSortEdgeCmp { void V3Graph::sortVertices() { // Sort list of vertices by rank, then fanout std::vector vertices; - for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) { vertices.push_back(vertexp); } std::stable_sort(vertices.begin(), vertices.end(), GraphSortVertexCmp()); this->verticesUnlink(); - for (std::vector::iterator it = vertices.begin(); it!=vertices.end(); ++it) { + for (std::vector::iterator it = vertices.begin(); it != vertices.end(); ++it) { (*it)->verticesPushBack(this); } } @@ -515,7 +496,7 @@ void V3Graph::sortVertices() { void V3Graph::sortEdges() { // Sort edges by rank then fanout of node they point to std::vector edges; - for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) { // Make a vector for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { edges.push_back(edgep); @@ -527,7 +508,8 @@ void V3Graph::sortEdges() { // We know the vector contains all of the edges that were // there originally (didn't delete or add) vertexp->outUnlink(); - for (std::vector::const_iterator it = edges.begin(); it!=edges.end(); ++it) { + for (std::vector::const_iterator it = edges.begin(); it != edges.end(); + ++it) { (*it)->outPushBack(); } // Prep for next @@ -544,7 +526,7 @@ void V3Graph::sortEdges() { // (Results in better dcache packing.) void V3Graph::order() { - UINFO(2,"Order:\n"); + UINFO(2, "Order:\n"); // Compute rankings again rank(&V3GraphEdge::followAlwaysTrue); @@ -555,10 +537,8 @@ void V3Graph::orderPreRanked() { // Compute fanouts // Vertex::m_user begin: 1 indicates processing, 2 indicates completed userClearVertices(); - for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { - if (!vertexp->user()) { - orderDFSIterate(vertexp); - } + for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) { + if (!vertexp->user()) orderDFSIterate(vertexp); } // Sort list of vertices by rank, then fanout. Fanout is a bit of a @@ -581,7 +561,7 @@ double V3Graph::orderDFSIterate(V3GraphVertex* vertexp) { } // Just count inbound edges for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { - if (edgep->weight()) fanout ++; + if (edgep->weight()) ++fanout; } vertexp->fanout(fanout); vertexp->user(2); diff --git a/src/V3GraphTest.cpp b/src/V3GraphTest.cpp index 3a6d3fcd3..232cb01b0 100644 --- a/src/V3GraphTest.cpp +++ b/src/V3GraphTest.cpp @@ -38,9 +38,7 @@ protected: // Utilities void dump() { - if (debug()>=9) { - m_graph.dumpDotFilePrefixed("v3graphtest_"+name()); - } + if (debug() >= 9) m_graph.dumpDotFilePrefixed("v3graphtest_" + name()); } public: @@ -56,9 +54,11 @@ public: class V3GraphTestVertex : public V3GraphVertex { string m_name; + public: V3GraphTestVertex(V3Graph* graphp, const string& name) - : V3GraphVertex(graphp), m_name(name) {} + : V3GraphVertex(graphp) + , m_name(name) {} virtual ~V3GraphTestVertex() {} // ACCESSORS virtual string name() const { return m_name; } @@ -84,13 +84,13 @@ public: V3Graph* gp = &m_graph; // Verify we break edges at a good point // A simple alg would make 3 breaks, below only requires b->i to break - V3GraphTestVertex* i = new V3GraphTestVarVertex(gp, "*INPUTS*"); - V3GraphTestVertex* a = new V3GraphTestVarVertex(gp, "a"); - V3GraphTestVertex* b = new V3GraphTestVarVertex(gp, "b"); - V3GraphTestVertex* g1 = new V3GraphTestVarVertex(gp, "g1"); - V3GraphTestVertex* g2 = new V3GraphTestVarVertex(gp, "g2"); - V3GraphTestVertex* g3 = new V3GraphTestVarVertex(gp, "g3"); - V3GraphTestVertex* q = new V3GraphTestVarVertex(gp, "q"); + V3GraphTestVertex* i = new V3GraphTestVarVertex(gp, "*INPUTS*"); + V3GraphTestVertex* a = new V3GraphTestVarVertex(gp, "a"); + V3GraphTestVertex* b = new V3GraphTestVarVertex(gp, "b"); + V3GraphTestVertex* g1 = new V3GraphTestVarVertex(gp, "g1"); + V3GraphTestVertex* g2 = new V3GraphTestVarVertex(gp, "g2"); + V3GraphTestVertex* g3 = new V3GraphTestVarVertex(gp, "g3"); + V3GraphTestVertex* q = new V3GraphTestVarVertex(gp, "q"); new V3GraphEdge(gp, i, a, 2, true); new V3GraphEdge(gp, a, b, 2, true); new V3GraphEdge(gp, b, g1, 2, true); @@ -106,11 +106,11 @@ public: gp->stronglyConnected(&V3GraphEdge::followAlwaysTrue); dump(); - UASSERT(i->color()!=a->color() && a->color() != g2->color() && g2->color() != q->color(), + UASSERT(i->color() != a->color() && a->color() != g2->color() && g2->color() != q->color(), "SelfTest: Separate colors not assigned"); - UASSERT(a->color()==b->color() && a->color()==g1->color(), + UASSERT(a->color() == b->color() && a->color() == g1->color(), "SelfTest: Strongly connected nodes not colored together"); - UASSERT(g2->color()==g3->color(), + UASSERT(g2->color() == g3->color(), "SelfTest: Strongly connected nodes not colored together"); } }; @@ -122,12 +122,12 @@ public: V3Graph* gp = &m_graph; // Verify we break edges at a good point // A simple alg would make 3 breaks, below only requires b->i to break - V3GraphTestVertex* i = new V3GraphTestVarVertex(gp, "*INPUTS*"); - V3GraphTestVertex* a = new V3GraphTestVarVertex(gp, "a"); - V3GraphTestVertex* b = new V3GraphTestVarVertex(gp, "b"); - V3GraphTestVertex* g1 = new V3GraphTestVarVertex(gp, "g1"); - V3GraphTestVertex* g2 = new V3GraphTestVarVertex(gp, "g2"); - V3GraphTestVertex* g3 = new V3GraphTestVarVertex(gp, "g3"); + V3GraphTestVertex* i = new V3GraphTestVarVertex(gp, "*INPUTS*"); + V3GraphTestVertex* a = new V3GraphTestVarVertex(gp, "a"); + V3GraphTestVertex* b = new V3GraphTestVarVertex(gp, "b"); + V3GraphTestVertex* g1 = new V3GraphTestVarVertex(gp, "g1"); + V3GraphTestVertex* g2 = new V3GraphTestVarVertex(gp, "g2"); + V3GraphTestVertex* g3 = new V3GraphTestVarVertex(gp, "g3"); new V3GraphEdge(gp, i, a, 2, true); new V3GraphEdge(gp, a, b, 2, true); new V3GraphEdge(gp, b, g1, 2, true); @@ -149,20 +149,20 @@ public: virtual void runTest() { V3Graph* gp = &m_graph; - V3GraphTestVertex* clk = new V3GraphTestVarVertex(gp, "$clk"); + V3GraphTestVertex* clk = new V3GraphTestVarVertex(gp, "$clk"); - V3GraphTestVertex* a = new V3GraphTestVarVertex(gp, "$a"); - V3GraphTestVertex* a_dly = new V3GraphTestVarVertex(gp, "$a_dly"); - V3GraphTestVertex* a_dlyblk= new V3GraphTestVarVertex(gp, "$a_dlyblk"); - V3GraphTestVertex* b = new V3GraphTestVarVertex(gp, "$b"); - V3GraphTestVertex* b_dly = new V3GraphTestVarVertex(gp, "$b_dly"); - V3GraphTestVertex* b_dlyblk= new V3GraphTestVarVertex(gp, "$b_dlyblk"); - V3GraphTestVertex* c = new V3GraphTestVarVertex(gp, "$c"); - V3GraphTestVertex* i = new V3GraphTestVarVertex(gp, "$i"); + V3GraphTestVertex* a = new V3GraphTestVarVertex(gp, "$a"); + V3GraphTestVertex* a_dly = new V3GraphTestVarVertex(gp, "$a_dly"); + V3GraphTestVertex* a_dlyblk = new V3GraphTestVarVertex(gp, "$a_dlyblk"); + V3GraphTestVertex* b = new V3GraphTestVarVertex(gp, "$b"); + V3GraphTestVertex* b_dly = new V3GraphTestVarVertex(gp, "$b_dly"); + V3GraphTestVertex* b_dlyblk = new V3GraphTestVarVertex(gp, "$b_dlyblk"); + V3GraphTestVertex* c = new V3GraphTestVarVertex(gp, "$c"); + V3GraphTestVertex* i = new V3GraphTestVarVertex(gp, "$i"); - V3GraphTestVertex* ap = new V3GraphTestVarVertex(gp, "$a_pre"); - V3GraphTestVertex* bp = new V3GraphTestVarVertex(gp, "$b_pre"); - V3GraphTestVertex* cp = new V3GraphTestVarVertex(gp, "$c_pre"); + V3GraphTestVertex* ap = new V3GraphTestVarVertex(gp, "$a_pre"); + V3GraphTestVertex* bp = new V3GraphTestVarVertex(gp, "$b_pre"); + V3GraphTestVertex* cp = new V3GraphTestVarVertex(gp, "$c_pre"); V3GraphTestVertex* n; @@ -177,26 +177,27 @@ public: // Desired order between different _DLY blocks so we can elim temporaries // implemented by cutable "pre" signal dependencies - - n = new V3GraphTestVertex(gp, "*INPUTS*"); { + n = new V3GraphTestVertex(gp, "*INPUTS*"); + { new V3GraphEdge(gp, n, clk, 2); new V3GraphEdge(gp, n, i, 2); } - V3GraphTestVertex* posedge = n = new V3GraphTestVertex(gp, "*posedge clk*"); { - new V3GraphEdge(gp, clk, n, 2); - } + V3GraphTestVertex* posedge = n = new V3GraphTestVertex(gp, "*posedge clk*"); + { new V3GraphEdge(gp, clk, n, 2); } // AssignPre's VarRefs on LHS: generate special BLK // normal: VarRefs on LHS: generate normal // underSBlock: VarRefs on RHS: consume 'pre' (required to save cutable tests) - n = new V3GraphTestVertex(gp, "a_dlystart(true); - DfaTestVertex* sl = new DfaTestVertex(gp, "sL"); - DfaTestVertex* srs = new DfaTestVertex(gp, "sR*"); - DfaTestVertex* sls = new DfaTestVertex(gp, "sL*"); - DfaTestVertex* sr = new DfaTestVertex(gp, "sR"); - DfaTestVertex* sz = new DfaTestVertex(gp, "sZ"); - DfaTestVertex* sac = new DfaTestVertex(gp, "*ACCEPT*"); sac->accepting(true); + DfaTestVertex* st = new DfaTestVertex(gp, "*START*"); + st->start(true); + DfaTestVertex* sl = new DfaTestVertex(gp, "sL"); + DfaTestVertex* srs = new DfaTestVertex(gp, "sR*"); + DfaTestVertex* sls = new DfaTestVertex(gp, "sL*"); + DfaTestVertex* sr = new DfaTestVertex(gp, "sR"); + DfaTestVertex* sz = new DfaTestVertex(gp, "sZ"); + DfaTestVertex* sac = new DfaTestVertex(gp, "*ACCEPT*"); + sac->accepting(true); VNUser L = VNUser::fromInt(0xaa); VNUser R = VNUser::fromInt(0xbb); VNUser Z = VNUser::fromInt(0xcc); - new DfaEdge(gp, st, sl, DfaEdge::EPSILON()); - new DfaEdge(gp, sl, srs, L); + new DfaEdge(gp, st, sl, DfaEdge::EPSILON()); + new DfaEdge(gp, sl, srs, L); new DfaEdge(gp, srs, srs, R); - new DfaEdge(gp, srs, sz, Z); - new DfaEdge(gp, sz, sac, DfaEdge::EPSILON()); + new DfaEdge(gp, srs, sz, Z); + new DfaEdge(gp, sz, sac, DfaEdge::EPSILON()); - new DfaEdge(gp, st, sls, DfaEdge::EPSILON()); + new DfaEdge(gp, st, sls, DfaEdge::EPSILON()); new DfaEdge(gp, sls, sls, L); - new DfaEdge(gp, sls, sr, R); - new DfaEdge(gp, sr, sz, Z); - new DfaEdge(gp, sz, sac, DfaEdge::EPSILON()); + new DfaEdge(gp, sls, sr, R); + new DfaEdge(gp, sr, sz, Z); + new DfaEdge(gp, sz, sac, DfaEdge::EPSILON()); dump(); gp->nfaToDfa(); @@ -335,18 +345,22 @@ public: } }; +// clang-format off #ifdef GRAPH_IMPORT # include "graph_export.cpp" #endif +// clang-format on //====================================================================== void V3Graph::selfTest() { // Execute all of the tests - UINFO(2,__FUNCTION__<<": "< V3Hash. Hash value of this node (hash of 0 is illegal) - //AstUser4InUse in V3Hashed.h + // AstUser4InUse in V3Hashed.h // STATE - V3Hash m_lowerHash; // Hash of the statement we're building - bool m_cacheInUser4; // Use user4 to cache each V3Hash? + V3Hash m_lowerHash; // Hash of the statement we're building + bool m_cacheInUser4; // Use user4 to cache each V3Hash? // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -55,10 +55,12 @@ private: void nodeHashIterate(AstNode* nodep) { V3Hash thisHash; if (!m_cacheInUser4 || !nodep->user4()) { - UASSERT_OBJ(!(VN_IS(nodep->backp(), CFunc) - && !(VN_IS(nodep, NodeStmt) || VN_IS(nodep, CFunc))), nodep, - "Node "<prettyTypeName() - <<" in statement position but not marked stmt (node under function)"); + UASSERT_OBJ( + !(VN_IS(nodep->backp(), CFunc) + && !(VN_IS(nodep, NodeStmt) || VN_IS(nodep, CFunc))), + nodep, + "Node " << nodep->prettyTypeName() + << " in statement position but not marked stmt (node under function)"); V3Hash oldHash = m_lowerHash; { m_lowerHash = nodep->sameHash(); @@ -66,20 +68,19 @@ private: "sameHash function undefined (returns 0) for node under CFunc."); // For identical nodes, the type should be the same thus // dtypep should be the same too - m_lowerHash = V3Hash(m_lowerHash, V3Hash(nodep->type()<<6, - V3Hash(nodep->dtypep()))); + m_lowerHash + = V3Hash(m_lowerHash, V3Hash(nodep->type() << 6, V3Hash(nodep->dtypep()))); // Now update m_lowerHash for our children's (and next children) contributions iterateChildren(nodep); // Store the hash value nodep->user4(m_lowerHash.fullValue()); - //UINFO(9, " hashnode "<user4p()) { - HashedVisitor visitor (nodep); - } + UINFO(8, " hashI " << nodep << endl); + if (!nodep->user4p()) { HashedVisitor visitor(nodep); } } bool V3Hashed::sameNodes(AstNode* node1p, AstNode* node2p) { @@ -135,7 +134,7 @@ bool V3Hashed::sameNodes(AstNode* node1p, AstNode* node2p) { void V3Hashed::erase(iterator it) { AstNode* nodep = iteratorNodep(it); - UINFO(8," erase "<user4p(), nodep, "Called removeNode on non-hashed node"); m_hashMmap.erase(it); nodep->user4p(NULL); // So we don't allow removeNode again @@ -149,24 +148,22 @@ void V3Hashed::check() { } void V3Hashed::dumpFilePrefixed(const string& nameComment, bool tree) { - if (v3Global.opt.dumpTree()) { - dumpFile(v3Global.debugFilename(nameComment)+".hash", tree); - } + if (v3Global.opt.dumpTree()) dumpFile(v3Global.debugFilename(nameComment) + ".hash", tree); } void V3Hashed::dumpFile(const string& filename, bool tree) { - const vl_unique_ptr logp (V3File::new_ofstream(filename)); - if (logp->fail()) v3fatal("Can't write "< logp(V3File::new_ofstream(filename)); + if (logp->fail()) v3fatal("Can't write " << filename); - std::map dist; + std::map dist; V3Hash lasthash; int num_in_bucket = 0; - for (HashMmap::iterator it=begin(); 1; ++it) { - if (it==end() || lasthash != it->first) { - if (it!=end()) lasthash = it->first; + for (HashMmap::iterator it = begin(); 1; ++it) { + if (it == end() || lasthash != it->first) { + if (it != end()) lasthash = it->first; if (num_in_bucket) { - if (dist.find(num_in_bucket)==dist.end()) { + if (dist.find(num_in_bucket) == dist.end()) { dist.insert(make_pair(num_in_bucket, 1)); } else { ++dist[num_in_bucket]; @@ -174,22 +171,23 @@ void V3Hashed::dumpFile(const string& filename, bool tree) { } num_in_bucket = 0; } - if (it==end()) break; + if (it == end()) break; num_in_bucket++; } - *logp <<"\n*** STATS:\n"<::iterator it=dist.begin(); it!=dist.end(); ++it) { - *logp<<" "<first<<" "<second<::iterator it = dist.begin(); it != dist.end(); ++it) { + *logp << " " << std::setw(9) << it->first << " " << std::setw(12) << it->second + << endl; } - *logp <<"\n*** Dump:\n"<first) { lasthash = it->first; - *logp <<" "<first<first << endl; } - *logp <<"\t"<second<second << endl; // Dumping the entire tree may make nearly N^2 sized dumps, // because the nodes under this one may also be in the hash table! if (tree) it->second->dumpTree(*logp, " "); @@ -197,14 +195,13 @@ void V3Hashed::dumpFile(const string& filename, bool tree) { } V3Hashed::iterator V3Hashed::findDuplicate(AstNode* nodep, V3HashedUserSame* checkp) { - UINFO(8," findD "<user4p(), nodep, "Called findDuplicate on non-hashed node"); - std::pair eqrange + std::pair eqrange = mmap().equal_range(nodeHash(nodep)); for (HashMmap::iterator eqit = eqrange.first; eqit != eqrange.second; ++eqit) { AstNode* node2p = eqit->second; - if (nodep != node2p - && (!checkp || checkp->isSame(nodep, node2p)) + if (nodep != node2p && (!checkp || checkp->isSame(nodep, node2p)) && sameNodes(nodep, node2p)) { return eqit; } diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index f1721588a..13aa8735b 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -127,11 +127,10 @@ private: } virtual void visit(AstPragma* nodep) VL_OVERRIDE { if (nodep->pragType() == AstPragmaType::INLINE_MODULE) { - // UINFO(0,"PRAG MARK "<v3error("Inline pragma not under a module"); // LCOV_EXCL_LINE - } else if (m_modp->user2() == CIL_MAYBE - || m_modp->user2() == CIL_NOTSOFT) { + } else if (m_modp->user2() == CIL_MAYBE || m_modp->user2() == CIL_NOTSOFT) { m_modp->user2(CIL_USER); } // Remove so don't propagate to upper cell... @@ -199,14 +198,13 @@ private: // If a mod*#refs is < this # nodes, can inline it bool doit = ((allowed == CIL_USER) || ((allowed == CIL_MAYBE) - && (refs == 1 - || statements < INLINE_MODS_SMALLER + && (refs == 1 || statements < INLINE_MODS_SMALLER || v3Global.opt.inlineMult() < 1 || refs * statements < v3Global.opt.inlineMult()))); // Packages aren't really "under" anything so they confuse this algorithm if (VN_IS(modp, Package)) doit = false; UINFO(4, " Inline=" << doit << " Possible=" << allowed << " Refs=" << refs - << " Stmts=" << statements << " " << modp << endl); + << " Stmts=" << statements << " " << modp << endl); modp->user1(doit); } } @@ -247,9 +245,7 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstCell* nodep) VL_OVERRIDE { - nodep->user4p(nodep->clonep()); - } + virtual void visit(AstCell* nodep) VL_OVERRIDE { nodep->user4p(nodep->clonep()); } //-------------------- virtual void visit(AstNodeStmt*) VL_OVERRIDE {} // Accelerate virtual void visit(AstNodeMath*) VL_OVERRIDE {} // Accelerate @@ -328,36 +324,30 @@ private: // remove the change detection on the output variable. UINFO(9, "public pin assign: " << exprvarrefp << endl); UASSERT_OBJ(!nodep->isNonOutput(), nodep, "Outputs only - inputs use AssignAlias"); - m_modp->addStmtp( - new AstAssignW(nodep->fileline(), - new AstVarRef(nodep->fileline(), exprvarrefp->varp(), true), - new AstVarRef(nodep->fileline(), nodep, false))); + m_modp->addStmtp(new AstAssignW( + nodep->fileline(), new AstVarRef(nodep->fileline(), exprvarrefp->varp(), true), + new AstVarRef(nodep->fileline(), nodep, false))); } else if (nodep->isSigPublic() && VN_IS(nodep->dtypep(), UnpackArrayDType)) { // Public variable at this end and it is an unpacked array. We need to assign // instead of aliased, because otherwise it will pass V3Slice and invalid // code will be emitted. UINFO(9, "assign to public and unpacked: " << nodep << endl); - m_modp->addStmtp( - new AstAssignW(nodep->fileline(), - new AstVarRef(nodep->fileline(), exprvarrefp->varp(), true), - new AstVarRef(nodep->fileline(), nodep, false))); + m_modp->addStmtp(new AstAssignW( + nodep->fileline(), new AstVarRef(nodep->fileline(), exprvarrefp->varp(), true), + new AstVarRef(nodep->fileline(), nodep, false))); } else if (nodep->isIfaceRef()) { - m_modp->addStmtp( - new AstAssignVarScope(nodep->fileline(), - new AstVarRef(nodep->fileline(), nodep, true), - new AstVarRef(nodep->fileline(), - exprvarrefp->varp(), false))); + m_modp->addStmtp(new AstAssignVarScope( + nodep->fileline(), new AstVarRef(nodep->fileline(), nodep, true), + new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false))); AstNode* nodebp = exprvarrefp->varp(); nodep->fileline()->modifyStateInherit(nodebp->fileline()); nodebp->fileline()->modifyStateInherit(nodep->fileline()); } else { // Do to inlining child's variable now within the same // module, so a AstVarRef not AstVarXRef below - m_modp->addStmtp( - new AstAssignAlias(nodep->fileline(), - new AstVarRef(nodep->fileline(), nodep, true), - new AstVarRef(nodep->fileline(), - exprvarrefp->varp(), false))); + m_modp->addStmtp(new AstAssignAlias( + nodep->fileline(), new AstVarRef(nodep->fileline(), nodep, true), + new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false))); AstNode* nodebp = exprvarrefp->varp(); nodep->fileline()->modifyStateInherit(nodebp->fileline()); nodebp->fileline()->modifyStateInherit(nodep->fileline()); @@ -406,7 +396,8 @@ private: virtual void visit(AstVarRef* nodep) VL_OVERRIDE { if (nodep->varp()->user2p() // It's being converted to an alias. && !nodep->varp()->user3() - && !VN_IS(nodep->backp(), AssignAlias)) { // Don't constant propagate aliases (we just made) + // Don't constant propagate aliases (we just made) + && !VN_IS(nodep->backp(), AssignAlias)) { AstConst* exprconstp = VN_CAST(nodep->varp()->user2p(), Const); AstVarRef* exprvarrefp = VN_CAST(nodep->varp()->user2p(), VarRef); if (exprconstp) { @@ -551,10 +542,10 @@ private: } // Clone original module - if (debug() >= 9) { nodep->dumpTree(cout, "inlcell:"); } - // if (debug()>=9) { nodep->modp()->dumpTree(cout,"oldmod:"); } + if (debug() >= 9) nodep->dumpTree(cout, "inlcell:"); + // if (debug() >= 9) nodep->modp()->dumpTree(cout, "oldmod:"); AstNodeModule* newmodp = nodep->modp()->cloneTree(false); - if (debug() >= 9) { newmodp->dumpTree(cout, "newmod:"); } + if (debug() >= 9) newmodp->dumpTree(cout, "newmod:"); // Clear var markings and find cell cross references AstNode::user2ClearTree(); AstNode::user4ClearTree(); @@ -575,8 +566,9 @@ private: UASSERT_OBJ(pinNewVarp, pinOldVarp, "Cloning failed"); AstNode* connectRefp = pinp->exprp(); - UASSERT_OBJ(VN_IS(connectRefp, Const) || VN_IS(connectRefp, VarRef), pinp, - "Unknown interconnect type; pinReconnectSimple should have cleared up"); + UASSERT_OBJ( + VN_IS(connectRefp, Const) || VN_IS(connectRefp, VarRef), pinp, + "Unknown interconnect type; pinReconnectSimple should have cleared up"); V3Inst::checkOutputShort(pinp); // Propagate any attributes across the interconnect @@ -624,7 +616,7 @@ public: m_modp = NULL; iterate(nodep); } - virtual ~InlineVisitor() { + virtual ~InlineVisitor() { // V3Stats::addStat("Optimizations, Inlined cells", m_statCells); } }; @@ -668,8 +660,7 @@ private: if (!irdtp) continue; AstCell* cellp; - if ((cellp = VN_CAST(fromVarp->user1p(), Cell)) - || (cellp = irdtp->cellp())) { + if ((cellp = VN_CAST(fromVarp->user1p(), Cell)) || (cellp = irdtp->cellp())) { varp->user1p(cellp); string alias = m_scope + "__DOT__" + pinp->name(); cellp->addIntfRefp(new AstIntfRef(pinp->fileline(), alias)); diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index caa68d056..aa602b75e 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -41,19 +41,19 @@ private: // NODE STATE // Cleared each Cell: // AstPin::user1p() -> bool. True if created assignment already - AstUser1InUse m_inuser1; + AstUser1InUse m_inuser1; // STATE - AstCell* m_cellp; // Current cell + AstCell* m_cellp; // Current cell // METHODS VL_DEBUG_FUNC; // Declare debug() // VISITORS virtual void visit(AstCell* nodep) VL_OVERRIDE { - UINFO(4," CELL "< ASSIGNW(VARXREF(p),expr) (if sub's input) // or ASSIGNW(expr,VARXREF(p)) (if sub's output) - UINFO(4," PIN "<user1()) { // Simplify it V3Inst::pinReconnectSimple(nodep, m_cellp, false); } if (!nodep->exprp()) return; // No-connect - if (debug()>=9) nodep->dumpTree(cout, " Pin_oldb: "); + if (debug() >= 9) nodep->dumpTree(cout, " Pin_oldb: "); V3Inst::checkOutputShort(nodep); // Use user1p on the PIN to indicate we created an assign for this pin if (!nodep->user1SetOnce()) { @@ -78,27 +78,28 @@ private: if (nodep->modVarp()->isInoutish()) { nodep->v3fatalSrc("Unsupported: Verilator is a 2-state simulator"); } else if (nodep->modVarp()->isWritable()) { - AstNode* rhsp = new AstVarXRef(exprp->fileline(), - nodep->modVarp(), m_cellp->name(), false); + AstNode* rhsp + = new AstVarXRef(exprp->fileline(), nodep->modVarp(), m_cellp->name(), false); AstAssignW* assp = new AstAssignW(exprp->fileline(), exprp, rhsp); m_cellp->addNextHere(assp); } else if (nodep->modVarp()->isNonOutput()) { // Don't bother moving constants now, // we'll be pushing the const down to the cell soon enough. - AstNode* assp = new AstAssignW - (exprp->fileline(), - new AstVarXRef(exprp->fileline(), nodep->modVarp(), m_cellp->name(), true), - exprp); + AstNode* assp = new AstAssignW( + exprp->fileline(), + new AstVarXRef(exprp->fileline(), nodep->modVarp(), m_cellp->name(), true), + exprp); m_cellp->addNextHere(assp); - if (debug()>=9) assp->dumpTree(cout, " _new: "); + if (debug() >= 9) assp->dumpTree(cout, " _new: "); } else if (nodep->modVarp()->isIfaceRef() || (VN_IS(nodep->modVarp()->subDTypep(), UnpackArrayDType) - && VN_IS(VN_CAST(nodep->modVarp()->subDTypep(), - UnpackArrayDType)->subDTypep(), IfaceRefDType))) { + && VN_IS(VN_CAST(nodep->modVarp()->subDTypep(), UnpackArrayDType) + ->subDTypep(), + IfaceRefDType))) { // Create an AstAssignVarScope for Vars to Cells so we can // link with their scope later - AstNode* lhsp = new AstVarXRef(exprp->fileline(), - nodep->modVarp(), m_cellp->name(), false); + AstNode* lhsp + = new AstVarXRef(exprp->fileline(), nodep->modVarp(), m_cellp->name(), false); const AstVarRef* refp = VN_CAST(exprp, VarRef); const AstVarXRef* xrefp = VN_CAST(exprp, VarXRef); UASSERT_OBJ(refp || xrefp, exprp, @@ -117,7 +118,8 @@ private: virtual void visit(AstUdpTable* nodep) VL_OVERRIDE { if (!v3Global.opt.bboxUnsup()) { // If we support primitives, update V3Undriven to remove special case - nodep->v3error("Unsupported: Verilog 1995 UDP Tables. Use --bbox-unsup to ignore tables."); + nodep->v3error("Unsupported: Verilog 1995 UDP Tables. " + "Use --bbox-unsup to ignore tables."); } } @@ -145,15 +147,15 @@ class InstDeModVarVisitor : public AstNVisitor { // Expand all module variables, and save names for later reference private: // STATE - typedef std::map VarNameMap; - VarNameMap m_modVarNameMap; // Per module, name of cloned variables + typedef std::map VarNameMap; + VarNameMap m_modVarNameMap; // Per module, name of cloned variables VL_DEBUG_FUNC; // Declare debug() // VISITORS virtual void visit(AstVar* nodep) VL_OVERRIDE { if (VN_IS(nodep->dtypep(), IfaceRefDType)) { - UINFO(8," dm-1-VAR "<name(), nodep)); } AstVar* find(const string& name) { @@ -176,15 +178,17 @@ public: } } void dump() { - for (VarNameMap::iterator it=m_modVarNameMap.begin(); it!=m_modVarNameMap.end(); ++it) { - cout<<"-namemap: "<first<<" -> "<second<first << " -> " << it->second << endl; } } + public: // CONSTRUCTORS explicit InstDeModVarVisitor() {} void main(AstNodeModule* nodep) { - UINFO(8," dmMODULE "< VarNameMap; + typedef std::map VarNameMap; VL_DEBUG_FUNC; // Declare debug() @@ -209,12 +213,12 @@ private: virtual void visit(AstVar* nodep) VL_OVERRIDE { if (VN_IS(nodep->dtypep(), UnpackArrayDType) && VN_IS(VN_CAST(nodep->dtypep(), UnpackArrayDType)->subDTypep(), IfaceRefDType)) { - UINFO(8," dv-vec-VAR "<dtypep(), UnpackArrayDType); AstNode* prevp = NULL; for (int i = arrdtype->lsb(); i <= arrdtype->msb(); ++i) { string varNewName = nodep->name() + "__BRA__" + cvtToStr(i) + "__KET__"; - UINFO(8,"VAR name insert "<subDTypep(), IfaceRefDType)->cloneTree(false); @@ -234,13 +238,16 @@ private: } } if (prevp) nodep->addNextHere(prevp); - if (prevp && debug()==9) { prevp->dumpTree(cout, "newintf: "); cout << endl; } + if (prevp && debug() == 9) { + prevp->dumpTree(cout, "newintf: "); + cout << endl; + } } iterateChildren(nodep); } virtual void visit(AstCell* nodep) VL_OVERRIDE { - UINFO(4," CELL "<modp(), nodep, "Unlinked"); m_deModVars.main(nodep->modp()); @@ -249,14 +256,14 @@ private: m_cellRangep = nodep->rangep(); AstVar* ifaceVarp = VN_CAST(nodep->nextp(), Var); - bool isIface = ifaceVarp - && VN_IS(ifaceVarp->dtypep(), UnpackArrayDType) - && VN_IS(VN_CAST(ifaceVarp->dtypep(), - UnpackArrayDType)->subDTypep(), IfaceRefDType); + bool isIface = ifaceVarp && VN_IS(ifaceVarp->dtypep(), UnpackArrayDType) + && VN_IS(VN_CAST(ifaceVarp->dtypep(), UnpackArrayDType)->subDTypep(), + IfaceRefDType); // Make all of the required clones for (int i = 0; i < m_cellRangep->elementsConst(); i++) { - m_instSelNum = m_cellRangep->littleEndian() ? (m_cellRangep->elementsConst() - 1 - i) : i; + m_instSelNum + = m_cellRangep->littleEndian() ? (m_cellRangep->elementsConst() - 1 - i) : i; int instNum = m_cellRangep->lsbConst() + i; AstCell* newp = nodep->cloneTree(false); @@ -266,15 +273,16 @@ private: // Somewhat illogically, we need to rename the original name of the cell too. // as that is the name users expect for dotting // The spec says we add [x], but that won't work in C... - newp->name(newp->name()+"__BRA__"+cvtToStr(instNum)+"__KET__"); - newp->origName(newp->origName()+"__BRA__"+cvtToStr(instNum)+"__KET__"); - UINFO(8," CELL loop "<name(newp->name() + "__BRA__" + cvtToStr(instNum) + "__KET__"); + newp->origName(newp->origName() + "__BRA__" + cvtToStr(instNum) + "__KET__"); + UINFO(8, " CELL loop " << newp << endl); // If this AstCell is actually an interface instantiation, also clone the IfaceRef // within the same parent module as the cell if (isIface) { AstUnpackArrayDType* arrdtype = VN_CAST(ifaceVarp->dtypep(), UnpackArrayDType); - AstIfaceRefDType* origIfaceRefp = VN_CAST(arrdtype->subDTypep(), IfaceRefDType); + AstIfaceRefDType* origIfaceRefp + = VN_CAST(arrdtype->subDTypep(), IfaceRefDType); origIfaceRefp->cellp(NULL); AstVar* varNewp = ifaceVarp->cloneTree(false); AstIfaceRefDType* ifaceRefp @@ -283,14 +291,21 @@ private: ifaceRefp->cellp(newp); ifaceRefp->cellName(newp->name()); varNewp->name(varNewp->name() + "__BRA__" + cvtToStr(instNum) + "__KET__"); - varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(instNum) + "__KET__"); + varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(instNum) + + "__KET__"); varNewp->dtypep(ifaceRefp); newp->addNextHere(varNewp); - if (debug()==9) { varNewp->dumpTree(cout, "newintf: "); cout << endl; } + if (debug() == 9) { + varNewp->dumpTree(cout, "newintf: "); + cout << endl; + } } // Fixup pins iterateAndNextNull(newp->pinsp()); - if (debug()==9) { newp->dumpTree(cout, "newcell: "); cout<dumpTree(cout, "newcell: "); + cout << endl; + } } // Done. Delete original @@ -299,7 +314,8 @@ private: ifaceVarp->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(ifaceVarp), ifaceVarp); } - nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); + nodep->unlinkFrBack(); + VL_DO_DANGLING(pushDeletep(nodep), nodep); } else { m_cellRangep = NULL; iterateChildren(nodep); @@ -310,66 +326,66 @@ private: // Any non-direct pins need reconnection with a part-select if (!nodep->exprp()) return; // No-connect if (m_cellRangep) { - UINFO(4," PIN "<modVarp()->width(); int expwidth = nodep->exprp()->width(); - std::pair pinDim = nodep->modVarp()->dtypep()->dimensions(false); - std::pair expDim = nodep->exprp()->dtypep()->dimensions(false); - UINFO(4," PINVAR "<modVarp()<exprp()< pinDim = nodep->modVarp()->dtypep()->dimensions(false); + std::pair expDim = nodep->exprp()->dtypep()->dimensions(false); + UINFO(4, " PINVAR " << nodep->modVarp() << endl); + UINFO(4, " EXP " << nodep->exprp() << endl); + UINFO(4, " pinwidth ew=" << expwidth << " pw=" << pinwidth << " ed=" << expDim.first + << "," << expDim.second << " pd=" << pinDim.first << "," + << pinDim.second << endl); + if (expDim.first == pinDim.first && expDim.second == pinDim.second + 1) { // Connection to array, where array dimensions match the instant dimension AstRange* rangep = VN_CAST(nodep->exprp()->dtypep(), UnpackArrayDType)->rangep(); int arraySelNum = rangep->littleEndian() - ? (rangep->elementsConst() - 1 - m_instSelNum) : m_instSelNum; + ? (rangep->elementsConst() - 1 - m_instSelNum) + : m_instSelNum; AstNode* exprp = nodep->exprp()->unlinkFrBack(); exprp = new AstArraySel(exprp->fileline(), exprp, arraySelNum); nodep->exprp(exprp); } else if (expwidth == pinwidth) { // NOP: Arrayed instants: widths match so connect to each instance - } else if (expwidth == pinwidth*m_cellRangep->elementsConst()) { + } else if (expwidth == pinwidth * m_cellRangep->elementsConst()) { // Arrayed instants: one bit for each of the instants (each // assign is 1 pinwidth wide) if (m_cellRangep->littleEndian()) { nodep->exprp()->v3warn( LITENDIAN, "Little endian cell range connecting to vector: MSB < LSB of cell range: " - <lsbConst()<<":"<msbConst()); + << m_cellRangep->lsbConst() << ":" << m_cellRangep->msbConst()); } AstNode* exprp = nodep->exprp()->unlinkFrBack(); bool inputPin = nodep->modVarp()->isNonOutput(); - if (!inputPin && !VN_IS(exprp, VarRef) - && !VN_IS(exprp, Concat) // V3Const will collapse the SEL with the one we're about to make - && !VN_IS(exprp, Sel)) { // V3Const will collapse the SEL with the one we're about to make - nodep->v3error("Unsupported: Per-bit array instantiations with output connections to non-wires."); + if (!inputPin + && !VN_IS(exprp, VarRef) + // V3Const will collapse the SEL with the one we're about to make + && !VN_IS(exprp, Concat) && !VN_IS(exprp, Sel)) { + nodep->v3error("Unsupported: Per-bit array instantiations with output " + "connections to non-wires."); // Note spec allows more complicated matches such as slices and such } - exprp = new AstSel(exprp->fileline(), exprp, - pinwidth*m_instSelNum, - pinwidth); + exprp = new AstSel(exprp->fileline(), exprp, pinwidth * m_instSelNum, pinwidth); nodep->exprp(exprp); } else { nodep->v3fatalSrc("Width mismatch; V3Width should have errored out."); } } else if (AstArraySel* arrselp = VN_CAST(nodep->exprp(), ArraySel)) { if (AstUnpackArrayDType* arrp = VN_CAST(arrselp->lhsp()->dtypep(), UnpackArrayDType)) { - if (!VN_IS(arrp->subDTypep(), IfaceRefDType)) - return; + if (!VN_IS(arrp->subDTypep(), IfaceRefDType)) return; V3Const::constifyParamsEdit(arrselp->rhsp()); const AstConst* constp = VN_CAST(arrselp->rhsp(), Const); if (!constp) { - nodep->v3error("Unsupported: Non-constant index when passing interface to module"); + nodep->v3error( + "Unsupported: Non-constant index when passing interface to module"); return; } string index = AstNode::encodeNumber(constp->toSInt()); AstVarRef* varrefp = VN_CAST(arrselp->lhsp(), VarRef); - AstVarXRef* newp = new AstVarXRef(nodep->fileline(), - varrefp->name()+"__BRA__"+index+"__KET__", - "", true); + AstVarXRef* newp = new AstVarXRef( + nodep->fileline(), varrefp->name() + "__BRA__" + index + "__KET__", "", true); newp->dtypep(nodep->modVarp()->dtypep()); newp->packagep(varrefp->packagep()); arrselp->addNextHere(newp); @@ -378,8 +394,7 @@ private: } else { AstVar* pinVarp = nodep->modVarp(); AstUnpackArrayDType* pinArrp = VN_CAST(pinVarp->dtypep(), UnpackArrayDType); - if (!pinArrp || !VN_IS(pinArrp->subDTypep(), IfaceRefDType)) - return; + if (!pinArrp || !VN_IS(pinArrp->subDTypep(), IfaceRefDType)) return; AstNode* prevp = NULL; AstNode* prevPinp = NULL; // Clone the var referenced by the pin, and clone each var referenced by the varref @@ -406,9 +421,9 @@ private: } } if (!varNewp) { - if (debug()>=9) m_deModVars.dump(); + if (debug() >= 9) m_deModVars.dump(); nodep->v3fatalSrc("Module dearray failed for " - <width() > rhsp->width()) { - rhsp = (rhsp->isSigned() - ? static_cast(new AstExtendS(fl, rhsp)) - : static_cast(new AstExtend (fl, rhsp))); - rhsp->dtypeFrom(cmpWidthp); // Need proper widthMin, which may differ from AstSel created above + rhsp = (rhsp->isSigned() ? static_cast(new AstExtendS(fl, rhsp)) + : static_cast(new AstExtend(fl, rhsp))); + // Need proper widthMin, which may differ from AstSel created above + rhsp->dtypeFrom(cmpWidthp); } else if (cmpWidthp->width() < rhsp->width()) { rhsp = new AstSel(fl, rhsp, 0, cmpWidthp->width()); - rhsp->dtypeFrom(cmpWidthp); // Need proper widthMin, which may differ from AstSel created above + // Need proper widthMin, which may differ from AstSel created above + rhsp->dtypeFrom(cmpWidthp); } // else don't change dtype, as might be e.g. array of something return rhsp; } public: - static AstAssignW* pinReconnectSimple(AstPin* pinp, AstCell* cellp, - bool forTristate, bool alwaysCvt) { + static AstAssignW* pinReconnectSimple(AstPin* pinp, AstCell* cellp, bool forTristate, + bool alwaysCvt) { // If a pin connection is "simple" leave it as-is // Else create a intermediate wire to perform the interconnect // Return the new assignment, if one was made @@ -504,40 +520,33 @@ public: AstAssignW* assignp = NULL; if (connectRefp) connBasicp = VN_CAST(connectRefp->varp()->dtypep(), BasicDType); // - if (!alwaysCvt - && connectRefp - && connectRefp->varp()->dtypep()->sameTree(pinVarp->dtypep()) + if (!alwaysCvt && connectRefp && connectRefp->varp()->dtypep()->sameTree(pinVarp->dtypep()) && !connectRefp->varp()->isSc()) { // Need the signal as a 'shell' to convert types // Done. Same data type - } else if (!alwaysCvt - && connectRefp - && connectRefp->varp()->isIfaceRef()) { + } else if (!alwaysCvt && connectRefp && connectRefp->varp()->isIfaceRef()) { // Done. Interface - } else if (!alwaysCvt - && connectXRefp - && connectXRefp->varp() + } else if (!alwaysCvt && connectXRefp && connectXRefp->varp() && connectXRefp->varp()->isIfaceRef()) { - } else if (!alwaysCvt - && connBasicp - && pinBasicp + } else if (!alwaysCvt && connBasicp && pinBasicp && connBasicp->width() == pinBasicp->width() && connBasicp->lsb() == pinBasicp->lsb() - && !connectRefp->varp()->isSc() // Need the signal as a 'shell' to convert types + && !connectRefp->varp() + ->isSc() // Need the signal as a 'shell' to convert types && connBasicp->width() == pinVarp->width()) { // Done. One to one interconnect won't need a temporary variable. } else if (!alwaysCvt && !forTristate && VN_IS(pinp->exprp(), Const)) { // Done. Constant. } else { // Make a new temp wire - //if (1||debug()>=9) { pinp->dumpTree(cout, "-in_pin:"); } + // if (1 || debug() >= 9) { pinp->dumpTree(cout, "-in_pin:"); } V3Inst::checkOutputShort(pinp); AstNode* pinexprp = pinp->exprp()->unlinkFrBack(); - string newvarname = (string(pinVarp->isWritable() ? "__Vcellout" : "__Vcellinp") - // Prevent name conflict if both tri & non-tri add signals - +(forTristate?"t":"") - +"__"+cellp->name()+"__"+pinp->name()); - AstVar* newvarp = new AstVar(pinVarp->fileline(), - AstVarType::MODULETEMP, newvarname, pinVarp); + string newvarname + = (string(pinVarp->isWritable() ? "__Vcellout" : "__Vcellinp") + // Prevent name conflict if both tri & non-tri add signals + + (forTristate ? "t" : "") + "__" + cellp->name() + "__" + pinp->name()); + AstVar* newvarp + = new AstVar(pinVarp->fileline(), AstVarType::MODULETEMP, newvarname, pinVarp); // Important to add statement next to cell, in case there is a // generate with same named cell cellp->addNextHere(newvarp); @@ -547,8 +556,8 @@ public: } else if (pinVarp->isWritable()) { // See also V3Inst AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false); - UINFO(5,"pinRecon width "<width()<<" >? " - <width()<<" >? "<width()<width() << " >? " << rhsp->width() << " >? " + << pinexprp->width() << endl); rhsp = extendOrSel(pinp->fileline(), rhsp, pinVarp); pinp->exprp(new AstVarRef(newvarp->fileline(), newvarp, true)); AstNode* rhsSelp = extendOrSel(pinp->fileline(), rhsp, pinexprp); @@ -556,13 +565,12 @@ public: } else { // V3 width should have range/extended to make the widths correct assignp = new AstAssignW(pinp->fileline(), - new AstVarRef(pinp->fileline(), newvarp, true), - pinexprp); + new AstVarRef(pinp->fileline(), newvarp, true), pinexprp); pinp->exprp(new AstVarRef(pinexprp->fileline(), newvarp, false)); } if (assignp) cellp->addNextHere(assignp); - //if (debug()) { pinp->dumpTree(cout, "- out:"); } - //if (debug()) { assignp->dumpTree(cout, "- aout:"); } + // if (debug()) { pinp->dumpTree(cout, "- out:"); } + // if (debug()) { assignp->dumpTree(cout, "- aout:"); } } return assignp; } @@ -571,20 +579,19 @@ public: //###################################################################### // Inst class functions -AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, - bool forTristate, bool alwaysCvt) { +AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, bool forTristate, + bool alwaysCvt) { return InstStatic::pinReconnectSimple(pinp, cellp, forTristate, alwaysCvt); } void V3Inst::checkOutputShort(AstPin* nodep) { if (nodep->modVarp()->direction() == VDirection::OUTPUT) { - if (VN_IS(nodep->exprp(), Const) - || VN_IS(nodep->exprp(), Extend) + if (VN_IS(nodep->exprp(), Const) || VN_IS(nodep->exprp(), Extend) || (VN_IS(nodep->exprp(), Concat) && (VN_IS(VN_CAST(nodep->exprp(), Concat)->lhsp(), Const)))) { // Uses v3warn for error, as might be found multiple times nodep->v3warn(E_PORTSHORT, "Output port is connected to a constant pin," - " electrical short"); + " electrical short"); } } } @@ -593,17 +600,13 @@ void V3Inst::checkOutputShort(AstPin* nodep) { // Inst class visitor void V3Inst::instAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } void V3Inst::dearrayAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 6); } diff --git a/src/V3Life.cpp b/src/V3Life.cpp index 08f674015..f8788bafe 100644 --- a/src/V3Life.cpp +++ b/src/V3Life.cpp @@ -42,7 +42,7 @@ class LifeState { // NODE STATE // See below - AstUser1InUse m_inuser1; + AstUser1InUse m_inuser1; // STATE public: @@ -56,8 +56,8 @@ public: ~LifeState() { V3Stats::addStatSum("Optimizations, Lifetime assign deletions", m_statAssnDel); V3Stats::addStatSum("Optimizations, Lifetime constant prop", m_statAssnCon); - for (std::vector::iterator it = m_unlinkps.begin(); - it != m_unlinkps.end(); ++it) { + for (std::vector::iterator it = m_unlinkps.begin(); it != m_unlinkps.end(); + ++it) { (*it)->unlinkFrBack(); (*it)->deleteTree(); } @@ -70,10 +70,12 @@ public: // Structure for each variable encountered class LifeVarEntry { - AstNodeAssign* m_assignp; // Last assignment to this varscope, NULL if no longer relevant - AstConst* m_constp; // Known constant value - bool m_setBeforeUse; // First access was a set (and thus block above may have a set that can be deleted - bool m_everSet; // Was ever assigned (and thus above block may not preserve constant propagation) + AstNodeAssign* m_assignp; // Last assignment to this varscope, NULL if no longer relevant + AstConst* m_constp; // Known constant value + // First access was a set (and thus block above may have a set that can be deleted + bool m_setBeforeUse; + // Was ever assigned (and thus above block may not preserve constant propagation) + bool m_everSet; inline void init(bool setBeforeUse) { m_assignp = NULL; @@ -81,19 +83,23 @@ class LifeVarEntry { m_setBeforeUse = setBeforeUse; m_everSet = false; } + public: class SIMPLEASSIGN {}; class COMPLEXASSIGN {}; class CONSUMED {}; LifeVarEntry(SIMPLEASSIGN, AstNodeAssign* assp) { - init(true); simpleAssign(assp); + init(true); + simpleAssign(assp); } explicit LifeVarEntry(COMPLEXASSIGN) { - init(false); complexAssign(); + init(false); + complexAssign(); } explicit LifeVarEntry(CONSUMED) { - init(false); consumed(); + init(false); + consumed(); } ~LifeVarEntry() {} inline void simpleAssign(AstNodeAssign* assp) { // New simple A=.... assignment @@ -127,9 +133,9 @@ class LifeBlock { // LIFE MAP // For each basic block, we'll make a new map of what variables that if/else is changing typedef std::map LifeMap; - LifeMap m_map; // Current active lifetime map for current scope - LifeBlock* m_aboveLifep; // Upper life, or NULL - LifeState* m_statep; // Current global state + LifeMap m_map; // Current active lifetime map for current scope + LifeBlock* m_aboveLifep; // Upper life, or NULL + LifeState* m_statep; // Current global state VL_DEBUG_FUNC; // Declare debug() @@ -148,11 +154,11 @@ public: // we just don't optimize any public sigs // Check the var entry, and remove if appropriate if (AstNode* oldassp = entp->assignp()) { - UINFO(7," PREV: "<4) oldassp->dumpTree(cout, " REMOVE/SAMEBLK "); + if (debug() > 4) oldassp->dumpTree(cout, " REMOVE/SAMEBLK "); entp->complexAssign(); VL_DO_DANGLING(m_statep->pushUnlinkDeletep(oldassp), oldassp); ++m_statep->m_statAssnDel; @@ -161,8 +167,8 @@ public: } void simpleAssign(AstVarScope* nodep, AstNodeAssign* assp) { // Do we have a old assignment we can nuke? - UINFO(4," ASSIGNof: "<second.complexAssign(); @@ -189,14 +195,14 @@ public: if (!varrefp->varp()->isSigPublic()) { // Aha, variable is constant; substitute in. // We'll later constant propagate - UINFO(4," replaceconst: "<replaceWith(constp->cloneTree(false)); VL_DO_DANGLING(varrefp->deleteTree(), varrefp); ++m_statep->m_statAssnCon; return; // **DONE, no longer a var reference** } } - UINFO(4," usage: "<second.consumed(); } else { m_map.insert(make_pair(nodep, LifeVarEntry(LifeVarEntry::CONSUMED()))); @@ -205,7 +211,7 @@ public: void complexAssignFind(AstVarScope* nodep) { LifeMap::iterator it = m_map.find(nodep); if (it != m_map.end()) { - UINFO(4," casfind: "<first<first << endl); it->second.complexAssign(); } else { m_map.insert(make_pair(nodep, LifeVarEntry(LifeVarEntry::COMPLEXASSIGN()))); @@ -222,7 +228,7 @@ public: void lifeToAbove() { // Any varrefs under a if/else branch affect statements outside and after the if/else if (!m_aboveLifep) v3fatalSrc("Pushing life when already at the top level"); - for (LifeMap::iterator it = m_map.begin(); it!=m_map.end(); ++it) { + for (LifeMap::iterator it = m_map.begin(); it != m_map.end(); ++it) { AstVarScope* nodep = it->first; m_aboveLifep->complexAssignFind(nodep); if (it->second.everSet()) { @@ -236,36 +242,33 @@ public: } void dualBranch(LifeBlock* life1p, LifeBlock* life2p) { // Find any common sets on both branches of IF and propagate upwards - //life1p->lifeDump(); - //life2p->lifeDump(); + // life1p->lifeDump(); + // life2p->lifeDump(); AstNode::user1ClearTree(); // user1p() used on entire tree - for (LifeMap::iterator it = life1p->m_map.begin(); it!=life1p->m_map.end(); ++it) { + for (LifeMap::iterator it = life1p->m_map.begin(); it != life1p->m_map.end(); ++it) { // When the if branch sets a var before it's used, mark that variable if (it->second.setBeforeUse()) it->first->user1(1); } - for (LifeMap::iterator it = life2p->m_map.begin(); it!=life2p->m_map.end(); ++it) { + for (LifeMap::iterator it = life2p->m_map.begin(); it != life2p->m_map.end(); ++it) { // When the else branch sets a var before it's used AstVarScope* nodep = it->first; if (it->second.setBeforeUse() && nodep->user1()) { // Both branches set the var, we can remove the assignment before the IF. - UINFO(4,"DUALBRANCH "<lifeDump(); + // this->lifeDump(); } // DEBUG void lifeDump() { - UINFO(5, " LifeMap:"<second.setBeforeUse()?"[F] ":" ") - <first<second.assignp()) { - UINFO(5, " Ass: "<second.assignp()<second.setBeforeUse() ? "[F] " : " ") << it->first + << endl); + if (it->second.assignp()) { // + UINFO(5, " Ass: " << it->second.assignp() << endl); } } } @@ -277,16 +280,16 @@ public: class LifeVisitor : public AstNVisitor { private: // STATE - LifeState* m_statep; // Current state - bool m_sideEffect; // Side effects discovered in assign RHS - bool m_noopt; // Disable optimization of variables in this block - bool m_tracingCall; // Iterating into a CCall to a CFunc + LifeState* m_statep; // Current state + bool m_sideEffect; // Side effects discovered in assign RHS + bool m_noopt; // Disable optimization of variables in this block + bool m_tracingCall; // Iterating into a CCall to a CFunc // LIFE MAP // For each basic block, we'll make a new map of what variables that if/else is changing typedef std::map LifeMap; // cppcheck-suppress memleak // cppcheck bug - it is deleted - LifeBlock* m_lifep; // Current active lifetime map for current scope + LifeBlock* m_lifep; // Current active lifetime map for current scope // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -333,11 +336,11 @@ private: //---- Track control flow changes virtual void visit(AstNodeIf* nodep) VL_OVERRIDE { - UINFO(4," IF "<condp()); LifeBlock* prevLifep = m_lifep; - LifeBlock* ifLifep = new LifeBlock(prevLifep, m_statep); + LifeBlock* ifLifep = new LifeBlock(prevLifep, m_statep); LifeBlock* elseLifep = new LifeBlock(prevLifep, m_statep); { m_lifep = ifLifep; @@ -348,7 +351,7 @@ private: iterateAndNextNull(nodep->elsesp()); } m_lifep = prevLifep; - UINFO(4," join "<dualBranch(ifLifep, elseLifep); // For the next assignments, clear any variables that were read or written in the block @@ -380,7 +383,7 @@ private: iterateAndNextNull(nodep->incsp()); } m_lifep = prevLifep; - UINFO(4," joinfor"<lifeToAbove(); bodyLifep->lifeToAbove(); @@ -401,22 +404,23 @@ private: m_lifep = prevLifep; m_noopt = prev_noopt; } - UINFO(4," joinjump"<lifeToAbove(); VL_DO_DANGLING(delete bodyLifep, bodyLifep); } virtual void visit(AstNodeCCall* nodep) VL_OVERRIDE { - //UINFO(4," CCALL "<funcp()->entryPoint()) { // else is non-inline or public function we optimize separately + // else is non-inline or public function we optimize separately + if (!nodep->funcp()->entryPoint()) { m_tracingCall = true; iterate(nodep->funcp()); } } virtual void visit(AstCFunc* nodep) VL_OVERRIDE { - //UINFO(4," CFUNC "<entryPoint()) return; m_tracingCall = false; if (nodep->dpiImport() && !nodep->pure()) { @@ -439,7 +443,7 @@ private: public: // CONSTRUCTORS LifeVisitor(AstNode* nodep, LifeState* statep) { - UINFO(4," LifeVisitor on "<entryPoint()) { // Usage model 1: Simulate all C code, doing lifetime analysis - LifeVisitor visitor (nodep, m_statep); + LifeVisitor visitor(nodep, m_statep); } } virtual void visit(AstAlways* nodep) VL_OVERRIDE { // Usage model 2: Cleanup basic blocks - LifeVisitor visitor (nodep, m_statep); + LifeVisitor visitor(nodep, m_statep); } virtual void visit(AstInitial* nodep) VL_OVERRIDE { // Usage model 2: Cleanup basic blocks - LifeVisitor visitor (nodep, m_statep); + LifeVisitor visitor(nodep, m_statep); } virtual void visit(AstFinal* nodep) VL_OVERRIDE { // Usage model 2: Cleanup basic blocks - LifeVisitor visitor (nodep, m_statep); + LifeVisitor visitor(nodep, m_statep); } virtual void visit(AstVar*) VL_OVERRIDE {} // Accelerate virtual void visit(AstNodeStmt*) VL_OVERRIDE {} // Accelerate @@ -502,10 +506,10 @@ public: // Life class functions void V3Life::lifeAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3LifePost.cpp b/src/V3LifePost.cpp index b50adc9e2..da75454bb 100644 --- a/src/V3LifePost.cpp +++ b/src/V3LifePost.cpp @@ -43,7 +43,7 @@ class LifePostElimVisitor : public AstNVisitor { private: - bool m_tracingCall; // Iterating into a CCall to a CFunc + bool m_tracingCall; // Iterating into a CCall to a CFunc // NODE STATE // INPUT: @@ -58,7 +58,7 @@ private: AstVarScope* vscp = nodep->varScopep(); UASSERT_OBJ(vscp, nodep, "Scope not assigned"); if (AstVarScope* newvscp = reinterpret_cast(vscp->user4p())) { - UINFO(9, " Replace "<fileline(), newvscp, nodep->lvalue()); nodep->replaceWith(newrefp); VL_DO_DANGLING(nodep->deleteTree(), nodep); @@ -105,11 +105,15 @@ public: struct LifeLocation { const ExecMTask* mtaskp; uint32_t sequence; + public: - LifeLocation() : mtaskp(NULL), sequence(0) {} + LifeLocation() + : mtaskp(NULL) + , sequence(0) {} LifeLocation(const ExecMTask* mtaskp_, uint32_t sequence_) - : mtaskp(mtaskp_), sequence(sequence_) {} - bool operator< (const LifeLocation& b) const { + : mtaskp(mtaskp_) + , sequence(sequence_) {} + bool operator<(const LifeLocation& b) const { unsigned a_id = mtaskp ? mtaskp->id() : 0; unsigned b_id = b.mtaskp ? b.mtaskp->id() : 0; if (a_id < b_id) { return true; } @@ -121,9 +125,11 @@ public: struct LifePostLocation { LifeLocation loc; AstAssignPost* nodep; - LifePostLocation() : nodep(NULL) {} + LifePostLocation() + : nodep(NULL) {} LifePostLocation(LifeLocation loc_, AstAssignPost* nodep_) - : loc(loc_), nodep(nodep_) {} + : loc(loc_) + , nodep(nodep_) {} }; //###################################################################### @@ -134,27 +140,27 @@ private: // NODE STATE // Cleared on entire tree // AstVarScope::user4() -> AstVarScope*: Passed to LifePostElim to substitute this var - AstUser4InUse m_inuser4; + AstUser4InUse m_inuser4; // STATE - uint32_t m_sequence; // Sequence number of assigns/varrefs, + uint32_t m_sequence; // Sequence number of assigns/varrefs, // // local to the current MTask. - const ExecMTask* m_execMTaskp; // Current ExecMTask being processed, + const ExecMTask* m_execMTaskp; // Current ExecMTask being processed, // // or NULL for serial code. - VDouble0 m_statAssnDel; // Statistic tracking - bool m_tracingCall; // Currently tracing a CCall to a CFunc + VDouble0 m_statAssnDel; // Statistic tracking + bool m_tracingCall; // Currently tracing a CCall to a CFunc // Map each varscope to one or more locations where it's accessed. // These maps will not include any ASSIGNPOST accesses: typedef vl_unordered_map > LocMap; - LocMap m_reads; // VarScope read locations - LocMap m_writes; // VarScope write locations + LocMap m_reads; // VarScope read locations + LocMap m_writes; // VarScope write locations // Map each dly var to its AstAssignPost* node and the location thereof typedef vl_unordered_map PostLocMap; - PostLocMap m_assignposts; // AssignPost dly var locations + PostLocMap m_assignposts; // AssignPost dly var locations - const V3Graph* m_mtasksGraphp; // Mtask tracking graph + const V3Graph* m_mtasksGraphp; // Mtask tracking graph vl_unique_ptr m_checker; // METHODS @@ -164,8 +170,7 @@ private: if (a.mtaskp == b.mtaskp) return a.sequence < b.sequence; return m_checker->pathExistsFrom(a.mtaskp, b.mtaskp); } - bool outsideCriticalArea(LifeLocation loc, - const std::set& dlyVarAssigns, + bool outsideCriticalArea(LifeLocation loc, const std::set& dlyVarAssigns, LifeLocation assignPostLoc) { // If loc is before all of dlyVarAssigns, return true. // ("Before" means certain to be ordered before them at execution time.) @@ -189,8 +194,7 @@ private: return true; } void squashAssignposts() { - for (PostLocMap::iterator it = m_assignposts.begin(); - it != m_assignposts.end(); ++it) { + for (PostLocMap::iterator it = m_assignposts.begin(); it != m_assignposts.end(); ++it) { LifePostLocation* app = &it->second; AstVarRef* lhsp = VN_CAST(app->nodep->lhsp(), VarRef); // original var AstVarRef* rhsp = VN_CAST(app->nodep->rhsp(), VarRef); // dly var @@ -246,7 +250,7 @@ private: if (!canScrunch) continue; // Delete and mark so LifePostElimVisitor will get it - UINFO(4," DELETE "<nodep<nodep << endl); dlyVarp->user4p(origVarp); VL_DO_DANGLING(app->nodep->unlinkFrBack()->deleteTree(), app->nodep); ++m_statAssnDel; @@ -262,8 +266,7 @@ private: iterateChildren(nodep); if (v3Global.opt.mtasks()) { - UASSERT_OBJ(m_mtasksGraphp, nodep, - "Should have initted m_mtasksGraphp by now"); + UASSERT_OBJ(m_mtasksGraphp, nodep, "Should have initted m_mtasksGraphp by now"); m_checker.reset(new GraphPathChecker(m_mtasksGraphp)); } else { UASSERT_OBJ(!m_mtasksGraphp, nodep, @@ -277,7 +280,7 @@ private: squashAssignposts(); // Replace any node4p varscopes with the new scope - LifePostElimVisitor visitor (nodep); + LifePostElimVisitor visitor(nodep); } virtual void visit(AstVarRef* nodep) VL_OVERRIDE { // Consumption/generation of a variable, @@ -325,8 +328,8 @@ private: virtual void visit(AstExecGraph* nodep) VL_OVERRIDE { // Treat the ExecGraph like a call to each mtask body m_mtasksGraphp = nodep->depGraphp(); - for (V3GraphVertex* mtaskVxp = m_mtasksGraphp->verticesBeginp(); - mtaskVxp; mtaskVxp = mtaskVxp->verticesNextp()) { + for (V3GraphVertex* mtaskVxp = m_mtasksGraphp->verticesBeginp(); mtaskVxp; + mtaskVxp = mtaskVxp->verticesNextp()) { ExecMTask* mtaskp = dynamic_cast(mtaskVxp); m_execMTaskp = mtaskp; m_sequence = 0; @@ -361,10 +364,8 @@ public: // LifePost class functions void V3LifePost::lifepostAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index 009b3f005..17fe78662 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -51,16 +51,18 @@ public: class LinkCellsVertex : public V3GraphVertex { AstNodeModule* m_modp; + public: LinkCellsVertex(V3Graph* graphp, AstNodeModule* modp) - : V3GraphVertex(graphp), m_modp(modp) {} + : V3GraphVertex(graphp) + , m_modp(modp) {} virtual ~LinkCellsVertex() {} AstNodeModule* modp() const { return m_modp; } virtual string name() const { return modp()->name(); } virtual FileLine* fileline() const { return modp()->fileline(); } // Recursive modules get space for maximum recursion virtual uint32_t rankAdder() const { - return m_modp->recursiveClone() ? (1+v3Global.opt.moduleRecursionDepth()) : 1; + return m_modp->recursiveClone() ? (1 + v3Global.opt.moduleRecursionDepth()) : 1; } }; @@ -74,10 +76,12 @@ public: void LinkCellsGraph::loopsMessageCb(V3GraphVertex* vertexp) { if (LinkCellsVertex* vvertexp = dynamic_cast(vertexp)) { - vvertexp->modp()->v3error("Unsupported: Recursive multiple modules (module instantiates something leading back to itself): " - <modp()->prettyNameQ()<modp()->v3error( + "Unsupported: Recursive multiple modules (module instantiates " + "something leading back to itself): " + << vvertexp->modp()->prettyNameQ() << endl + << V3Error::warnMore() + << "... note: self-recursion (module instantiating itself directly) is supported."); V3Error::abortIfErrors(); } else { // Everything should match above, but... v3fatalSrc("Recursive instantiations"); @@ -97,19 +101,19 @@ private: // AstCell::user2() // bool clone renaming completed // Allocated across all readFiles in V3Global::readFiles: // AstNode::user4p() // VSymEnt* Package and typedef symbol names - AstUser1InUse m_inuser1; - AstUser2InUse m_inuser2; + AstUser1InUse m_inuser1; + AstUser2InUse m_inuser2; // STATE - VInFilter* m_filterp; // Parser filter - V3ParseSym* m_parseSymp; // Parser symbol table + VInFilter* m_filterp; // Parser filter + V3ParseSym* m_parseSymp; // Parser symbol table // Below state needs to be preserved between each module call. - AstNodeModule* m_modp; // Current module - VSymGraph m_mods; // Symbol table of all module names - LinkCellsGraph m_graph; // Linked graph of all cell interconnects - LibraryVertex* m_libVertexp; // Vertex at root of all libraries - V3GraphVertex* m_topVertexp; // Vertex of top module + AstNodeModule* m_modp; // Current module + VSymGraph m_mods; // Symbol table of all module names + LinkCellsGraph m_graph; // Linked graph of all cell interconnects + LibraryVertex* m_libVertexp; // Vertex at root of all libraries + V3GraphVertex* m_topVertexp; // Vertex of top module vl_unordered_set m_declfnWarned; // Files we issued DECLFILENAME on VL_DEBUG_FUNC; // Declare debug() @@ -117,16 +121,17 @@ private: // METHODS V3GraphVertex* vertex(AstNodeModule* nodep) { // Return corresponding vertex for this module - if (!nodep->user1p()) { - nodep->user1p(new LinkCellsVertex(&m_graph, nodep)); - } + if (!nodep->user1p()) nodep->user1p(new LinkCellsVertex(&m_graph, nodep)); return (nodep->user1u().toGraphVertex()); } AstNodeModule* findModuleSym(const string& modName) { VSymEnt* foundp = m_mods.rootp()->findIdFallback(modName); - if (!foundp) return NULL; - else return VN_CAST(foundp->nodep(), NodeModule); + if (!foundp) { + return NULL; + } else { + return VN_CAST(foundp->nodep(), NodeModule); + } } AstNodeModule* resolveModule(AstNode* nodep, const string& modName) { @@ -136,7 +141,7 @@ private: // If file not found, make AstNotFoundModule, rather than error out. // We'll throw the error when we know the module will really be needed. string prettyName = AstNode::prettyName(modName); - V3Parse parser (v3Global.rootp(), m_filterp, m_parseSymp); + V3Parse parser(v3Global.rootp(), m_filterp, m_parseSymp); // true below -> other simulators treat modules in link-found files as library cells parser.parseFile(nodep->fileline(), prettyName, true, ""); V3Error::abortIfErrors(); @@ -147,7 +152,7 @@ private: if (!modp) { // This shouldn't throw a message as parseFile will create // a AstNotFoundModule for us - nodep->v3error("Can't resolve module reference: '"<v3error("Can't resolve module reference: '" << prettyName << "'"); } } return modp; @@ -162,11 +167,11 @@ private: m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue); m_graph.dumpDotFilePrefixed("linkcells"); m_graph.rank(); - for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) { + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { if (LinkCellsVertex* vvertexp = dynamic_cast(itp)) { // +1 so we leave level 1 for the new wrapper we'll make in a moment AstNodeModule* modp = vvertexp->modp(); - modp->level(vvertexp->rank()+1); + modp->level(vvertexp->rank() + 1); if (vvertexp == m_topVertexp && modp->level() != 2) { AstNodeModule* abovep = NULL; if (V3GraphEdge* edgep = vvertexp->inBeginp()) { @@ -175,15 +180,16 @@ private: abovep = eFromVertexp->modp(); } } - v3error("Specified --top-module '"<prettyName() : "UNKNOWN")<<"'"); + v3error("Specified --top-module '" + << v3Global.opt.topModule() + << "' isn't at the top level, it's under another cell '" + << (abovep ? abovep->prettyName() : "UNKNOWN") << "'"); } } } - if (v3Global.opt.topModule()!="" - && !m_topVertexp) { - v3error("Specified --top-module '"<fileline()->filename()) == m_declfnWarned.end()) { m_declfnWarned.insert(nodep->fileline()->filename()); nodep->v3warn(DECLFILENAME, "Filename '" - << nodep->fileline()->filebasenameNoExt() - << "' does not match " << nodep->typeName() - << " name: " << nodep->prettyNameQ()); + << nodep->fileline()->filebasenameNoExt() + << "' does not match " << nodep->typeName() + << " name: " << nodep->prettyNameQ()); } } if (VN_IS(nodep, Iface) || VN_IS(nodep, Package)) { @@ -215,7 +221,7 @@ private: nodep->inLibrary(false); // Safer to make sure it doesn't disappear } if (v3Global.opt.topModule() == "" ? nodep->inLibrary() // Library cells are lower - : !topMatch) { // Any non-specified module is lower + : !topMatch) { // Any non-specified module is lower // Put under a fake vertex so that the graph ranking won't indicate // this is a top level module if (!m_libVertexp) m_libVertexp = new LibraryVertex(&m_graph); @@ -230,7 +236,7 @@ private: virtual void visit(AstIfaceRefDType* nodep) VL_OVERRIDE { // Cell: Resolve its filename. If necessary, parse it. - UINFO(4,"Link IfaceRef: "<ifaceName()); @@ -241,7 +247,7 @@ private: if (!nodep->cellp()) nodep->ifacep(VN_CAST(modp, Iface)); } else if (VN_IS(modp, NotFoundModule)) { // Will error out later } else { - nodep->v3error("Non-interface used as an interface: "<prettyNameQ()); + nodep->v3error("Non-interface used as an interface: " << nodep->prettyNameQ()); } } // Note cannot do modport resolution here; modports are allowed underneath generates @@ -260,7 +266,7 @@ private: // TODO this doesn't allow bind to dotted hier names, that would require // this move to post param, which would mean we do not auto-read modules // and means we cannot compute module levels until later. - UINFO(4,"Link Bind: "<name()); if (modp) { AstNode* cellsp = nodep->cellsp()->unlinkFrBackWithNext(); @@ -268,7 +274,8 @@ private: AstNodeModule* oldModp = m_modp; { m_modp = modp; - modp->addStmtp(cellsp); // Important that this adds to end, as next iterate assumes does all cells + // Important that this adds to end, as next iterate assumes does all cells + modp->addStmtp(cellsp); iterateAndNextNull(cellsp); } m_modp = oldModp; @@ -281,19 +288,18 @@ private: // Execute only once. Complication is that cloning may result in // user1 being set (for pre-clone) so check if user1() matches the // m_mod, if 0 never did it, if !=, it is an unprocessed clone - bool cloned = (nodep->user1p() && nodep->user1p()!=m_modp); - if (nodep->user1p()==m_modp) return; // AstBind and AstNodeModule may call a cell twice + bool cloned = (nodep->user1p() && nodep->user1p() != m_modp); + if (nodep->user1p() == m_modp) return; // AstBind and AstNodeModule may call a cell twice nodep->user1p(m_modp); // if (!nodep->modp() || cloned) { - UINFO(4,"Link Cell: "<modName()); if (cellmodp) { - if (cellmodp == m_modp - || cellmodp->user2p() == m_modp) { - UINFO(1,"Self-recursive module "<user2p() == m_modp) { + UINFO(1, "Self-recursive module " << cellmodp << endl); cellmodp->recursive(true); nodep->recursive(true); if (!cellmodp->recursiveClone()) { @@ -307,27 +313,25 @@ private: AstNodeModule* otherModp = VN_CAST(cellmodp->user2p(), NodeModule); if (!otherModp) { otherModp = cellmodp->cloneTree(false); - otherModp->name(otherModp->name()+"__Vrcm"); + otherModp->name(otherModp->name() + "__Vrcm"); otherModp->user1p(NULL); // Need new vertex otherModp->user2p(cellmodp); otherModp->recursiveClone(true); // user1 etc will retain its pre-clone value cellmodp->user2p(otherModp); v3Global.rootp()->addModulep(otherModp); - new V3GraphEdge(&m_graph, vertex(cellmodp), - vertex(otherModp), 1, false); + new V3GraphEdge(&m_graph, vertex(cellmodp), vertex(otherModp), 1, + false); } cellmodp = otherModp; nodep->modp(cellmodp); - } - else { + } else { // In the Vrcm, which needs to point back to Vrcm flavor // The cell already has the correct resolution (to Vrcm) nodep->modp(cellmodp); // We don't create a V3GraphEdge (as it would be circular) } - } - else { // Non-recursive + } else { // Non-recursive // Track module depths, so can sort list from parent down to children nodep->modp(cellmodp); new V3GraphEdge(&m_graph, vertex(m_modp), vertex(cellmodp), 1, false); @@ -336,19 +340,17 @@ private: } // Remove AstCell(AstPin("",NULL)), it's a side effect of how we parse "()" // the empty middle is identical to the empty rule that must find pins in "(,)". - if (nodep->pinsp() && !nodep->pinsp()->nextp() - && nodep->pinsp()->name() == "" + if (nodep->pinsp() && !nodep->pinsp()->nextp() && nodep->pinsp()->name() == "" && !nodep->pinsp()->exprp()) { pushDeletep(nodep->pinsp()->unlinkFrBackWithNext()); } - if (nodep->paramsp() && !nodep->paramsp()->nextp() - && nodep->paramsp()->name() == "" + if (nodep->paramsp() && !nodep->paramsp()->nextp() && nodep->paramsp()->name() == "" && !nodep->paramsp()->exprp()) { pushDeletep(nodep->paramsp()->unlinkFrBackWithNext()); } // Convert .* to list of pins bool pinStar = false; - for (AstPin* nextp, *pinp = nodep->pinsp(); pinp; pinp=nextp) { + for (AstPin *nextp, *pinp = nodep->pinsp(); pinp; pinp = nextp) { nextp = VN_CAST(pinp->nextp(), Pin); if (pinp->dotStar()) { if (pinStar) pinp->v3error("Duplicate .* in a cell"); @@ -358,40 +360,41 @@ private: } } // Convert unnamed pins to pin number based assignments - for (AstPin* pinp = nodep->pinsp(); pinp; pinp=VN_CAST(pinp->nextp(), Pin)) { - if (pinp->name()=="") pinp->name("__pinNumber"+cvtToStr(pinp->pinNum())); + for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { + if (pinp->name() == "") pinp->name("__pinNumber" + cvtToStr(pinp->pinNum())); } - for (AstPin* pinp = nodep->paramsp(); pinp; pinp=VN_CAST(pinp->nextp(), Pin)) { + for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { pinp->param(true); - if (pinp->name()=="") pinp->name("__paramNumber"+cvtToStr(pinp->pinNum())); + if (pinp->name() == "") pinp->name("__paramNumber" + cvtToStr(pinp->pinNum())); } if (nodep->modp()) { nodep->modName(nodep->modp()->name()); // Note what pins exist vl_unordered_set ports; // Symbol table of all connected port names - for (AstPin* pinp = nodep->pinsp(); pinp; pinp=VN_CAST(pinp->nextp(), Pin)) { - if (pinp->name()=="") pinp->v3error("Connect by position is illegal in .* connected cells"); + for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { + if (pinp->name() == "") + pinp->v3error("Connect by position is illegal in .* connected cells"); if (!pinp->exprp()) { if (pinp->name().substr(0, 11) == "__pinNumber") { - pinp->v3warn(PINNOCONNECT, "Cell pin is not connected: " - <prettyNameQ()); + pinp->v3warn(PINNOCONNECT, + "Cell pin is not connected: " << pinp->prettyNameQ()); } else { pinp->v3warn(PINCONNECTEMPTY, "Cell pin connected by name with empty reference: " - <prettyNameQ()); + << pinp->prettyNameQ()); } } ports.insert(pinp->name()); } // We search ports, rather than in/out declarations as they aren't resolved yet, // and it's easier to do it now than in V3LinkDot when we'd need to repeat steps. - for (AstNode* portnodep = nodep->modp()->stmtsp(); - portnodep; portnodep=portnodep->nextp()) { + for (AstNode* portnodep = nodep->modp()->stmtsp(); portnodep; + portnodep = portnodep->nextp()) { if (const AstPort* portp = VN_CAST(portnodep, Port)) { if (ports.find(portp->name()) == ports.end() - && ports.find("__pinNumber"+cvtToStr(portp->pinNum())) == ports.end()) { + && ports.find("__pinNumber" + cvtToStr(portp->pinNum())) == ports.end()) { if (pinStar) { - UINFO(9," need .* PORT "<fileline(), 0, portp->name(), new AstParseRef(nodep->fileline(), @@ -400,8 +403,8 @@ private: newp->svImplicit(true); nodep->addPinsp(newp); } else { // warn on the CELL that needs it, not the port - nodep->v3warn(PINMISSING, "Cell has missing pin: " - <prettyNameQ()); + nodep->v3warn(PINMISSING, + "Cell has missing pin: " << portp->prettyNameQ()); AstPin* newp = new AstPin(nodep->fileline(), 0, portp->name(), NULL); nodep->addPinsp(newp); } @@ -413,8 +416,9 @@ private: // Cell really is the parent's instantiation of an interface, not a normal module // Make sure we have a variable to refer to this cell, so can . // in the same way that a child does. Rename though to avoid conflict with cell. - // This is quite similar to how classes work; when unpacked classes are better supported - // may remap interfaces to be more like a class. + // This is quite similar to how classes work; when unpacked + // classes are better supported may remap interfaces to be more + // like a class. if (!nodep->hasIfaceVar()) { string varName = nodep->name() + "__Viftop"; // V3LinkDot looks for this naming AstIfaceRefDType* idtypep = new AstIfaceRefDType(nodep->fileline(), nodep->name(), @@ -425,8 +429,8 @@ private: AstVar* varp; if (nodep->rangep()) { AstNodeArrayDType* arrp - = new AstUnpackArrayDType(nodep->fileline(), VFlagChildDType(), - idtypep, nodep->rangep()->cloneTree(true)); + = new AstUnpackArrayDType(nodep->fileline(), VFlagChildDType(), idtypep, + nodep->rangep()->cloneTree(true)); varp = new AstVar(nodep->fileline(), AstVarType::IFACEREF, varName, VFlagChildDType(), arrp); } else { @@ -438,10 +442,8 @@ private: nodep->hasIfaceVar(true); } } - if (nodep->modp()) { - iterateChildren(nodep); - } - UINFO(4," Link Cell done: "<modp()) { iterateChildren(nodep); } + UINFO(4, " Link Cell done: " << nodep << endl); } // Accelerate the recursion @@ -452,17 +454,18 @@ private: // METHODS void readModNames() { // Look at all modules, and store pointers to all module names - for (AstNodeModule* nextp,* nodep = v3Global.rootp()->modulesp(); nodep; nodep=nextp) { + for (AstNodeModule *nextp, *nodep = v3Global.rootp()->modulesp(); nodep; nodep = nextp) { nextp = VN_CAST(nodep->nextp(), NodeModule); AstNodeModule* foundp = findModuleSym(nodep->name()); if (foundp && foundp != nodep) { if (!(foundp->fileline()->warnIsOff(V3ErrorCode::MODDUP) || nodep->fileline()->warnIsOff(V3ErrorCode::MODDUP))) { nodep->v3warn(MODDUP, "Duplicate declaration of module: " - <prettyNameQ()<warnContextPrimary()<warnOther()<<"... Location of original declaration"<warnContextSecondary()); + << nodep->prettyNameQ() << endl + << nodep->warnContextPrimary() << endl + << foundp->warnOther() + << "... Location of original declaration" << endl + << foundp->warnContextSecondary()); } nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); @@ -470,7 +473,7 @@ private: m_mods.rootp()->insert(nodep->name(), new VSymEnt(&m_mods, nodep)); } } - //if (debug()>=9) m_mods.dump(cout, "-syms: "); + // if (debug() >= 9) m_mods.dump(cout, "-syms: "); } public: @@ -491,6 +494,6 @@ public: // Link class functions void V3LinkCells::link(AstNetlist* nodep, VInFilter* filterp, V3ParseSym* parseSymp) { - UINFO(4,__FUNCTION__<<": "< NameScopeSymMap; - typedef std::map ScopeAliasMap; - typedef std::set > ImplicitNameSet; + typedef std::multimap NameScopeSymMap; + typedef std::map ScopeAliasMap; + typedef std::set > ImplicitNameSet; typedef std::vector IfaceVarSyms; - typedef std::vector > IfaceModSyms; + typedef std::vector > IfaceModSyms; - static LinkDotState* s_errorThisp; // Last self, for error reporting only + static LinkDotState* s_errorThisp; // Last self, for error reporting only // MEMBERS - VSymGraph m_syms; // Symbol table - VSymEnt* m_dunitEntp; // $unit entry - NameScopeSymMap m_nameScopeSymMap; // Map of scope referenced by non-pretty textual name - ImplicitNameSet m_implicitNameSet; // For [module][signalname] if we can implicitly create it - ScopeAliasMap m_scopeAliasMap[SAMN__MAX]; // Map of aliases - IfaceVarSyms m_ifaceVarSyms; // List of AstIfaceRefDType's to be imported - IfaceModSyms m_ifaceModSyms; // List of AstIface+Symbols to be processed - bool m_forPrimary; // First link - bool m_forPrearray; // Compress cell__[array] refs - bool m_forScopeCreation; // Remove VarXRefs for V3Scope + VSymGraph m_syms; // Symbol table + VSymEnt* m_dunitEntp; // $unit entry + NameScopeSymMap m_nameScopeSymMap; // Map of scope referenced by non-pretty textual name + ImplicitNameSet m_implicitNameSet; // For [module][signalname] if we can implicitly create it + ScopeAliasMap m_scopeAliasMap[SAMN__MAX]; // Map of aliases + IfaceVarSyms m_ifaceVarSyms; // List of AstIfaceRefDType's to be imported + IfaceModSyms m_ifaceModSyms; // List of AstIface+Symbols to be processed + bool m_forPrimary; // First link + bool m_forPrearray; // Compress cell__[array] refs + bool m_forScopeCreation; // Remove VarXRefs for V3Scope public: - // METHODS VL_DEBUG_FUNC; // Declare debug() - void dump(const string& nameComment="linkdot", bool force=false) { - if (debug()>=6 || force) { - string filename = v3Global.debugFilename(nameComment)+".txt"; - const vl_unique_ptr logp (V3File::new_ofstream(filename)); - if (logp->fail()) v3fatal("Can't write "<= 6 || force) { + string filename = v3Global.debugFilename(nameComment) + ".txt"; + const vl_unique_ptr logp(V3File::new_ofstream(filename)); + if (logp->fail()) v3fatal("Can't write " << filename); std::ostream& os = *logp; m_syms.dump(os); bool first = true; - for (int samn=0; samnfirst<<" ("<first->nodep()->typeName() - <<") <- "<second<<" "<second->nodep()<first << " (" + << it->first->nodep()->typeName() << ") <- " << it->second << " " + << it->second->nodep() << endl; } } } @@ -207,9 +201,9 @@ public: // CONSTRUCTORS LinkDotState(AstNetlist* rootp, VLinkDotStep step) : m_syms(rootp) { - UINFO(4,__FUNCTION__<<": "<prettyTypeName(); + if (VN_IS(nodep, Var)) { + return "variable"; + } else if (VN_IS(nodep, Cell)) { + return "cell"; + } else if (VN_IS(nodep, Task)) { + return "task"; + } else if (VN_IS(nodep, Func)) { + return "function"; + } else if (VN_IS(nodep, Begin)) { + return "block"; + } else if (VN_IS(nodep, Iface)) { + return "interface"; + } else if (VN_IS(nodep, ParamTypeDType)) { + return "parameter type"; + } else { + return nodep->prettyTypeName(); + } } VSymEnt* rootEntp() const { return m_syms.rootp(); } @@ -251,7 +254,7 @@ public: AstNode* fnodep = foundp ? foundp->nodep() : NULL; if (!fnodep) { // Not found, will add in a moment. - } else if (nodep==fnodep) { // Already inserted. + } else if (nodep == fnodep) { // Already inserted. // Good. } else if (foundp->imported()) { // From package // We don't throw VARHIDDEN as if the import is later the symbol @@ -261,29 +264,29 @@ public: // Begin: ... blocks often replicate under genif/genfor, so simply // suppress duplicate checks. See t_gen_forif.v for an example. } else { - UINFO(4,"name "<name - UINFO(4,"Var1 "<name + UINFO(4, "Var1 " << nodep << endl); + UINFO(4, "Var2 " << fnodep << endl); if (nodep->type() == fnodep->type()) { - nodep->v3error("Duplicate declaration of "<prettyNameQ()<warnContextPrimary()<warnOther()<<"... Location of original declaration\n" - <warnContextSecondary()); + nodep->v3error("Duplicate declaration of " + << nodeTextType(fnodep) << ": " << nodep->prettyNameQ() << endl + << nodep->warnContextPrimary() << endl + << fnodep->warnOther() << "... Location of original declaration\n" + << fnodep->warnContextSecondary()); } else { - nodep->v3error("Unsupported in C: "<prettyNameQ()<warnContextPrimary()<warnOther()<<"... Location of original declaration\n" - <warnContextSecondary()); + nodep->v3error("Unsupported in C: " + << ucfirst(nodeTextType(nodep)) << " has the same name as " + << nodeTextType(fnodep) << ": " << nodep->prettyNameQ() << endl + << nodep->warnContextPrimary() << endl + << fnodep->warnOther() << "... Location of original declaration\n" + << fnodep->warnContextSecondary()); } } } void insertDUnit(AstNetlist* nodep) { // $unit on top scope VSymEnt* symp = new VSymEnt(&m_syms, nodep); - UINFO(9," INSERTdunit se"<parentp(rootEntp()); // Needed so backward search can find name of top module symp->fallbackp(NULL); rootEntp()->insert("$unit ", symp); // Space so can never name conflict with user code @@ -294,7 +297,8 @@ public: VSymEnt* insertTopCell(AstNodeModule* nodep, const string& scopename) { // Only called on the module at the very top of the hierarchy VSymEnt* symp = new VSymEnt(&m_syms, nodep); - UINFO(9," INSERTtop se"<parentp(rootEntp()); // Needed so backward search can find name of top module symp->fallbackp(dunitEntp()); // Needed so can find $unit stuff nodep->user1p(symp); @@ -303,13 +307,13 @@ public: if (forScopeCreation()) m_nameScopeSymMap.insert(make_pair(scopename, symp)); return symp; } - VSymEnt* insertCell(VSymEnt* abovep, VSymEnt* modSymp, - AstCell* nodep, const string& scopename) { + VSymEnt* insertCell(VSymEnt* abovep, VSymEnt* modSymp, AstCell* nodep, + const string& scopename) { UASSERT_OBJ(abovep, nodep, "Null symbol table inserting node"); VSymEnt* symp = new VSymEnt(&m_syms, nodep); - UINFO(9," INSERTcel se"<symPrefix(nodep->name() + "__DOT__"); nodep->user1p(symp); checkDuplicate(abovep, nodep, nodep->name()); abovep->reinsert(basename, symp); @@ -358,15 +362,13 @@ public: // However, cells walk the graph, so cells will appear under the begin/ftask itself UASSERT_OBJ(abovep, nodep, "Null symbol table inserting node"); VSymEnt* symp = new VSymEnt(&m_syms, nodep); - UINFO(9," INSERTblk se"<reinsert(name, symp); return symp; @@ -375,8 +377,8 @@ public: AstNodeModule* packagep) { UASSERT_OBJ(abovep, nodep, "Null symbol table inserting node"); VSymEnt* symp = new VSymEnt(&m_syms, nodep); - UINFO(9," INSERTsym se"<subDTypep()); UASSERT_OBJ(ifacerefp, varp, "Non-ifacerefs on list!"); if (!ifacerefp->ifaceViaCellp()) { - if (!ifacerefp->cellp()) { // Probably a NotFoundModule, or a normal module if made mistake + if (!ifacerefp->cellp()) { // Probably a NotFoundModule, or a normal module if + // made mistake ifacerefp->v3error("Cannot find file containing interface: " - <ifaceName())); + << AstNode::prettyNameQ(ifacerefp->ifaceName())); continue; } else { ifacerefp->v3fatalSrc("Unlinked interface"); } } else if (ifacerefp->ifaceViaCellp()->dead()) { ifacerefp->v3error("Parent cell's interface is not found: " - <ifaceName())); + << AstNode::prettyNameQ(ifacerefp->ifaceName())); continue; } VSymEnt* ifaceSymp = getNodeSym(ifacerefp->ifaceViaCellp()); @@ -466,20 +467,20 @@ public: bool ok = false; if (foundp) { if (AstModport* modportp = VN_CAST(foundp->nodep(), Modport)) { - UINFO(4,"Link Modport: "<modportp(modportp); ifOrPortSymp = foundp; ok = true; } } if (!ok) { - string suggest = suggestSymFallback( - ifaceSymp, ifacerefp->modportName(), LinkNodeMatcherModport()); - ifacerefp->modportFileline() - ->v3error("Modport not found under interface " - <prettyNameQ(ifacerefp->ifaceName())<<": " - <prettyNameQ(ifacerefp->modportName())<warnMore()+suggest)); + string suggest = suggestSymFallback(ifaceSymp, ifacerefp->modportName(), + LinkNodeMatcherModport()); + ifacerefp->modportFileline()->v3error( + "Modport not found under interface " + << ifacerefp->prettyNameQ(ifacerefp->ifaceName()) << ": " + << ifacerefp->prettyNameQ(ifacerefp->modportName()) << endl + << (suggest.empty() ? "" : ifacerefp->warnMore() + suggest)); } } // Alias won't expand until interfaces and modport names are known; see notes at top @@ -492,52 +493,59 @@ public: // Track and later insert scope aliases; an interface referenced by // a child cell connecting to that interface // Typically lhsp=VAR w/dtype IFACEREF, rhsp=IFACE cell - UINFO(9," insertScopeAlias se"<nodep(), Cell) - && !VN_IS(VN_CAST(rhsp->nodep(), Cell)->modp(), Iface)), - rhsp->nodep(), "Got a non-IFACE alias RHS"); + UINFO(9, " insertScopeAlias se" << cvtToHex(lhsp) << " se" << cvtToHex(rhsp) << endl); + UASSERT_OBJ( + !(VN_IS(rhsp->nodep(), Cell) && !VN_IS(VN_CAST(rhsp->nodep(), Cell)->modp(), Iface)), + rhsp->nodep(), "Got a non-IFACE alias RHS"); m_scopeAliasMap[samn].insert(make_pair(lhsp, rhsp)); } void computeScopeAliases() { - UINFO(9,"computeIfaceAliases\n"); - for (int samn=0; samnfirst; VSymEnt* srcp = lhsp; while (true) { // Follow chain of aliases up to highest level non-alias ScopeAliasMap::iterator it2 = m_scopeAliasMap[samn].find(srcp); - if (it2 != m_scopeAliasMap[samn].end()) { srcp = it2->second; continue; } - else break; + if (it2 != m_scopeAliasMap[samn].end()) { + srcp = it2->second; + continue; + } else + break; } - UINFO(9," iiasa: Insert alias se"<nodep()->typeName() - <<") <- se"<nodep()<nodep()->typeName() + << ") <- se" << srcp << " " << srcp->nodep() + << endl); + // srcp should be an interface reference pointing to the interface we want to + // import lhsp->importFromIface(symsp(), srcp); // Allow access to objects not permissible to be listed in a modport if (VN_IS(srcp->nodep(), Modport)) { lhsp->importFromIface(symsp(), srcp->parentp(), true); } } - //m_scopeAliasMap[samn].clear(); // Done with it, but put into debug file + // m_scopeAliasMap[samn].clear(); // Done with it, but put into debug file } } + private: VSymEnt* findWithAltFallback(VSymEnt* symp, const string& name, const string& altname) { VSymEnt* findp = symp->findIdFallback(name); if (findp) return findp; if (altname != "") { - UINFO(8," alt fallback\n"); + UINFO(8, " alt fallback\n"); findp = symp->findIdFallback(altname); } return findp; } + public: - VSymEnt* findDotted(VSymEnt* lookupSymp, const string& dotname, - string& baddot, VSymEnt*& okSymp) { + VSymEnt* findDotted(VSymEnt* lookupSymp, const string& dotname, string& baddot, + VSymEnt*& okSymp) { // Given a dotted hierarchy name, return where in scope it is // Note when dotname=="" we just fall through and return lookupSymp - UINFO(8," dottedFind se"<nodep(), Cell) : NULL; // Replicated below - AstCellInline* inlinep = lookupSymp ? VN_CAST(lookupSymp->nodep(), CellInline) : NULL; // Replicated below + AstCell* cellp + = lookupSymp ? VN_CAST(lookupSymp->nodep(), Cell) : NULL; // Replicated below + AstCellInline* inlinep = lookupSymp ? VN_CAST(lookupSymp->nodep(), CellInline) + : NULL; // Replicated below if (VSymEnt* findSymp = findWithAltFallback(lookupSymp, ident, altIdent)) { lookupSymp = findSymp; } // Check this module - cur modname else if ((cellp && cellp->modp()->origName() == ident) - || (inlinep && inlinep->origModName() == ident)) {} + || (inlinep && inlinep->origModName() == ident)) { + } // Move up and check cellname + modname else { bool crossedCell = false; // Crossed a cell boundary while (lookupSymp) { lookupSymp = lookupSymp->parentp(); - cellp = lookupSymp ? VN_CAST(lookupSymp->nodep(), Cell) : NULL; // Replicated above - inlinep = lookupSymp ? VN_CAST(lookupSymp->nodep(), CellInline) : NULL; // Replicated above + cellp = lookupSymp ? VN_CAST(lookupSymp->nodep(), Cell) + : NULL; // Replicated above + inlinep = lookupSymp ? VN_CAST(lookupSymp->nodep(), CellInline) + : NULL; // Replicated above if (lookupSymp) { - UINFO(9," Up to "<modp()->origName() == ident) || (inlinep && inlinep->origModName() == ident)) { break; - } - else if (VSymEnt* findSymp - = findWithAltFallback(lookupSymp, ident, altIdent)) { + } else if (VSymEnt* findSymp + = findWithAltFallback(lookupSymp, ident, altIdent)) { lookupSymp = findSymp; if (crossedCell && VN_IS(lookupSymp->nodep(), Var)) { - UINFO(9," Not found but matches var name in parent " - <symPrefix()=="") ? "" : " as ") - <<((lookupSymp->symPrefix()=="") ? "" : lookupSymp->symPrefix()+dotname) - <<" at se"<symPrefix() == "") ? "" : " as ") + << ((lookupSymp->symPrefix() == "") ? "" : lookupSymp->symPrefix() + dotname) + << " at se" << lookupSymp << endl); string prefix = lookupSymp->symPrefix(); VSymEnt* foundp = NULL; while (!foundp) { @@ -660,8 +670,7 @@ public: lookupSymp->candidateIdFallback(&speller, &matcher); return speller.bestCandidateMsg(name); } - string suggestSymFlat(VSymEnt* lookupSymp, const string& name, - const VNodeMatcher& matcher) { + string suggestSymFlat(VSymEnt* lookupSymp, const string& name, const VNodeMatcher& matcher) { if (!lookupSymp) return ""; VSpellCheck speller; lookupSymp->candidateIdFlat(&speller, &matcher); @@ -677,14 +686,14 @@ class LinkDotFindVisitor : public AstNVisitor { // STATE LinkDotState* m_statep; // State to pass between visitors, including symbol table AstNodeModule* m_packagep; // Current package - VSymEnt* m_modSymp; // Symbol Entry for current module - VSymEnt* m_curSymp; // Symbol Entry for current table, where to lookup/insert - string m_scope; // Scope text - AstBegin* m_beginp; // Current Begin/end block - AstNodeFTask* m_ftaskp; // Current function/task - bool m_inRecursion; // Inside a recursive module - int m_paramNum; // Parameter number, for position based connection - int m_beginNum; // Begin block number, 0=none seen + VSymEnt* m_modSymp; // Symbol Entry for current module + VSymEnt* m_curSymp; // Symbol Entry for current table, where to lookup/insert + string m_scope; // Scope text + AstBegin* m_beginp; // Current Begin/end block + AstNodeFTask* m_ftaskp; // Current function/task + bool m_inRecursion; // Inside a recursive module + int m_paramNum; // Parameter number, for position based connection + int m_beginNum; // Begin block number, 0=none seen bool m_explicitNew; // Hit a "new" function int m_modBeginNum; // Begin block number in module, 0=none seen @@ -697,13 +706,10 @@ class LinkDotFindVisitor : public AstNVisitor { // This is a string string v = literal.substr(1, literal.find('"', 1) - 1); return new AstConst(fl, AstConst::VerilogStringLiteral(), v); - } else if ((literal.find('.') != string::npos) - || (literal.find('e') != string::npos)) { + } else if ((literal.find('.') != string::npos) || (literal.find('e') != string::npos)) { // This may be a real double v = V3ParseImp::parseDouble(literal.c_str(), literal.length(), &success); - if (success) { - return new AstConst(fl, AstConst::RealDouble(), v); - } + if (success) return new AstConst(fl, AstConst::RealDouble(), v); } if (!success) { // This is either an integer or an error @@ -735,7 +741,7 @@ class LinkDotFindVisitor : public AstNVisitor { virtual void visit(AstNetlist* nodep) VL_OVERRIDE { // Process $unit or other packages // Not needed - dotted references not allowed from inside packages - //for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); + // for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); // nodep; nodep=VN_CAST(nodep->nextp(), NodeModule)) { // if (VN_IS(nodep, Package)) {}} @@ -749,17 +755,13 @@ class LinkDotFindVisitor : public AstNVisitor { // (sorted before this is called). // This may not be the module with isTop() set, as early in the steps, // wrapTop may have not been created yet. - if (!nodep->modulesp()) { - nodep->v3error("No top level module found"); - } + if (!nodep->modulesp()) nodep->v3error("No top level module found"); for (AstNodeModule* modp = nodep->modulesp(); modp && modp->level() <= 2; modp = VN_CAST(modp->nextp(), NodeModule)) { - UINFO(8,"Top Module: "<insertTopCell(modp, m_scope); - { - iterate(modp); - } + { iterate(modp); } m_scope = ""; m_curSymp = m_modSymp = NULL; } @@ -768,7 +770,7 @@ class LinkDotFindVisitor : public AstNVisitor { virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { // Called on top module from Netlist, other modules from the cell creating them, // and packages - UINFO(8," "<user2()) { - nodep->v3error("Unsupported: Identically recursive module (module instantiates itself, without changing parameters): " - <origName())); + nodep->v3error("Unsupported: Identically recursive module (module instantiates " + "itself, without changing parameters): " + << AstNode::prettyNameQ(nodep->origName())); } else if (doit) { - UINFO(4," Link Module: "<dead(), nodep, "Module in cell tree mislabeled as dead?"); VSymEnt* upperSymp = m_curSymp ? m_curSymp : m_statep->rootEntp(); AstPackage* pkgp = VN_CAST(nodep, Package); @@ -795,9 +798,9 @@ class LinkDotFindVisitor : public AstNVisitor { nodep->user1p(m_curSymp); } else { m_scope = nodep->name(); - m_curSymp = m_modSymp - = m_statep->insertBlock(upperSymp, nodep->name()+"::", nodep, m_packagep); - UINFO(9, "New module scope "<insertBlock( + upperSymp, nodep->name() + "::", nodep, m_packagep); + UINFO(9, "New module scope " << m_curSymp << endl); } } // @@ -817,34 +820,34 @@ class LinkDotFindVisitor : public AstNVisitor { } else { // !doit // Will be optimized away later // Can't remove now, as our backwards iterator will throw up - UINFO(5, "Module not under any CELL or top - dead module: "<name(); m_curSymp = m_modSymp = m_statep->insertBlock(upperSymp, nodep->name(), nodep, m_packagep); m_statep->insertMap(m_curSymp, m_scope); - UINFO(9, "New module scope "<recursive() && m_inRecursion) return; iterateChildren(nodep); @@ -892,11 +895,11 @@ class LinkDotFindVisitor : public AstNVisitor { VSymEnt* okSymp; aboveSymp = m_statep->findDotted(aboveSymp, scope, baddot, okSymp); UASSERT_OBJ(aboveSymp, nodep, - "Can't find cell insertion point at " - <prettyNameQ()); + "Can't find cell insertion point at " << AstNode::prettyNameQ(baddot) + << " in: " << nodep->prettyNameQ()); } { - m_scope = m_scope+"."+nodep->name(); + m_scope = m_scope + "." + nodep->name(); m_curSymp = m_modSymp = m_statep->insertCell(aboveSymp, m_modSymp, nodep, m_scope); m_beginp = NULL; m_inRecursion = nodep->recursive(); @@ -911,20 +914,20 @@ class LinkDotFindVisitor : public AstNVisitor { m_inRecursion = oldRecursion; } virtual void visit(AstCellInline* nodep) VL_OVERRIDE { - UINFO(5," CELLINLINE under "<name(); string::size_type pos; if ((pos = dottedname.rfind("__DOT__")) != string::npos) { string dotted = dottedname.substr(0, pos); - string ident = dottedname.substr(pos+strlen("__DOT__")); + string ident = dottedname.substr(pos + strlen("__DOT__")); string baddot; VSymEnt* okSymp; aboveSymp = m_statep->findDotted(aboveSymp, dotted, baddot, okSymp); UASSERT_OBJ(aboveSymp, nodep, "Can't find cellinline insertion point at " - <prettyNameQ()); + << AstNode::prettyNameQ(baddot) << " in: " << nodep->prettyNameQ()); m_statep->insertInline(aboveSymp, m_modSymp, nodep, ident); } else { // No __DOT__, just directly underneath m_statep->insertInline(aboveSymp, m_modSymp, nodep, nodep->name()); @@ -935,25 +938,25 @@ class LinkDotFindVisitor : public AstNVisitor { iterateChildren(nodep); } virtual void visit(AstBegin* nodep) VL_OVERRIDE { - UINFO(5," "<forPrimary() && !nodep->user4SetOnce()) { if (nodep->name() == "genblk") { ++m_beginNum; - nodep->name(nodep->name()+cvtToStr(m_beginNum)); + nodep->name(nodep->name() + cvtToStr(m_beginNum)); } } // All blocks are numbered in the standard, IE we start with "genblk1" even if only one. - if (nodep->name()=="" && nodep->unnamed()) { + if (nodep->name() == "" && nodep->unnamed()) { // Unnamed blocks are only important when they contain var // decls, so search for them. (Otherwise adding all the // unnamed#'s would just confuse tracing variables in // places such as tasks, where "task ...; begin ... end" // are common. - for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) { + for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) { if (VN_IS(stmtp, Var)) { ++m_modBeginNum; - nodep->name("unnamedblk"+cvtToStr(m_modBeginNum)); + nodep->name("unnamedblk" + cvtToStr(m_modBeginNum)); break; } } @@ -979,7 +982,7 @@ class LinkDotFindVisitor : public AstNVisitor { } virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { // NodeTask: Remember its name for later resolution - UINFO(5," "<name() == "new") m_explicitNew = true; // Remember the existing symbol table scope @@ -991,13 +994,15 @@ class LinkDotFindVisitor : public AstNVisitor { // Convert the func's range to the output variable // This should probably be done in the Parser instead, as then we could // just attach normal signal attributes to it. - if (nodep->fvarp() - && !VN_IS(nodep->fvarp(), Var)) { + if (nodep->fvarp() && !VN_IS(nodep->fvarp(), Var)) { AstNodeDType* dtypep = VN_CAST(nodep->fvarp(), NodeDType); // If unspecified, function returns one bit; however when we // support NEW() it could also return the class reference. - if (dtypep) dtypep->unlinkFrBack(); - else dtypep = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::LOGIC); + if (dtypep) { + dtypep->unlinkFrBack(); + } else { + dtypep = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::LOGIC); + } AstVar* newvarp = new AstVar(nodep->fileline(), AstVarType::VAR, nodep->name(), VFlagChildDType(), dtypep); // Not dtype resolved yet newvarp->direction(VDirection::OUTPUT); @@ -1006,7 +1011,7 @@ class LinkDotFindVisitor : public AstNVisitor { newvarp->attrIsolateAssign(nodep->attrIsolateAssign()); nodep->addFvarp(newvarp); // Explicit insert required, as the var name shadows the upper level's task name - m_statep->insertSym(m_curSymp, newvarp->name(), newvarp, NULL/*packagep*/); + m_statep->insertSym(m_curSymp, newvarp->name(), newvarp, NULL /*packagep*/); } m_ftaskp = nodep; iterateChildren(nodep); @@ -1035,16 +1040,17 @@ class LinkDotFindVisitor : public AstNVisitor { ins = true; } else if (!findvarp && foundp && m_curSymp->findIdFlat(nodep->name())) { nodep->v3error("Unsupported in C: Variable has same name as " - <nodep()) - <<": "<prettyNameQ()); + << LinkDotState::nodeTextType(foundp->nodep()) << ": " + << nodep->prettyNameQ()); } else if (findvarp != nodep) { - UINFO(4,"DupVar: "<nodep()<parentp())<nodep() << endl); + UINFO(4, " found cur=se" << cvtToHex(m_curSymp) << " ;; parent=se" + << cvtToHex(foundp->parentp()) << endl); if (foundp->parentp() == m_curSymp // Only when on same level && !foundp->imported()) { // and not from package - bool nansiBad = ((findvarp->isDeclTyped() && nodep->isDeclTyped()) - || (findvarp->isIO() && nodep->isIO())); // e.g. !(output && output) + bool nansiBad + = ((findvarp->isDeclTyped() && nodep->isDeclTyped()) + || (findvarp->isIO() && nodep->isIO())); // e.g. !(output && output) bool ansiBad = findvarp->isAnsi() || nodep->isAnsi(); // dup illegal with ANSI if (ansiBad || nansiBad) { bool ansiWarn = ansiBad && !nansiBad; @@ -1053,14 +1059,16 @@ class LinkDotFindVisitor : public AstNVisitor { if (didAnsiWarn++) ansiWarn = false; } nodep->v3error("Duplicate declaration of signal: " - <prettyNameQ()<warnMore() + "... note: ANSI ports must have" - " type declared with the I/O (IEEE 1800-2017 23.2.2.2)\n" - : "") - <warnContextPrimary()<warnOther()<<"... Location of original declaration"<warnContextSecondary()); + << nodep->prettyNameQ() << endl + << (ansiWarn ? nodep->warnMore() + + "... note: ANSI ports must have" + " type declared with the I/O (IEEE " + "1800-2017 23.2.2.2)\n" + : "") + << nodep->warnContextPrimary() << endl + << findvarp->warnOther() + << "... Location of original declaration" << endl + << findvarp->warnContextSecondary()); // Combining most likely reduce other errors findvarp->combineType(nodep); findvarp->fileline()->modifyStateInherit(nodep->fileline()); @@ -1083,15 +1091,17 @@ class LinkDotFindVisitor : public AstNVisitor { } else { // User can disable the message at either point if (!(m_ftaskp && m_ftaskp->dpiImport()) - && (!m_ftaskp || m_ftaskp != foundp->nodep()) // Not the function's variable hiding function + && (!m_ftaskp || m_ftaskp != foundp->nodep()) // Not the function's + // variable hiding function && !nodep->fileline()->warnIsOff(V3ErrorCode::VARHIDDEN) && !foundp->nodep()->fileline()->warnIsOff(V3ErrorCode::VARHIDDEN)) { - nodep->v3warn(VARHIDDEN, "Declaration of signal hides declaration in upper scope: " - <prettyNameQ()<warnContextPrimary()<nodep()->warnOther() - <<"... Location of original declaration\n" - <nodep()->warnContextSecondary()); + nodep->v3warn(VARHIDDEN, + "Declaration of signal hides declaration in upper scope: " + << nodep->prettyNameQ() << endl + << nodep->warnContextPrimary() << endl + << foundp->nodep()->warnOther() + << "... Location of original declaration\n" + << foundp->nodep()->warnContextSecondary()); } ins = true; } @@ -1103,15 +1113,16 @@ class LinkDotFindVisitor : public AstNVisitor { // We first search if the parameter is overwritten and then replace it with a // new value. It will keep the same FileLine information. if (v3Global.opt.hasParameter(nodep->name())) { - AstVar* newp = new AstVar(nodep->fileline(), - AstVarType(AstVarType::GPARAM), - nodep->name(), nodep); + AstVar* newp + = new AstVar(nodep->fileline(), AstVarType(AstVarType::GPARAM), + nodep->name(), nodep); string svalue = v3Global.opt.parameter(nodep->name()); if (AstNode* valuep = parseParamLiteral(nodep->fileline(), svalue)) { newp->valuep(valuep); - UINFO(9," replace parameter "<replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); + UINFO(9, " replace parameter " << nodep << endl); + UINFO(9, " with " << newp << endl); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); nodep = newp; } } @@ -1119,9 +1130,8 @@ class LinkDotFindVisitor : public AstNVisitor { VSymEnt* insp = m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep); if (m_statep->forPrimary() && nodep->isGParam()) { m_paramNum++; - VSymEnt* symp = m_statep->insertSym(m_curSymp, - "__paramNumber"+cvtToStr(m_paramNum), - nodep, m_packagep); + VSymEnt* symp = m_statep->insertSym( + m_curSymp, "__paramNumber" + cvtToStr(m_paramNum), nodep, m_packagep); symp->exported(false); } AstIfaceRefDType* ifacerefp = LinkDotState::ifaceRefFromArray(nodep->subDTypep()); @@ -1166,65 +1176,66 @@ class LinkDotFindVisitor : public AstNVisitor { if (!foundp) { ins = true; } else if (findvarp != nodep) { - UINFO(4,"DupVar: "<parentp() == m_curSymp // Only when on same level && !foundp->imported()) { // and not from package - nodep->v3error("Duplicate declaration of enum value: "<prettyName()<warnContextPrimary()<nodep()->warnOther()<<"... Location of original declaration\n" - <nodep()->warnContextSecondary()); + nodep->v3error("Duplicate declaration of enum value: " + << nodep->prettyName() << endl + << nodep->warnContextPrimary() << endl + << foundp->nodep()->warnOther() + << "... Location of original declaration\n" + << foundp->nodep()->warnContextSecondary()); } else { // User can disable the message at either point if (!nodep->fileline()->warnIsOff(V3ErrorCode::VARHIDDEN) && !foundp->nodep()->fileline()->warnIsOff(V3ErrorCode::VARHIDDEN)) { - nodep->v3warn(VARHIDDEN, "Declaration of enum value hides declaration in upper scope: " - <prettyName()<warnContextPrimary()<nodep()->warnOther() - <<"... Location of original declaration\n" - <warnContextSecondary()); + nodep->v3warn(VARHIDDEN, + "Declaration of enum value hides declaration in upper scope: " + << nodep->prettyName() << endl + << nodep->warnContextPrimary() << endl + << foundp->nodep()->warnOther() + << "... Location of original declaration\n" + << nodep->warnContextSecondary()); } ins = true; } } - if (ins) { - m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep); - } + if (ins) m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep); } virtual void visit(AstPackageImport* nodep) VL_OVERRIDE { - UINFO(4," Link: "<getNodeSym(nodep->packagep()); - if (nodep->name()=="*") { + if (nodep->name() == "*") { if (m_curSymp == m_statep->dunitEntp()) { nodep->v3warn(IMPORTSTAR, "Import::* in $unit scope may pollute global namespace"); } } else { VSymEnt* impp = srcp->findIdFlat(nodep->name()); if (!impp) { - nodep->v3error("Import object not found: '" - <packagep()->prettyName()<<"::"<prettyName()<<"'"); + nodep->v3error("Import object not found: '" << nodep->packagep()->prettyName() + << "::" << nodep->prettyName() << "'"); } } m_curSymp->importFromPackage(m_statep->symsp(), srcp, nodep->name()); - UINFO(9," Link Done: "<getNodeSym(nodep->packagep()); - if (nodep->name()!="*") { + if (nodep->name() != "*") { VSymEnt* impp = srcp->findIdFlat(nodep->name()); if (!impp) { - nodep->v3error("Export object not found: '" - <packagep()->prettyName()<<"::"<prettyName()<<"'"); + nodep->v3error("Export object not found: '" << nodep->packagep()->prettyName() + << "::" << nodep->prettyName() << "'"); } } m_curSymp->exportFromPackage(m_statep->symsp(), srcp, nodep->name()); - UINFO(9," Link Done: "<exportStarStar(m_statep->symsp()); // No longer needed, but can't delete until any multi-instantiated modules are expanded } @@ -1234,7 +1245,7 @@ class LinkDotFindVisitor : public AstNVisitor { public: // CONSTRUCTORS LinkDotFindVisitor(AstNetlist* rootp, LinkDotState* statep) { - UINFO(4,__FUNCTION__<<": "< See LinkDotState // STATE - LinkDotState* m_statep; // State to pass between visitors, including symbol table - AstNodeModule* m_modp; // Current module + LinkDotState* m_statep; // State to pass between visitors, including symbol table + AstNodeModule* m_modp; // Current module int debug() { return LinkDotState::debug(); } @@ -1272,8 +1283,7 @@ private: // Create implicit variable as needed if (VN_IS(nodep, Dot)) { // Not creating a simple implied type, // and implying something else would just confuse later errors - } - else if (VN_IS(nodep, VarRef) || VN_IS(nodep, ParseRef)) { + } else if (VN_IS(nodep, VarRef) || VN_IS(nodep, ParseRef)) { // To prevent user errors, we should only do single bit // implicit vars, however some netlists (MIPS) expect single // bit implicit wires to get created with range 0:0 etc. @@ -1293,9 +1303,9 @@ private: // VISITs virtual void visit(AstTypeTable*) VL_OVERRIDE {} virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { - UINFO(5," "<dead() || !nodep->user4()) { - UINFO(4,"Mark dead module "<forPrearray(), nodep, "Dead module persisted past where should have removed"); // Don't remove now, because we may have a tree of @@ -1321,21 +1331,19 @@ private: virtual void visit(AstDefParam* nodep) VL_OVERRIDE { iterateChildren(nodep); nodep->v3warn(DEFPARAM, "Suggest replace defparam assignment with Verilog 2001 #(." - <prettyName()<<"(...etc...))"); + << nodep->prettyName() << "(...etc...))"); VSymEnt* foundp = m_statep->getNodeSym(nodep)->findIdFallback(nodep->path()); AstCell* cellp = foundp ? VN_CAST(foundp->nodep(), Cell) : NULL; if (!cellp) { - nodep->v3error("In defparam, cell "<path()<<" never declared"); + nodep->v3error("In defparam, cell " << nodep->path() << " never declared"); } else { AstNode* exprp = nodep->rhsp()->unlinkFrBack(); - UINFO(9,"Defparam cell "<path()<<"."<name() - <<" attach-to "<path() << "." << nodep->name() << " attach-to " + << cellp << " <= " << exprp << endl); // Don't need to check the name of the defparam exists. V3Param does. AstPin* pinp = new AstPin(nodep->fileline(), -1, // Pin# not relevant - nodep->name(), - exprp); + nodep->name(), exprp); cellp->addParamsp(pinp); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } @@ -1347,21 +1355,22 @@ private: VSymEnt* foundp = m_statep->getNodeSym(m_modp)->findIdFlat(nodep->name()); AstVar* refp = foundp ? VN_CAST(foundp->nodep(), Var) : NULL; if (!refp) { - nodep->v3error("Input/output/inout declaration not found for port: " - <prettyNameQ()); + nodep->v3error( + "Input/output/inout declaration not found for port: " << nodep->prettyNameQ()); } else if (!refp->isIO() && !refp->isIfaceRef()) { - nodep->v3error("Pin is not an in/out/inout/interface: "<prettyNameQ()); + nodep->v3error("Pin is not an in/out/inout/interface: " << nodep->prettyNameQ()); } else { if (refp->user4()) { - nodep->v3error("Duplicate declaration of port: "<prettyNameQ()<warnContextPrimary()<warnOther()<<"... Location of original declaration\n" - <warnContextSecondary()); + nodep->v3error("Duplicate declaration of port: " + << nodep->prettyNameQ() << endl + << nodep->warnContextPrimary() << endl + << refp->warnOther() << "... Location of original declaration\n" + << refp->warnContextSecondary()); } refp->user4(true); VSymEnt* symp = m_statep->insertSym(m_statep->getNodeSym(m_modp), - "__pinNumber"+cvtToStr(nodep->pinNum()), - refp, NULL/*packagep*/); + "__pinNumber" + cvtToStr(nodep->pinNum()), refp, + NULL /*packagep*/); symp->exported(false); } // Ports not needed any more @@ -1411,7 +1420,7 @@ private: public: // CONSTRUCTORS LinkDotParamVisitor(AstNetlist* rootp, LinkDotState* statep) { - UINFO(4,__FUNCTION__<<": "<forScopeCreation(), nodep, "Scopes should only exist right after V3Scope"); // Using the CELL names, we created all hierarchy. We now need to match this Scope @@ -1452,29 +1460,29 @@ class LinkDotScopeVisitor : public AstNVisitor { virtual void visit(AstVarScope* nodep) VL_OVERRIDE { if (!nodep->varp()->isFuncLocal() && !nodep->varp()->isClassMember()) { VSymEnt* varSymp = m_statep->insertSym(m_modSymp, nodep->varp()->name(), nodep, NULL); - if (nodep->varp()->isIfaceRef() - && nodep->varp()->isIfaceParent()) { - UINFO(9,"Iface parent ref var "<varp()->name()<<" "<varp()->isIfaceRef() && nodep->varp()->isIfaceParent()) { + UINFO(9, "Iface parent ref var " << nodep->varp()->name() << " " << nodep << endl); // Find the interface cell the var references AstIfaceRefDType* dtypep = LinkDotState::ifaceRefFromArray(nodep->varp()->dtypep()); UASSERT_OBJ(dtypep, nodep, "Non AstIfaceRefDType on isIfaceRef() var"); - UINFO(9,"Iface parent dtype "<cellName(); - string baddot; VSymEnt* okSymp; + string baddot; + VSymEnt* okSymp; VSymEnt* cellSymp = m_statep->findDotted(m_modSymp, ifcellname, baddot, okSymp); UASSERT_OBJ(cellSymp, nodep, - "No symbol for interface cell: "<prettyNameQ(ifcellname)); - UINFO(5, " Found interface cell: se"<nodep()<modportName()!="") { + "No symbol for interface cell: " << nodep->prettyNameQ(ifcellname)); + UINFO(5, " Found interface cell: se" << cvtToHex(cellSymp) << " " + << cellSymp->nodep() << endl); + if (dtypep->modportName() != "") { VSymEnt* mpSymp = m_statep->findDotted(m_modSymp, ifcellname, baddot, okSymp); UASSERT_OBJ(mpSymp, nodep, "No symbol for interface modport: " - <prettyNameQ(dtypep->modportName())); + << nodep->prettyNameQ(dtypep->modportName())); cellSymp = mpSymp; - UINFO(5, " Found modport cell: se" - <nodep()<nodep() << endl); } // Interface reference; need to put whole thing into // symtable, but can't clone it now as we may have a later @@ -1491,40 +1499,43 @@ class LinkDotScopeVisitor : public AstNVisitor { virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { // Track aliases created by V3Inline; if we get a VARXREF(aliased_from) // we'll need to replace it with a VARXREF(aliased_to) - if (debug()>=9) nodep->dumpTree(cout, "- alias: "); + if (debug() >= 9) nodep->dumpTree(cout, "- alias: "); AstVarScope* fromVscp = VN_CAST(nodep->lhsp(), VarRef)->varScopep(); - AstVarScope* toVscp = VN_CAST(nodep->rhsp(), VarRef)->varScopep(); + AstVarScope* toVscp = VN_CAST(nodep->rhsp(), VarRef)->varScopep(); UASSERT_OBJ(fromVscp && toVscp, nodep, "Bad alias scopes"); fromVscp->user2p(toVscp); iterateChildren(nodep); } virtual void visit(AstAssignVarScope* nodep) VL_OVERRIDE { - UINFO(5,"ASSIGNVARSCOPE "<=9) nodep->dumpTree(cout, "- avs: "); + UINFO(5, "ASSIGNVARSCOPE " << nodep << endl); + if (debug() >= 9) nodep->dumpTree(cout, "- avs: "); VSymEnt* rhsSymp; { AstVarRef* refp = VN_CAST(nodep->rhsp(), VarRef); AstVarXRef* xrefp = VN_CAST(nodep->rhsp(), VarXRef); UASSERT_OBJ(refp || xrefp, nodep, "Unsupported: Non Var(X)Ref attached to interface pin"); - string inl = ((xrefp && xrefp->inlinedDots().size()) - ? (xrefp->inlinedDots() + "__DOT__") : ""); + string inl + = ((xrefp && xrefp->inlinedDots().size()) ? (xrefp->inlinedDots() + "__DOT__") + : ""); VSymEnt* symp = NULL; string scopename; while (!symp) { - scopename = refp ? refp->name() : (inl.size() ? (inl + xrefp->name()) - : xrefp->name()); - string baddot; VSymEnt* okSymp; + scopename + = refp ? refp->name() : (inl.size() ? (inl + xrefp->name()) : xrefp->name()); + string baddot; + VSymEnt* okSymp; symp = m_statep->findDotted(m_modSymp, scopename, baddot, okSymp); - if (inl == "") - break; + if (inl == "") break; inl = LinkDotState::removeLastInlineScope(inl); } - if (!symp) UINFO(9,"No symbol for interface alias rhs (" - <nodep()<nodep() << endl); rhsSymp = symp; } VSymEnt* lhsSymp; @@ -1534,12 +1545,13 @@ class LinkDotScopeVisitor : public AstNVisitor { UASSERT_OBJ(refp || xrefp, nodep, "Unsupported: Non Var(X)Ref attached to interface pin"); - string scopename = refp ? refp->varp()->name() : xrefp->dotted()+"."+xrefp->name(); - string baddot; VSymEnt* okSymp; + string scopename = refp ? refp->varp()->name() : xrefp->dotted() + "." + xrefp->name(); + string baddot; + VSymEnt* okSymp; VSymEnt* symp = m_statep->findDotted(m_modSymp, scopename, baddot, okSymp); UASSERT_OBJ(symp, nodep, "No symbol for interface alias lhs"); - UINFO(5, " Found a linked scope LHS: "<nodep()<nodep() << endl); lhsSymp = symp; } // Remember the alias - can't do it yet because we may have additional symbols to be added, @@ -1558,7 +1570,7 @@ class LinkDotScopeVisitor : public AstNVisitor { public: // CONSTRUCTORS LinkDotScopeVisitor(AstNetlist* rootp, LinkDotState* statep) { - UINFO(4,__FUNCTION__<<": "<isExport()) nodep->v3error("Unsupported: modport export"); VSymEnt* symp = m_curSymp->findIdFallback(nodep->name()); if (!symp) { - nodep->v3error("Modport item not found: "<prettyNameQ()); + nodep->v3error("Modport item not found: " << nodep->prettyNameQ()); } else if (AstNodeFTask* ftaskp = VN_CAST(symp->nodep(), NodeFTask)) { // Make symbol under modport that points at the _interface_'s var, not the modport. nodep->ftaskp(ftaskp); - VSymEnt* subSymp = m_statep->insertSym(m_curSymp, nodep->name(), - ftaskp, NULL/*package*/); + VSymEnt* subSymp + = m_statep->insertSym(m_curSymp, nodep->name(), ftaskp, NULL /*package*/); m_statep->insertScopeAlias(LinkDotState::SAMN_MODPORT, subSymp, symp); } else { - nodep->v3error("Modport item is not a function/task: "<prettyNameQ()); + nodep->v3error("Modport item is not a function/task: " << nodep->prettyNameQ()); } if (m_statep->forScopeCreation()) { // Done with AstModportFTaskRef. // Delete to prevent problems if we dead-delete pointed to ftask - nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); + nodep->unlinkFrBack(); + VL_DO_DANGLING(pushDeletep(nodep), nodep); } } virtual void visit(AstModportVarRef* nodep) VL_OVERRIDE { - UINFO(5," fiv: "<findIdFallback(nodep->name()); if (!symp) { - nodep->v3error("Modport item not found: "<prettyNameQ()); + nodep->v3error("Modport item not found: " << nodep->prettyNameQ()); } else if (AstVar* varp = VN_CAST(symp->nodep(), Var)) { // Make symbol under modport that points at the _interface_'s var via the modport. // (Need modport still to test input/output markings) nodep->varp(varp); - m_statep->insertSym(m_curSymp, nodep->name(), nodep, NULL/*package*/); + m_statep->insertSym(m_curSymp, nodep->name(), nodep, NULL /*package*/); } else if (AstVarScope* vscp = VN_CAST(symp->nodep(), VarScope)) { // Make symbol under modport that points at the _interface_'s var, not the modport. nodep->varp(vscp->varp()); - m_statep->insertSym(m_curSymp, nodep->name(), vscp, NULL/*package*/); + m_statep->insertSym(m_curSymp, nodep->name(), vscp, NULL /*package*/); } else { - nodep->v3error("Modport item is not a variable: "<prettyNameQ()); + nodep->v3error("Modport item is not a variable: " << nodep->prettyNameQ()); } if (m_statep->forScopeCreation()) { // Done with AstModportVarRef. // Delete to prevent problems if we dead-delete pointed to variable - nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); + nodep->unlinkFrBack(); + VL_DO_DANGLING(pushDeletep(nodep), nodep); } } virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } @@ -1643,7 +1657,7 @@ class LinkDotIfaceVisitor : public AstNVisitor { public: // CONSTRUCTORS LinkDotIfaceVisitor(AstIface* nodep, VSymEnt* curSymp, LinkDotState* statep) { - UINFO(4,__FUNCTION__<<": "<first; VSymEnt* symp = it->second; LinkDotIfaceVisitor(nodep, symp, this); @@ -1672,49 +1686,54 @@ private: // *::user4() -> See LinkDotState // Cleared on Cell // AstVar::user5() // bool. True if pin used in this cell - AstUser3InUse m_inuser3; - AstUser5InUse m_inuser5; + AstUser3InUse m_inuser3; + AstUser5InUse m_inuser5; // TYPES - enum DotPosition { DP_NONE=0, // Not under a DOT - DP_PACKAGE, // {package}:: DOT - DP_SCOPE, // [DOT...] {scope-or-var} DOT - DP_FINAL, // [DOT...] {var-or-func-or-dtype} with no following dots - DP_MEMBER }; // DOT {member-name} [DOT...] + enum DotPosition { + DP_NONE = 0, // Not under a DOT + DP_PACKAGE, // {package}:: DOT + DP_SCOPE, // [DOT...] {scope-or-var} DOT + DP_FINAL, // [DOT...] {var-or-func-or-dtype} with no following dots + DP_MEMBER + }; // DOT {member-name} [DOT...] // STATE - LinkDotState* m_statep; // State, including dotted symbol table - VSymEnt* m_curSymp; // SymEnt for current lookup point - VSymEnt* m_modSymp; // SymEnt for current module - VSymEnt* m_pinSymp; // SymEnt for pin lookups - AstCell* m_cellp; // Current cell - AstNodeModule* m_modp; // Current module - AstNodeFTask* m_ftaskp; // Current function/task - int m_modportNum; // Uniqueify modport numbers + LinkDotState* m_statep; // State, including dotted symbol table + VSymEnt* m_curSymp; // SymEnt for current lookup point + VSymEnt* m_modSymp; // SymEnt for current module + VSymEnt* m_pinSymp; // SymEnt for pin lookups + AstCell* m_cellp; // Current cell + AstNodeModule* m_modp; // Current module + AstNodeFTask* m_ftaskp; // Current function/task + int m_modportNum; // Uniqueify modport numbers struct DotStates { - DotPosition m_dotPos; // Scope part of dotted resolution - VSymEnt* m_dotSymp; // SymEnt for dotted AstParse lookup - AstDot* m_dotp; // Current dot - bool m_unresolved; // Unresolved, needs help from V3Param - AstNode* m_unlinkedScope;// Unresolved scope, needs corresponding VarXRef - bool m_dotErr; // Error found in dotted resolution, ignore upwards - string m_dotText; // String of dotted names found in below parseref + DotPosition m_dotPos; // Scope part of dotted resolution + VSymEnt* m_dotSymp; // SymEnt for dotted AstParse lookup + AstDot* m_dotp; // Current dot + bool m_unresolved; // Unresolved, needs help from V3Param + AstNode* m_unlinkedScope; // Unresolved scope, needs corresponding VarXRef + bool m_dotErr; // Error found in dotted resolution, ignore upwards + string m_dotText; // String of dotted names found in below parseref DotStates() { init(NULL); } ~DotStates() {} void init(VSymEnt* curSymp) { - m_dotPos = DP_NONE; m_dotSymp = curSymp; m_dotp = NULL; - m_dotErr = false; m_dotText = ""; - m_unresolved = false; m_unlinkedScope = NULL; + m_dotPos = DP_NONE; + m_dotSymp = curSymp; + m_dotp = NULL; + m_dotErr = false; + m_dotText = ""; + m_unresolved = false; + m_unlinkedScope = NULL; } string ascii() const { - static const char* const names[] - = { "NONE", "PACKAGE", "SCOPE", "FINAL", "MEMBER" }; + static const char* const names[] = {"NONE", "PACKAGE", "SCOPE", "FINAL", "MEMBER"}; std::ostringstream sstr; - sstr<<"ds="<prettyNameQ()<warnMore()+suggest)); + string suggest = m_statep->suggestSymFallback(moduleSymp, nodep->name(), + LinkNodeMatcherVar()); + nodep->v3error("Signal definition not found, and implicit disabled with " + "`default_nettype: " + << nodep->prettyNameQ() << endl + << (suggest.empty() ? "" : nodep->warnMore() + suggest)); } // Bypass looking for suggestions if IMPLICIT is turned off // as there could be thousands of these suppressed in large netlists else if (!nodep->fileline()->warnIsOff(V3ErrorCode::IMPLICIT)) { - string suggest = m_statep->suggestSymFallback( - moduleSymp, nodep->name(), LinkNodeMatcherVar()); - nodep->v3warn(IMPLICIT, "Signal definition not found, creating implicitly: " - <prettyNameQ()<warnMore()+suggest)); + string suggest = m_statep->suggestSymFallback(moduleSymp, nodep->name(), + LinkNodeMatcherVar()); + nodep->v3warn(IMPLICIT, + "Signal definition not found, creating implicitly: " + << nodep->prettyNameQ() << endl + << (suggest.empty() ? "" : nodep->warnMore() + suggest)); } } - AstVar* newp = new AstVar(nodep->fileline(), AstVarType::WIRE, - nodep->name(), VFlagLogicPacked(), 1); + AstVar* newp = new AstVar(nodep->fileline(), AstVarType::WIRE, nodep->name(), + VFlagLogicPacked(), 1); newp->trace(modp->modTrace()); nodep->varp(newp); modp->addStmtp(newp); // Link it to signal list, must add the variable under the module; // current scope might be lower now - m_statep->insertSym(moduleSymp, newp->name(), newp, NULL/*packagep*/); + m_statep->insertSym(moduleSymp, newp->name(), newp, NULL /*packagep*/); } } AstVar* foundToVarp(const VSymEnt* symp, AstNode* nodep, bool lvalue) { @@ -1765,7 +1786,7 @@ private: AstModportVarRef* snodep = VN_CAST(symp->nodep(), ModportVarRef); AstVar* varp = snodep->varp(); if (lvalue && snodep->direction().isReadOnly()) { - nodep->v3error("Attempt to drive input-only modport: "<prettyNameQ()); + nodep->v3error("Attempt to drive input-only modport: " << nodep->prettyNameQ()); } // else other simulators don't warn about reading, and IEEE doesn't say illegal return varp; } else { @@ -1773,26 +1794,26 @@ private: } } void taskFuncSwapCheck(AstNodeFTaskRef* nodep) { - if (nodep->taskp() && VN_IS(nodep->taskp(), Task) - && VN_IS(nodep, FuncRef)) nodep->v3error("Illegal call of a task as a function: " - <prettyNameQ()); + if (nodep->taskp() && VN_IS(nodep->taskp(), Task) && VN_IS(nodep, FuncRef)) { + nodep->v3error("Illegal call of a task as a function: " << nodep->prettyNameQ()); + } } inline void checkNoDot(AstNode* nodep) { if (VL_UNLIKELY(m_ds.m_dotPos != DP_NONE)) { - //UINFO(9,"ds="<v3error("Syntax Error: Not expecting "<type()<<" under a " - <backp()->type()<<" in dotted expression"); + // UINFO(9, "ds=" << m_ds.ascii() << endl); + nodep->v3error("Syntax Error: Not expecting " << nodep->type() << " under a " + << nodep->backp()->type() + << " in dotted expression"); m_ds.m_dotErr = true; } } - AstVar* makeIfaceModportVar(FileLine* fl, AstCell* cellp, - AstIface* ifacep, AstModport* modportp) { + AstVar* makeIfaceModportVar(FileLine* fl, AstCell* cellp, AstIface* ifacep, + AstModport* modportp) { // Create iface variable, using duplicate var when under same module scope - string varName - = ifacep->name()+"__Vmp__"+modportp->name()+"__Viftop"+cvtToStr(++m_modportNum); - AstIfaceRefDType* idtypep - = new AstIfaceRefDType(fl, modportp->fileline(), - cellp->name(), ifacep->name(), modportp->name()); + string varName = ifacep->name() + "__Vmp__" + modportp->name() + "__Viftop" + + cvtToStr(++m_modportNum); + AstIfaceRefDType* idtypep = new AstIfaceRefDType(fl, modportp->fileline(), cellp->name(), + ifacep->name(), modportp->name()); idtypep->cellp(cellp); AstVar* varp = new AstVar(fl, AstVarType::IFACEREF, varName, VFlagChildDType(), idtypep); varp->isIfaceParent(true); @@ -1800,12 +1821,12 @@ private: return varp; } void markAndCheckPinDup(AstNode* nodep, AstNode* refp, const char* whatp) { - if (refp->user5p() && refp->user5p()!=nodep) { - nodep->v3error("Duplicate "<prettyNameQ()<warnContextPrimary()<user5p()->warnOther() - <<"... Location of original "<user5p()->warnContextSecondary()); + if (refp->user5p() && refp->user5p() != nodep) { + nodep->v3error("Duplicate " << whatp << " connection: " << nodep->prettyNameQ() << endl + << nodep->warnContextPrimary() << endl + << refp->user5p()->warnOther() + << "... Location of original " << whatp << " connection\n" + << refp->user5p()->warnContextSecondary()); } else { refp->user5p(nodep); } @@ -1820,9 +1841,10 @@ private: virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { if (nodep->dead()) return; checkNoDot(nodep); - UINFO(8," "<getNodeSym(nodep); // Until overridden by a SCOPE + m_ds.m_dotSymp = m_curSymp = m_modSymp + = m_statep->getNodeSym(nodep); // Until overridden by a SCOPE m_cellp = NULL; m_modp = nodep; m_modportNum = 0; @@ -1831,7 +1853,7 @@ private: m_ds.m_dotSymp = m_curSymp = m_modSymp = NULL; } virtual void visit(AstScope* nodep) VL_OVERRIDE { - UINFO(8," "<forScopeCreation() && !v3Global.opt.vpi()) { - nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); + nodep->unlinkFrBack(); + VL_DO_DANGLING(pushDeletep(nodep), nodep); } } virtual void visit(AstCell* nodep) VL_OVERRIDE { @@ -1865,9 +1888,9 @@ private: // instantiator's symbols else { m_pinSymp = m_statep->getNodeSym(nodep->modp()); - UINFO(4,"(Backto) Link Cell: "<dumpTree(cout, "linkcell:"); } - //if (debug()) { nodep->modp()->dumpTree(cout, "linkcemd:"); } + UINFO(4, "(Backto) Link Cell: " << nodep << endl); + // if (debug()) nodep->dumpTree(cout, "linkcell:"); + // if (debug()) nodep->modp()->dumpTree(cout, "linkcemd:"); iterateChildren(nodep); m_pinSymp = NULL; } @@ -1891,29 +1914,26 @@ private: return; } string suggest - = (nodep->param() - ? m_statep->suggestSymFlat( - m_pinSymp, nodep->name(), LinkNodeMatcherVarParam()) - : m_statep->suggestSymFlat( - m_pinSymp, nodep->name(), LinkNodeMatcherVarIO())); - nodep->v3error(ucfirst(whatp)<<" not found: "<prettyNameQ()<warnMore()+suggest)); - } - else if (AstVar* refp = VN_CAST(foundp->nodep(), Var)) { + = (nodep->param() ? m_statep->suggestSymFlat(m_pinSymp, nodep->name(), + LinkNodeMatcherVarParam()) + : m_statep->suggestSymFlat(m_pinSymp, nodep->name(), + LinkNodeMatcherVarIO())); + nodep->v3error(ucfirst(whatp) + << " not found: " << nodep->prettyNameQ() << endl + << (suggest.empty() ? "" : nodep->warnMore() + suggest)); + } else if (AstVar* refp = VN_CAST(foundp->nodep(), Var)) { if (!refp->isIO() && !refp->isParam() && !refp->isIfaceRef()) { - nodep->v3error(ucfirst(whatp)<<" is not an in/out/inout/param/interface: " - <prettyNameQ()); + nodep->v3error(ucfirst(whatp) << " is not an in/out/inout/param/interface: " + << nodep->prettyNameQ()); } else { nodep->modVarp(refp); markAndCheckPinDup(nodep, refp, whatp); } - } - else if (AstParamTypeDType* refp = VN_CAST(foundp->nodep(), ParamTypeDType)) { + } else if (AstParamTypeDType* refp = VN_CAST(foundp->nodep(), ParamTypeDType)) { nodep->modPTypep(refp); markAndCheckPinDup(nodep, refp, whatp); - } - else { - nodep->v3error(ucfirst(whatp)<<" not found: "<prettyNameQ()); + } else { + nodep->v3error(ucfirst(whatp) << " not found: " << nodep->prettyNameQ()); } } // Early return() above when deleted @@ -1925,12 +1945,12 @@ private: // DOT(PACKAGEREF, PARSEREF(text)) // DOT(DOT(DOT(PARSEREF(text), ... if (nodep->user3SetOnce()) return; - UINFO(8," "<=9) nodep->dumpTree("-dot-in: "); + if (debug() >= 9) nodep->dumpTree("-dot-in: "); m_ds.init(m_curSymp); // Start from current point } m_ds.m_dotp = nodep; // Always, not just at start @@ -1938,23 +1958,24 @@ private: // m_ds.m_dotText communicates the cell prefix between stages if (VN_IS(nodep->lhsp(), PackageRef)) { - //if (!start) { nodep->lhsp()->v3error("Package reference may not be embedded in dotted reference"); m_ds.m_dotErr=true; } + // if (!start) { nodep->lhsp()->v3error("Package reference may not be embedded in + // dotted reference"); m_ds.m_dotErr=true; } m_ds.m_dotPos = DP_PACKAGE; } else { m_ds.m_dotPos = DP_SCOPE; iterateAndNextNull(nodep->lhsp()); - //if (debug()>=9) nodep->dumpTree("-dot-lho: "); + // if (debug()>=9) nodep->dumpTree("-dot-lho: "); } - if (m_ds.m_unresolved && (VN_IS(nodep->lhsp(), CellRef) - || VN_IS(nodep->lhsp(), CellArrayRef))) { + if (m_ds.m_unresolved + && (VN_IS(nodep->lhsp(), CellRef) || VN_IS(nodep->lhsp(), CellArrayRef))) { m_ds.m_unlinkedScope = nodep->lhsp(); } if (!m_ds.m_dotErr) { // Once something wrong, give up // Top 'final' dot RHS is final RHS, else it's a // DOT(DOT(x,*here*),real-rhs) which we consider a RHS - if (start && m_ds.m_dotPos==DP_SCOPE) m_ds.m_dotPos = DP_FINAL; + if (start && m_ds.m_dotPos == DP_SCOPE) m_ds.m_dotPos = DP_FINAL; iterateAndNextNull(nodep->rhsp()); - //if (debug()>=9) nodep->dumpTree("-dot-rho: "); + // if (debug() >= 9) nodep->dumpTree("-dot-rho: "); } if (start) { AstNode* newp; @@ -1964,7 +1985,7 @@ private: // RHS is what we're left with newp = nodep->rhsp()->unlinkFrBack(); } - if (debug()>=9) newp->dumpTree("-dot-out: "); + if (debug() >= 9) newp->dumpTree("-dot-out: "); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } else { // Dot midpoint @@ -1986,13 +2007,13 @@ private: } virtual void visit(AstParseRef* nodep) VL_OVERRIDE { if (nodep->user3SetOnce()) return; - UINFO(9," linkPARSEREF "<forPrimary() || m_statep->forPrearray(), - nodep, "ParseRefs should no longer exist"); + UASSERT_OBJ(m_statep->forPrimary() || m_statep->forPrearray(), nodep, + "ParseRefs should no longer exist"); DotStates lastStates = m_ds; bool start = (m_ds.m_dotPos == DP_NONE); // Save, as m_dotp will be changed if (start) { @@ -2002,13 +2023,14 @@ private: if (m_ds.m_dotPos == DP_MEMBER) { // Found a Var, everything following is membership. {scope}.{var}.HERE {member} AstNode* varEtcp = m_ds.m_dotp->lhsp()->unlinkFrBack(); - AstNode* newp = new AstMemberSel(nodep->fileline(), varEtcp, - VFlagChildDType(), nodep->name()); - if (m_ds.m_dotErr) nodep->unlinkFrBack(); // Avoid circular node loop on errors - else nodep->replaceWith(newp); + AstNode* newp + = new AstMemberSel(nodep->fileline(), varEtcp, VFlagChildDType(), nodep->name()); + if (m_ds.m_dotErr) + nodep->unlinkFrBack(); // Avoid circular node loop on errors + else + nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - else { + } else { // string expectWhat; bool allowScope = false; @@ -2019,8 +2041,8 @@ private: expectWhat = "scope/variable"; allowScope = true; allowVar = true; - UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), PackageRef), - m_ds.m_dotp->lhsp(), "Bad package link"); + UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), PackageRef), m_ds.m_dotp->lhsp(), + "Bad package link"); packagep = VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep(); UASSERT_OBJ(packagep, m_ds.m_dotp->lhsp(), "Bad package link"); m_ds.m_dotSymp = m_statep->getNodeSym(packagep); @@ -2031,12 +2053,11 @@ private: expectWhat = "scope/variable"; allowScope = true; allowVar = true; - } else if (m_ds.m_dotPos == DP_NONE - || m_ds.m_dotPos == DP_FINAL) { + } else if (m_ds.m_dotPos == DP_NONE || m_ds.m_dotPos == DP_FINAL) { expectWhat = "variable"; allowVar = true; } else { - UINFO(1,"ds="<findDotted(m_ds.m_dotSymp, - nodep->name(), baddot, okSymp); // Maybe NULL + foundp = m_statep->findDotted(m_ds.m_dotSymp, nodep->name(), baddot, + okSymp); // Maybe NULL } else { foundp = m_ds.m_dotSymp->findIdFallback(nodep->name()); } - if (foundp) UINFO(9," found=se"<parentp(); // Container of the var; probably a module or generate begin - string findName = nodep->name()+"__Viftop"; + VSymEnt* parentEntp + = cellEntp->parentp(); // Container of the var; probably a module or + // generate begin + string findName = nodep->name() + "__Viftop"; VSymEnt* ifaceSymp = parentEntp->findIdFallback(findName); AstVar* ifaceRefVarp = ifaceSymp ? VN_CAST(ifaceSymp->nodep(), Var) : NULL; UASSERT_OBJ(ifaceRefVarp, nodep, - "Can't find interface var ref: "<name()); m_ds.m_dotSymp = foundp; m_ds.m_dotPos = DP_SCOPE; - UINFO(9," cell -> iface varref "<nodep()<fileline(), - ifaceRefVarp, false); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); + UINFO(9, " cell -> iface varref " << foundp->nodep() << endl); + AstNode* newp + = new AstVarRef(ifaceRefVarp->fileline(), ifaceRefVarp, false); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); } else if (VN_IS(cellp->modp(), NotFoundModule)) { cellp->modNameFileline()->v3error("Cannot find file containing interface: " - <modp()->prettyNameQ()); + << cellp->modp()->prettyNameQ()); } } - } - else if (AstVar* varp = foundToVarp(foundp, nodep, false)) { + } else if (AstVar* varp = foundToVarp(foundp, nodep, false)) { AstIfaceRefDType* ifacerefp = LinkDotState::ifaceRefFromArray(varp->subDTypep()); if (ifacerefp) { UASSERT_OBJ(ifacerefp->ifaceViaCellp(), ifacerefp, "Unlinked interface"); // Really this is a scope reference into an interface - UINFO(9,"varref-ifaceref "<name()); m_ds.m_dotSymp = m_statep->getNodeSym(ifacerefp->ifaceViaCellp()); m_ds.m_dotPos = DP_SCOPE; ok = true; AstNode* newp = new AstVarRef(nodep->fileline(), varp, false); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - else if (allowVar) { + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } else if (allowVar) { AstNode* newp; if (m_ds.m_dotText != "") { - AstVarXRef* refp = new AstVarXRef(nodep->fileline(), nodep->name(), - m_ds.m_dotText, false); // lvalue'ness computed later + AstVarXRef* refp + = new AstVarXRef(nodep->fileline(), nodep->name(), m_ds.m_dotText, + false); // lvalue'ness computed later refp->varp(varp); if (varp->attrSplitVar()) { - refp->v3warn(SPLITVAR, varp->prettyNameQ() - << " has split_var metacomment but will not be split because" - << " it is accessed from another module via a dot."); + refp->v3warn( + SPLITVAR, + varp->prettyNameQ() + << " has split_var metacomment but will not be split because" + << " it is accessed from another module via a dot."); varp->attrSplitVar(false); } m_ds.m_dotText = ""; @@ -2128,62 +2153,61 @@ private: newp = refp; } else { newp = new AstUnlinkedRef(nodep->fileline(), - VN_CAST(refp, VarXRef), - refp->name(), + VN_CAST(refp, VarXRef), refp->name(), m_ds.m_unlinkedScope->unlinkFrBack()); m_ds.m_unlinkedScope = NULL; m_ds.m_unresolved = false; - } + } } else { newp = refp; } } else { - AstVarRef* refp = new AstVarRef(nodep->fileline(), varp, false); // lvalue'ness computed later + AstVarRef* refp = new AstVarRef(nodep->fileline(), varp, + false); // lvalue'ness computed later refp->packagep(foundp->packagep()); newp = refp; } - UINFO(9," new "<replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); + UINFO(9, " new " << newp << endl); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); m_ds.m_dotPos = DP_MEMBER; ok = true; } - } - else if (AstModport* modportp = VN_CAST(foundp->nodep(), Modport)) { + } else if (AstModport* modportp = VN_CAST(foundp->nodep(), Modport)) { // A scope reference into an interface's modport (not // necessarily at a pin connection) - UINFO(9,"cell-ref-to-modport "<nodep()<nodep() << endl); // Iface was the previously dotted component - if (!m_ds.m_dotSymp - || !VN_IS(m_ds.m_dotSymp->nodep(), Cell) + if (!m_ds.m_dotSymp || !VN_IS(m_ds.m_dotSymp->nodep(), Cell) || !VN_CAST(m_ds.m_dotSymp->nodep(), Cell)->modp() || !VN_IS(VN_CAST(m_ds.m_dotSymp->nodep(), Cell)->modp(), Iface)) { nodep->v3error("Modport not referenced as ." - <prettyNameQ()); + << modportp->prettyNameQ()); } else if (!VN_CAST(m_ds.m_dotSymp->nodep(), Cell)->modp() || !VN_IS(VN_CAST(m_ds.m_dotSymp->nodep(), Cell)->modp(), Iface)) { nodep->v3error("Modport not referenced from underneath an interface: " - <prettyNameQ()); + << modportp->prettyNameQ()); } else { AstCell* cellp = VN_CAST(m_ds.m_dotSymp->nodep(), Cell); UASSERT_OBJ(cellp, nodep, "Modport not referenced from a cell"); AstIface* ifacep = VN_CAST(cellp->modp(), Iface); - //string cellName = m_ds.m_dotText; // Use cellp->name + // string cellName = m_ds.m_dotText; // Use cellp->name m_ds.m_dotText = VString::dot(m_ds.m_dotText, ".", nodep->name()); m_ds.m_dotSymp = m_statep->getNodeSym(modportp); m_ds.m_dotPos = DP_SCOPE; ok = true; - AstVar* varp = makeIfaceModportVar(nodep->fileline(), - cellp, ifacep, modportp); + AstVar* varp = makeIfaceModportVar(nodep->fileline(), cellp, ifacep, modportp); AstVarRef* refp = new AstVarRef(varp->fileline(), varp, false); - nodep->replaceWith(refp); VL_DO_DANGLING(pushDeletep(nodep), nodep); + nodep->replaceWith(refp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); } - } - else if (AstEnumItem* valuep = VN_CAST(foundp->nodep(), EnumItem)) { + } else if (AstEnumItem* valuep = VN_CAST(foundp->nodep(), EnumItem)) { if (allowVar) { - AstNode* newp = new AstEnumItemRef(nodep->fileline(), - valuep, foundp->packagep()); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); + AstNode* newp + = new AstEnumItemRef(nodep->fileline(), valuep, foundp->packagep()); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); ok = true; m_ds.m_dotText = ""; } @@ -2192,37 +2216,38 @@ private: if (!ok) { // Cells/interfaces can't be implicit bool isCell = foundp ? VN_IS(foundp->nodep(), Cell) : false; - bool checkImplicit = (!m_ds.m_dotp && m_ds.m_dotText=="" && !isCell); + bool checkImplicit = (!m_ds.m_dotp && m_ds.m_dotText == "" && !isCell); bool err = !(checkImplicit && m_statep->implicitOk(m_modp, nodep->name())); if (err) { if (foundp) { nodep->v3error("Found definition of '" - <prettyName() - <<"'"<<" as a "<nodep()->typeName() - <<" but expected a "<prettyName() << "'" + << " as a " << foundp->nodep()->typeName() + << " but expected a " << expectWhat); + } else if (m_ds.m_dotText == "") { + UINFO(7, " ErrParseRef curSymp=se" << cvtToHex(m_curSymp) + << " ds=" << m_ds.ascii() << endl); string suggest = m_statep->suggestSymFallback( m_ds.m_dotSymp, nodep->name(), VNodeMatcher()); - nodep->v3error("Can't find definition of "<prettyNameQ()<warnMore()+suggest)); + nodep->v3error("Can't find definition of " + << expectWhat << ": " << nodep->prettyNameQ() << endl + << (suggest.empty() ? "" : nodep->warnMore() + suggest)); } else { nodep->v3error("Can't find definition of " - <<(!baddot.empty() ? AstNode::prettyNameQ(baddot) - : nodep->prettyNameQ()) - <<" in dotted "<prettyName()<<"'"); + << (!baddot.empty() ? AstNode::prettyNameQ(baddot) + : nodep->prettyNameQ()) + << " in dotted " << expectWhat << ": '" + << m_ds.m_dotText + "." + nodep->prettyName() << "'"); if (okSymp) { okSymp->cellErrorScopes(nodep, AstNode::prettyName(m_ds.m_dotText)); } } m_ds.m_dotErr = true; } - if (checkImplicit) { // Else if a scope is allowed, making a signal won't help error cascade + if (checkImplicit) { // Create if implicit, and also if error (so only complain once) + // Else if a scope is allowed, making a signal won't help error cascade AstVarRef* newp = new AstVarRef(nodep->fileline(), nodep->name(), false); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); @@ -2230,9 +2255,7 @@ private: } } } - if (start) { - m_ds = lastStates; - } + if (start) m_ds = lastStates; } virtual void visit(AstVarRef* nodep) VL_OVERRIDE { // VarRef: Resolve its reference @@ -2241,15 +2264,16 @@ private: // No checkNoDot; created and iterated from a parseRef iterateChildren(nodep); if (!nodep->varp()) { - UINFO(9," linkVarRef se"<findIdFallback(nodep->name()); if (AstVar* varp = foundp ? foundToVarp(foundp, nodep, nodep->lvalue()) : NULL) { nodep->varp(varp); - nodep->packagep(foundp->packagep()); // Generally set by parse, but might be an import + // Generally set by parse, but might be an import + nodep->packagep(foundp->packagep()); } if (!nodep->varp()) { - nodep->v3error("Can't find definition of signal, again: "<prettyNameQ()); + nodep->v3error("Can't find definition of signal, again: " << nodep->prettyNameQ()); } } } @@ -2258,33 +2282,38 @@ private: // We always link even if varp() is set, because the module we choose may change // due to creating new modules, flattening, etc. if (nodep->user3SetOnce()) return; - UINFO(8," "<varp(NULL); // Module that is not in hierarchy. We'll be dead code eliminating it later. + // Module that is not in hierarchy. We'll be dead code eliminating it later. + UINFO(9, "Dead module for " << nodep << endl); + nodep->varp(NULL); } else { string baddot; VSymEnt* okSymp; VSymEnt* dotSymp = m_curSymp; // Start search at current scope - if (nodep->inlinedDots()!="") { // Correct for current scope - dotSymp = m_modSymp; // Dotted lookup is always relative to module, as maybe variable name lower down with same scope name we want to ignore (t_math_divw) + if (nodep->inlinedDots() != "") { // Correct for current scope + // Dotted lookup is always relative to module, as maybe + // variable name lower down with same scope name we want to + // ignore (t_math_divw) + dotSymp = m_modSymp; string inl = AstNode::dedotName(nodep->inlinedDots()); dotSymp = m_statep->findDotted(dotSymp, inl, baddot, okSymp); UASSERT_OBJ(dotSymp, nodep, - "Couldn't resolve inlined scope " - <inlinedDots()); + "Couldn't resolve inlined scope " << AstNode::prettyNameQ(baddot) + << " in: " << nodep->inlinedDots()); } - dotSymp = m_statep->findDotted(dotSymp, nodep->dotted(), baddot, okSymp); // Maybe NULL + dotSymp + = m_statep->findDotted(dotSymp, nodep->dotted(), baddot, okSymp); // Maybe NULL if (!m_statep->forScopeCreation()) { VSymEnt* foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot); AstVar* varp = foundp ? foundToVarp(foundp, nodep, nodep->lvalue()) : NULL; nodep->varp(varp); - UINFO(7," Resolved "<varp()) { nodep->v3error("Can't find definition of " - <dotted()+"."+nodep->prettyName()<<"'"); + << AstNode::prettyNameQ(baddot) << " in dotted signal: '" + << nodep->dotted() + "." + nodep->prettyName() << "'"); okSymp->cellErrorScopes(nodep); return; } @@ -2293,8 +2322,8 @@ private: // this and convert to normal VarRefs if (!m_statep->forPrearray() && !m_statep->forScopeCreation()) { if (VN_IS(nodep->dtypep(), IfaceRefDType)) { - AstVarRef* newrefp = new AstVarRef(nodep->fileline(), - nodep->varp(), nodep->lvalue()); + AstVarRef* newrefp + = new AstVarRef(nodep->fileline(), nodep->varp(), nodep->lvalue()); nodep->replaceWith(newrefp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } @@ -2304,24 +2333,24 @@ private: AstVarScope* vscp = foundp ? VN_CAST(foundp->nodep(), VarScope) : NULL; if (!vscp) { nodep->v3error("Can't find varpin scope of " - <dotted()+"."+nodep->prettyName()<<"'"); + << AstNode::prettyNameQ(baddot) << " in dotted signal: '" + << nodep->dotted() + "." + nodep->prettyName() << "'"); okSymp->cellErrorScopes(nodep); } else { while (vscp->user2p()) { // If V3Inline aliased it, pick up the new signal - UINFO(7," Resolved pre-alias "<user2p(), VarScope); } // Convert the VarXRef to a VarRef, so we don't need // later optimizations to deal with VarXRef. nodep->varp(vscp->varp()); nodep->varScopep(vscp); - UINFO(7," Resolved "<fileline(), vscp, nodep->lvalue()); nodep->replaceWith(newvscp); VL_DO_DANGLING(nodep->deleteTree(), nodep); - UINFO(9," new "<forPrimary() && nodep->isIO() && !m_ftaskp && !nodep->user4()) { - nodep->v3error("Input/output/inout does not appear in port list: " - <prettyNameQ()); + nodep->v3error( + "Input/output/inout does not appear in port list: " << nodep->prettyNameQ()); } } virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { if (nodep->user3SetOnce()) return; - UINFO(8," "<lhsp(), PackageRef), - m_ds.m_dotp->lhsp(), "Bad package link"); - UASSERT_OBJ(VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep(), - m_ds.m_dotp->lhsp(), "Bad package link"); + UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), PackageRef), m_ds.m_dotp->lhsp(), + "Bad package link"); + UASSERT_OBJ(VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep(), m_ds.m_dotp->lhsp(), + "Bad package link"); nodep->packagep(VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep()); m_ds.m_dotPos = DP_SCOPE; m_ds.m_dotp = NULL; @@ -2362,8 +2391,7 @@ private: if (m_ds.m_unresolved && m_ds.m_unlinkedScope) { AstNodeFTaskRef* newftaskp = nodep->cloneTree(false); newftaskp->dotted(m_ds.m_dotText); - AstNode* newp = new AstUnlinkedRef(nodep->fileline(), newftaskp, - nodep->name(), + AstNode* newp = new AstUnlinkedRef(nodep->fileline(), newftaskp, nodep->name(), m_ds.m_unlinkedScope->unlinkFrBack()); m_ds.m_unlinkedScope = NULL; m_ds.m_unresolved = false; @@ -2378,8 +2406,8 @@ private: AstNode* varEtcp = m_ds.m_dotp->lhsp()->unlinkFrBack(); AstNode* argsp = NULL; if (nodep->pinsp()) argsp = nodep->pinsp()->unlinkFrBackWithNext(); - AstNode* newp = new AstMethodCall(nodep->fileline(), varEtcp, - VFlagChildDType(), nodep->name(), argsp); + AstNode* newp = new AstMethodCall(nodep->fileline(), varEtcp, VFlagChildDType(), + nodep->name(), argsp); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); return; @@ -2389,9 +2417,10 @@ private: if (nodep->packagep() && nodep->taskp()) { // References into packages don't care about cell hierarchy. } else if (!m_modSymp) { - UINFO(9,"Dead module for "<taskp(NULL); // Module that is not in hierarchy. We'll be dead code eliminating it later. - } else if (nodep->dotted()=="" && nodep->taskp()) { + // Module that is not in hierarchy. We'll be dead code eliminating it later. + UINFO(9, "Dead module for " << nodep << endl); + nodep->taskp(NULL); + } else if (nodep->dotted() == "" && nodep->taskp()) { // Earlier should have setup the links // Might be under a BEGIN we're not processing, so don't relink it } else { @@ -2404,53 +2433,56 @@ private: if (nodep->packagep()) { // Look only in specified package dotSymp = m_statep->getNodeSym(nodep->packagep()); } else { - if (nodep->inlinedDots()!="") { // Correct for current scope - dotSymp = m_modSymp; // Dotted lookup is always relative to module, as maybe variable name lower down with same scope name we want to ignore (t_math_divw) + if (nodep->inlinedDots() != "") { // Correct for current scope + // Dotted lookup is always relative to module, as maybe + // variable name lower down with same scope name we want + // to ignore (t_math_divw) + dotSymp = m_modSymp; string inl = AstNode::dedotName(nodep->inlinedDots()); - UINFO(8," Inlined "<findDotted(dotSymp, inl, baddot, okSymp); if (!dotSymp) { okSymp->cellErrorScopes(nodep); nodep->v3fatalSrc("Couldn't resolve inlined scope " - <inlinedDots()); + << AstNode::prettyNameQ(baddot) + << " in: " << nodep->inlinedDots()); } } - dotSymp = m_statep->findDotted(dotSymp, nodep->dotted(), - baddot, okSymp); // Maybe NULL + dotSymp = m_statep->findDotted(dotSymp, nodep->dotted(), baddot, + okSymp); // Maybe NULL } VSymEnt* foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot); - AstNodeFTask* taskp = foundp ? VN_CAST(foundp->nodep(), NodeFTask) : NULL; // Maybe NULL + AstNodeFTask* taskp + = foundp ? VN_CAST(foundp->nodep(), NodeFTask) : NULL; // Maybe NULL if (taskp) { nodep->taskp(taskp); nodep->packagep(foundp->packagep()); - UINFO(7," Resolved "<v3error("Found definition of '" - <prettyName() - <<"'"<<" as a "<nodep()->typeName() - <<" but expected a task/function"); + << m_ds.m_dotText << (m_ds.m_dotText == "" ? "" : ".") + << nodep->prettyName() << "'" + << " as a " << foundp->nodep()->typeName() + << " but expected a task/function"); } else if (VN_IS(nodep, New) && m_statep->forPrearray()) { // Resolved in V3Width } else if (nodep->dotted() == "") { - string suggest = m_statep->suggestSymFallback( - dotSymp, nodep->name(), LinkNodeMatcherFTask()); + string suggest = m_statep->suggestSymFallback(dotSymp, nodep->name(), + LinkNodeMatcherFTask()); nodep->v3error("Can't find definition of task/function: " - <prettyNameQ()<warnMore()+suggest)); + << nodep->prettyNameQ() << endl + << (suggest.empty() ? "" : nodep->warnMore() + suggest)); } else { - string suggest = m_statep->suggestSymFallback( - dotSymp, nodep->name(), LinkNodeMatcherFTask()); + string suggest = m_statep->suggestSymFallback(dotSymp, nodep->name(), + LinkNodeMatcherFTask()); nodep->v3error("Can't find definition of " - <dotted()+"."+nodep->prettyName()<<"'\n" - <<(suggest.empty() ? "" : nodep->warnMore()+suggest)); + << AstNode::prettyNameQ(baddot) << " in dotted task/function: '" + << nodep->dotted() + "." + nodep->prettyName() << "'\n" + << (suggest.empty() ? "" : nodep->warnMore() + suggest)); okSymp->cellErrorScopes(nodep); } } @@ -2466,8 +2498,9 @@ private: virtual void visit(AstSelBit* nodep) VL_OVERRIDE { if (nodep->user3SetOnce()) return; iterateAndNextNull(nodep->lhsp()); - if (m_ds.m_dotPos == DP_SCOPE) { // Already under dot, so this is {modulepart} DOT {modulepart} - UINFO(9," deferring until after a V3Param pass: "<bitp()->unlinkFrBack(); AstCellArrayRef* newp = new AstCellArrayRef(nodep->fileline(), nodep->fromp()->name(), exprp); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); } } virtual void visit(AstNodePreSel* nodep) VL_OVERRIDE { // Excludes simple AstSelBit, see above if (nodep->user3SetOnce()) return; - if (m_ds.m_dotPos == DP_SCOPE) { // Already under dot, so this is {modulepart} DOT {modulepart} - nodep->v3error("Syntax Error: Range ':', '+:' etc are not allowed in the cell part of a dotted reference"); + if (m_ds.m_dotPos + == DP_SCOPE) { // Already under dot, so this is {modulepart} DOT {modulepart} + nodep->v3error("Syntax Error: Range ':', '+:' etc are not allowed in the cell part of " + "a dotted reference"); m_ds.m_dotErr = true; return; } @@ -2511,21 +2547,21 @@ private: iterateChildren(nodep); } virtual void visit(AstBegin* nodep) VL_OVERRIDE { - UINFO(5," "<name() != "") { m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep); - UINFO(5," cur=se"<user3SetOnce()) return; if (m_ds.m_dotp && m_ds.m_dotPos == DP_PACKAGE) { - UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), PackageRef), - m_ds.m_dotp->lhsp(), "Bad package link"); - UASSERT_OBJ(VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep(), - m_ds.m_dotp->lhsp(), "Bad package link"); + UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), PackageRef), m_ds.m_dotp->lhsp(), + "Bad package link"); + UASSERT_OBJ(VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep(), m_ds.m_dotp->lhsp(), + "Bad package link"); nodep->packagep(VN_CAST(m_ds.m_dotp->lhsp(), PackageRef)->packagep()); m_ds.m_dotPos = DP_SCOPE; m_ds.m_dotp = NULL; @@ -2599,20 +2635,17 @@ private: if (AstTypedef* defp = foundp ? VN_CAST(foundp->nodep(), Typedef) : NULL) { nodep->refDTypep(defp->subDTypep()); nodep->packagep(foundp->packagep()); - } - else if (AstParamTypeDType* defp = foundp ? VN_CAST(foundp->nodep(), ParamTypeDType) - : NULL) { + } else if (AstParamTypeDType* defp + = foundp ? VN_CAST(foundp->nodep(), ParamTypeDType) : NULL) { nodep->refDTypep(defp); nodep->packagep(foundp->packagep()); - } - else if (AstClass* defp = foundp ? VN_CAST(foundp->nodep(), Class) : NULL) { + } else if (AstClass* defp = foundp ? VN_CAST(foundp->nodep(), Class) : NULL) { AstClassRefDType* newp = new AstClassRefDType(nodep->fileline(), defp); newp->packagep(foundp->packagep()); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); return; - } - else { + } else { if (foundp) UINFO(1, "Found sym node: " << foundp->nodep() << endl); nodep->v3error("Can't find typedef: " << nodep->prettyNameQ()); } @@ -2625,14 +2658,15 @@ private: checkNoDot(nodep); VSymEnt* foundp = m_curSymp->findIdFallback(nodep->name()); AstNodeFTask* taskp = foundp ? VN_CAST(foundp->nodep(), NodeFTask) : NULL; - if (!taskp) { nodep->v3error("Can't find definition of exported task/function: " - <prettyNameQ()); } - else if (taskp->dpiExport()) { + if (!taskp) { + nodep->v3error( + "Can't find definition of exported task/function: " << nodep->prettyNameQ()); + } else if (taskp->dpiExport()) { nodep->v3error("Function was already DPI Exported, duplicate not allowed: " - <prettyNameQ()); + << nodep->prettyNameQ()); } else { taskp->dpiExport(true); - if (nodep->cname()!="") taskp->cname(nodep->cname()); + if (nodep->cname() != "") taskp->cname(nodep->cname()); } VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } @@ -2652,15 +2686,15 @@ private: VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } virtual void visit(AstCellRef* nodep) VL_OVERRIDE { - UINFO(5," AstCellRef: "<=5 || v3Global.opt.dumpTree()>=9) { + if (LinkDotState::debug() >= 5 || v3Global.opt.dumpTree() >= 9) { v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot.tree")); } - LinkDotState state (rootp, step); - LinkDotFindVisitor visitor(rootp,&state); - if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) { + LinkDotState state(rootp, step); + LinkDotFindVisitor visitor(rootp, &state); + if (LinkDotState::debug() >= 5 || v3Global.opt.dumpTree() >= 9) { v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-find.tree")); } if (step == LDS_PRIMARY || step == LDS_PARAMED) { // Initial link stage, resolve parameters - LinkDotParamVisitor visitors(rootp,&state); - if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) { + LinkDotParamVisitor visitors(rootp, &state); + if (LinkDotState::debug() >= 5 || v3Global.opt.dumpTree() >= 9) { v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-param.tree")); } - } - else if (step == LDS_ARRAYED) {} - else if (step == LDS_SCOPED) { + } else if (step == LDS_ARRAYED) { + } else if (step == LDS_SCOPED) { // Well after the initial link when we're ready to operate on the flat design, // process AstScope's. This needs to be separate pass after whole hierarchy graph created. - LinkDotScopeVisitor visitors(rootp,&state); - if (LinkDotState::debug()>=5 || v3Global.opt.dumpTree()>=9) { + LinkDotScopeVisitor visitors(rootp, &state); + if (LinkDotState::debug() >= 5 || v3Global.opt.dumpTree() >= 9) { v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-scoped.tree")); } + } else { + v3fatalSrc("Bad case"); } - else v3fatalSrc("Bad case"); state.dump(); state.computeIfaceModSyms(); state.computeIfaceVarSyms(); state.computeScopeAliases(); state.dump(); - LinkDotResolveVisitor visitorb(rootp,&state); + LinkDotResolveVisitor visitorb(rootp, &state); } diff --git a/src/V3LinkJump.cpp b/src/V3LinkJump.cpp index 50244c0b5..4cbb97210 100644 --- a/src/V3LinkJump.cpp +++ b/src/V3LinkJump.cpp @@ -41,35 +41,37 @@ private: typedef std::vector BeginStack; // STATE - AstNodeModule* m_modp; // Current module - AstNodeFTask* m_ftaskp; // Current function/task - AstWhile* m_loopp; // Current loop - bool m_loopInc; // In loop increment - int m_modRepeatNum; // Repeat counter - BeginStack m_beginStack; // All begin blocks above current node + AstNodeModule* m_modp; // Current module + AstNodeFTask* m_ftaskp; // Current function/task + AstWhile* m_loopp; // Current loop + bool m_loopInc; // In loop increment + int m_modRepeatNum; // Repeat counter + BeginStack m_beginStack; // All begin blocks above current node // METHODS VL_DEBUG_FUNC; // Declare debug() AstJumpLabel* findAddLabel(AstNode* nodep, bool endOfIter) { // Put label under given node, and if WHILE optionally at end of iteration - UINFO(4,"Create label for "<stmtsp(); - else if (VN_IS(nodep, NodeFTask)) underp = VN_CAST(nodep, NodeFTask)->stmtsp(); - else if (VN_IS(nodep, While)) { + bool under_and_next = true; + if (VN_IS(nodep, Begin)) { + underp = VN_CAST(nodep, Begin)->stmtsp(); + } else if (VN_IS(nodep, NodeFTask)) { + underp = VN_CAST(nodep, NodeFTask)->stmtsp(); + } else if (VN_IS(nodep, While)) { if (endOfIter) { // Note we jump to end of bodysp; a FOR loop has its // increment under incsp() which we don't skip underp = VN_CAST(nodep, While)->bodysp(); } else { - underp = nodep; under_and_next = false; // IE we skip the entire while + underp = nodep; + under_and_next = false; // IE we skip the entire while } - } - else { + } else { nodep->v3fatalSrc("Unknown jump point for break/disable/continue"); return NULL; } @@ -78,7 +80,7 @@ private: // see t_func_return test. while (underp && VN_IS(underp, Var)) underp = underp->nextp(); UASSERT_OBJ(underp, nodep, "Break/disable/continue not under expected statement"); - UINFO(5," Underpoint is "<fileline(), NULL); AstNRelinker repHandle; - if (under_and_next) underp->unlinkFrBackWithNext(&repHandle); - else underp->unlinkFrBack(&repHandle); + if (under_and_next) { + underp->unlinkFrBackWithNext(&repHandle); + } else { + underp->unlinkFrBack(&repHandle); + } repHandle.relink(labelp); labelp->addStmtsp(underp); // Keep any AstVars under the function not under the new JumpLabel - for (AstNode* nextp, *varp=underp; varp; varp = nextp) { + for (AstNode *nextp, *varp = underp; varp; varp = nextp) { nextp = varp->nextp(); - if (VN_IS(varp, Var)) { - labelp->addPrev(varp->unlinkFrBack()); - } + if (VN_IS(varp, Var)) labelp->addPrev(varp->unlinkFrBack()); } return labelp; } @@ -121,7 +124,7 @@ private: m_ftaskp = NULL; } virtual void visit(AstBegin* nodep) VL_OVERRIDE { - UINFO(8," "< loop=count,WHILE(loop>0) { body, loop-- } // Note var can be signed or unsigned based on original number. AstNode* countp = nodep->countp()->unlinkFrBackWithNext(); - string name = string("__Vrepeat")+cvtToStr(m_modRepeatNum++); + string name = string("__Vrepeat") + cvtToStr(m_modRepeatNum++); // Spec says value is integral, if negative is ignored AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name, nodep->findSigned32DType()); varp->usedLoopIdx(true); m_modp->addStmtp(varp); AstNode* initsp = new AstAssign(nodep->fileline(), - new AstVarRef(nodep->fileline(), varp, true), - countp); - AstNode* decp = new AstAssign(nodep->fileline(), - new AstVarRef(nodep->fileline(), varp, true), - new AstSub(nodep->fileline(), - new AstVarRef(nodep->fileline(), varp, false), - new AstConst(nodep->fileline(), 1))); + new AstVarRef(nodep->fileline(), varp, true), countp); + AstNode* decp = new AstAssign( + nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true), + new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false), + new AstConst(nodep->fileline(), 1))); AstNode* zerosp = new AstConst(nodep->fileline(), AstConst::Signed32(), 0); - AstNode* condp = new AstGtS(nodep->fileline(), - new AstVarRef(nodep->fileline(), varp, false), - zerosp); - AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext(); - AstNode* newp = new AstWhile(nodep->fileline(), - condp, - bodysp, - decp); + AstNode* condp + = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false), zerosp); + AstNode* bodysp = nodep->bodysp(); + if (bodysp) bodysp->unlinkFrBackWithNext(); + AstNode* newp = new AstWhile(nodep->fileline(), condp, bodysp, decp); initsp = initsp->addNext(newp); newp = initsp; nodep->replaceWith(newp); @@ -178,67 +176,73 @@ private: AstFunc* funcp = VN_CAST(m_ftaskp, Func); if (!m_ftaskp) { nodep->v3error("Return isn't underneath a task or function"); - } else if (funcp && !nodep->lhsp()) { + } else if (funcp && !nodep->lhsp()) { nodep->v3error("Return underneath a function should have return value"); - } else if (!funcp && nodep->lhsp()) { + } else if (!funcp && nodep->lhsp()) { nodep->v3error("Return underneath a task shouldn't have return value"); } else { if (funcp && nodep->lhsp()) { // Set output variable to return value - nodep->addPrev(new AstAssign(nodep->fileline(), - new AstVarRef(nodep->fileline(), - VN_CAST(funcp->fvarp(), Var), true), - nodep->lhsp()->unlinkFrBackWithNext())); + nodep->addPrev(new AstAssign( + nodep->fileline(), + new AstVarRef(nodep->fileline(), VN_CAST(funcp->fvarp(), Var), true), + nodep->lhsp()->unlinkFrBackWithNext())); } // Jump to the end of the function call AstJumpLabel* labelp = findAddLabel(m_ftaskp, false); nodep->addPrev(new AstJumpGo(nodep->fileline(), labelp)); } - nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); + nodep->unlinkFrBack(); + VL_DO_DANGLING(pushDeletep(nodep), nodep); } virtual void visit(AstBreak* nodep) VL_OVERRIDE { iterateChildren(nodep); - if (!m_loopp) { nodep->v3error("break isn't underneath a loop"); } - else { + if (!m_loopp) { + nodep->v3error("break isn't underneath a loop"); + } else { // Jump to the end of the loop AstJumpLabel* labelp = findAddLabel(m_loopp, false); nodep->addNextHere(new AstJumpGo(nodep->fileline(), labelp)); } - nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); + nodep->unlinkFrBack(); + VL_DO_DANGLING(pushDeletep(nodep), nodep); } virtual void visit(AstContinue* nodep) VL_OVERRIDE { iterateChildren(nodep); - if (!m_loopp) { nodep->v3error("continue isn't underneath a loop"); } - else { + if (!m_loopp) { + nodep->v3error("continue isn't underneath a loop"); + } else { // Jump to the end of this iteration // If a "for" loop then need to still do the post-loop increment AstJumpLabel* labelp = findAddLabel(m_loopp, true); nodep->addNextHere(new AstJumpGo(nodep->fileline(), labelp)); } - nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); + nodep->unlinkFrBack(); + VL_DO_DANGLING(pushDeletep(nodep), nodep); } virtual void visit(AstDisable* nodep) VL_OVERRIDE { - UINFO(8," DISABLE "<name() == nodep->name()) { beginp = *it; break; } } - //if (debug()>=9) { UINFO(0,"\n"); beginp->dumpTree(cout, " labeli: "); } - if (!beginp) { nodep->v3error("disable isn't underneath a begin with name: " - <prettyNameQ()); } - else { + // if (debug() >= 9) { UINFO(0, "\n"); beginp->dumpTree(cout, " labeli: "); } + if (!beginp) { + nodep->v3error("disable isn't underneath a begin with name: " << nodep->prettyNameQ()); + } else { // Jump to the end of the named begin AstJumpLabel* labelp = findAddLabel(beginp, false); nodep->addNextHere(new AstJumpGo(nodep->fileline(), labelp)); } - nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); - //if (debug()>=9) { UINFO(0,"\n"); beginp->dumpTree(cout, " labelo: "); } + nodep->unlinkFrBack(); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + // if (debug() >= 9) { UINFO(0, "\n"); beginp->dumpTree(cout, " labelo: "); } } virtual void visit(AstVarRef* nodep) VL_OVERRIDE { if (m_loopInc && nodep->varp()) nodep->varp()->usedLoopIdx(true); @@ -263,9 +267,7 @@ public: // Task class functions void V3LinkJump::linkJump(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3LinkLevel.cpp b/src/V3LinkLevel.cpp index 062cfa44b..7e6643543 100644 --- a/src/V3LinkLevel.cpp +++ b/src/V3LinkLevel.cpp @@ -35,7 +35,7 @@ // Levelizing class functions struct CmpLevel { - inline bool operator() (const AstNodeModule* lhsp, const AstNodeModule* rhsp) const { + inline bool operator()(const AstNodeModule* lhsp, const AstNodeModule* rhsp) const { return lhsp->level() < rhsp->level(); } }; @@ -43,7 +43,7 @@ struct CmpLevel { void V3LinkLevel::modSortByLevel() { // Sort modules by levels, root down to lowest children // Calculate levels again in case we added modules - UINFO(2,"modSortByLevel()\n"); + UINFO(2, "modSortByLevel()\n"); // level() was computed for us in V3LinkCells @@ -60,20 +60,21 @@ void V3LinkLevel::modSortByLevel() { AstNode* secp = tops[1]; // Complain about second one, as first often intended if (!secp->fileline()->warnIsOff(V3ErrorCode::MULTITOP)) { secp->v3warn(MULTITOP, "Multiple top level modules\n" - <warnMore() - <<"... Suggest see manual; fix the duplicates, or use --top-module to select top." - <warnMore() + << "... Suggest see manual; fix the duplicates, or use " + "--top-module to select top." + << V3Error::warnContextNone()); for (ModVec::const_iterator it = tops.begin(); it != tops.end(); ++it) { AstNode* alsop = *it; - std::cout<warnMore()<<"... Top module "<prettyNameQ()<warnContextSecondary(); + std::cout << secp->warnMore() << "... Top module " << alsop->prettyNameQ() << endl + << alsop->warnContextSecondary(); } } } // Reorder the netlist's modules to have modules in level sorted order stable_sort(mods.begin(), mods.end(), CmpLevel()); // Sort the vector - UINFO(9,"modSortByLevel() sorted\n"); // Comment required for gcc4.6.3 / bug666 + UINFO(9, "modSortByLevel() sorted\n"); // Comment required for gcc4.6.3 / bug666 for (ModVec::const_iterator it = mods.begin(); it != mods.end(); ++it) { AstNodeModule* nodep = *it; nodep->clearIter(); // Because we didn't iterate to find the node @@ -85,7 +86,7 @@ void V3LinkLevel::modSortByLevel() { AstNodeModule* nodep = *it; v3Global.rootp()->addModulep(nodep); } - UINFO(9,"modSortByLevel() done\n"); // Comment required for gcc4.6.3 / bug666 + UINFO(9, "modSortByLevel() done\n"); // Comment required for gcc4.6.3 / bug666 V3Global::dumpCheckGlobalTree("cells", false, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); } @@ -93,11 +94,11 @@ void V3LinkLevel::modSortByLevel() { // Wrapping void V3LinkLevel::wrapTop(AstNetlist* rootp) { - UINFO(2,__FUNCTION__<<": "<modulesp(); if (!oldmodp) { // Later V3LinkDot will warn - UINFO(1,"No module found to wrap\n"); + UINFO(1, "No module found to wrap\n"); return; } AstNodeModule* newmodp = new AstModule(oldmodp->fileline(), string("TOP")); @@ -115,15 +116,13 @@ void V3LinkLevel::wrapTop(AstNetlist* rootp) { // Instantiate all packages under the top wrapper // This way all later SCOPE based optimizations can ignore packages - for (AstNodeModule* modp = rootp->modulesp(); modp; modp=VN_CAST(modp->nextp(), NodeModule)) { + for (AstNodeModule* modp = rootp->modulesp(); modp; + modp = VN_CAST(modp->nextp(), NodeModule)) { if (VN_IS(modp, Package)) { - AstCell* cellp = new AstCell(modp->fileline(), - modp->fileline(), + AstCell* cellp = new AstCell(modp->fileline(), modp->fileline(), // Could add __03a__03a="::" to prevent conflict // with module names/"v" - modp->name(), - modp->name(), - NULL, NULL, NULL); + modp->name(), modp->name(), NULL, NULL, NULL); cellp->modp(modp); newmodp->addStmtp(cellp); } @@ -142,13 +141,12 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) { NameSet dupNames; // For all modules, skipping over new top for (AstNodeModule* oldmodp = VN_CAST(rootp->modulesp()->nextp(), NodeModule); - oldmodp && oldmodp->level() <= 2; - oldmodp = VN_CAST(oldmodp->nextp(), NodeModule)) { + oldmodp && oldmodp->level() <= 2; oldmodp = VN_CAST(oldmodp->nextp(), NodeModule)) { for (AstNode* subnodep = oldmodp->stmtsp(); subnodep; subnodep = subnodep->nextp()) { if (AstVar* oldvarp = VN_CAST(subnodep, Var)) { if (oldvarp->isIO()) { if (ioNames.find(oldvarp->name()) != ioNames.end()) { - //UINFO(8, "Multitop dup I/O found: "<name()); } else { ioNames.insert(oldvarp->name()); @@ -160,29 +158,26 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) { // For all modules, skipping over new top for (AstNodeModule* oldmodp = VN_CAST(rootp->modulesp()->nextp(), NodeModule); - oldmodp && oldmodp->level() <= 2; - oldmodp = VN_CAST(oldmodp->nextp(), NodeModule)) { + oldmodp && oldmodp->level() <= 2; oldmodp = VN_CAST(oldmodp->nextp(), NodeModule)) { if (VN_IS(oldmodp, Package)) continue; // Add instance - UINFO(5,"LOOP "<fileline(), - newmodp->fileline(), - (!v3Global.opt.l2Name().empty() - ? v3Global.opt.l2Name() : oldmodp->name()), - oldmodp->name(), - NULL, NULL, NULL); + UINFO(5, "LOOP " << oldmodp << endl); + AstCell* cellp = new AstCell( + newmodp->fileline(), newmodp->fileline(), + (!v3Global.opt.l2Name().empty() ? v3Global.opt.l2Name() : oldmodp->name()), + oldmodp->name(), NULL, NULL, NULL); cellp->modp(oldmodp); newmodp->addStmtp(cellp); // Add pins - for (AstNode* subnodep=oldmodp->stmtsp(); subnodep; subnodep = subnodep->nextp()) { + for (AstNode* subnodep = oldmodp->stmtsp(); subnodep; subnodep = subnodep->nextp()) { if (AstVar* oldvarp = VN_CAST(subnodep, Var)) { - UINFO(8,"VARWRAP "<isIO()) { string name = oldvarp->name(); if (dupNames.find(name) != dupNames.end()) { // __02E=. while __DOT__ looks nicer but will break V3LinkDot - name = oldmodp->name()+"__02E"+name; + name = oldmodp->name() + "__02E" + name; } AstVar* varp = oldvarp->cloneTree(false); @@ -196,7 +191,7 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) { } if (varp->direction().isRefOrConstRef()) { varp->v3error("Unsupported: ref/const ref as primary input/output: " - <prettyNameQ()); + << varp->prettyNameQ()); } if (varp->isIO() && v3Global.opt.systemC()) { varp->sc(true); @@ -205,9 +200,9 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) { varp->trace(false); } - AstPin* pinp = new AstPin(oldvarp->fileline(), 0, varp->name(), - new AstVarRef(varp->fileline(), - varp, oldvarp->isWritable())); + AstPin* pinp + = new AstPin(oldvarp->fileline(), 0, varp->name(), + new AstVarRef(varp->fileline(), varp, oldvarp->isWritable())); // Skip length and width comp; we know it's a direct assignment pinp->modVarp(oldvarp); cellp->addPinsp(pinp); diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index d0e852695..c1ef8ebc5 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -41,24 +41,24 @@ private: // Cleared on netlist // AstNode::user1() -> bool. True if processed // AstNode::user2() -> bool. True if fileline recomputed - AstUser1InUse m_inuser1; - AstUser2InUse m_inuser2; + AstUser1InUse m_inuser1; + AstUser2InUse m_inuser2; // TYPES - typedef std::map,AstTypedef*> ImplTypedefMap; + typedef std::map, AstTypedef*> ImplTypedefMap; typedef std::set FileLineSet; // STATE - AstVar* m_varp; // Variable we're under - ImplTypedefMap m_implTypedef; // Created typedefs for each - FileLineSet m_filelines; // Filelines that have been seen - bool m_inAlways; // Inside an always - bool m_inGenerate; // Inside a generate - bool m_needStart; // Need start marker on lower AstParse - AstNodeModule* m_valueModp; // If set, move AstVar->valuep() initial values to this module - AstNodeModule* m_modp; // Current module - AstNodeFTask* m_ftaskp; // Current task - AstNodeDType* m_dtypep; // Current data type + AstVar* m_varp; // Variable we're under + ImplTypedefMap m_implTypedef; // Created typedefs for each + FileLineSet m_filelines; // Filelines that have been seen + bool m_inAlways; // Inside an always + bool m_inGenerate; // Inside a generate + bool m_needStart; // Need start marker on lower AstParse + AstNodeModule* m_valueModp; // If set, move AstVar->valuep() initial values to this module + AstNodeModule* m_modp; // Current module + AstNodeFTask* m_ftaskp; // Current task + AstNodeDType* m_dtypep; // Current data type // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -84,8 +84,11 @@ private: // Create a name for the enum, to aid debug and tracing // This name is not guaranteed to be globally unique (due to later parameterization) string above; - if (m_modp && VN_IS(m_modp, Package)) above = m_modp->name()+"::"; - else if (m_modp) above = m_modp->name()+"."; + if (m_modp && VN_IS(m_modp, Package)) { + above = m_modp->name() + "::"; + } else if (m_modp) { + above = m_modp->name() + "."; + } return above + typedefp->name(); } return ""; @@ -115,16 +118,14 @@ private: virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { if (!nodep->user1SetOnce()) { // Process only once. cleanFileline(nodep); - UINFO(5," "<name() == "") { nodep->name(nameFromTypedef(nodep)); // Might still remain "" @@ -142,7 +143,7 @@ private: cleanFileline(nodep); iterateChildren(nodep); if (nodep->rangep()) { - if (!VN_IS(nodep->rangep()->msbp(), Const) + if (!VN_IS(nodep->rangep()->msbp(), Const) // || !VN_IS(nodep->rangep()->lsbp(), Const)) { nodep->v3error("Enum ranges must be integral, per spec"); } @@ -151,18 +152,19 @@ private: int increment = (msb > lsb) ? -1 : 1; int offset_from_init = 0; AstNode* addp = NULL; - for (int i=msb; i!=(lsb+increment); i+=increment, offset_from_init++) { + for (int i = msb; i != (lsb + increment); i += increment, offset_from_init++) { string name = nodep->name() + cvtToStr(i); AstNode* valuep = NULL; - if (nodep->valuep()) valuep = new AstAdd - (nodep->fileline(), - nodep->valuep()->cloneTree(true), - new AstConst(nodep->fileline(), - AstConst::Unsized32(), - offset_from_init)); + if (nodep->valuep()) + valuep = new AstAdd( + nodep->fileline(), nodep->valuep()->cloneTree(true), + new AstConst(nodep->fileline(), AstConst::Unsized32(), offset_from_init)); AstNode* newp = new AstEnumItem(nodep->fileline(), name, NULL, valuep); - if (addp) addp = addp->addNextNull(newp); - else addp = newp; + if (addp) { + addp = addp->addNextNull(newp); + } else { + addp = newp; + } } nodep->replaceWith(addp); VL_DO_DANGLING(nodep->deleteTree(), nodep); @@ -175,15 +177,15 @@ private: // It's a parameter type. Use a different node type for this. AstNodeDType* dtypep = VN_CAST(nodep->valuep(), NodeDType); if (!dtypep) { - nodep->v3error("Parameter type's initial value isn't a type: " - <prettyNameQ()); + nodep->v3error( + "Parameter type's initial value isn't a type: " << nodep->prettyNameQ()); nodep->unlinkFrBack(); } else { dtypep->unlinkFrBack(); - AstNode* newp = new AstParamTypeDType(nodep->fileline(), - nodep->varType(), nodep->name(), - VFlagChildDType(), dtypep); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + AstNode* newp = new AstParamTypeDType(nodep->fileline(), nodep->varType(), + nodep->name(), VFlagChildDType(), dtypep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } return; } @@ -195,18 +197,15 @@ private: switch (nodep->varType()) { case AstVarType::VAR: case AstVarType::PORT: - case AstVarType::WIRE: - nodep->sigUserRWPublic(true); - break; + case AstVarType::WIRE: nodep->sigUserRWPublic(true); break; default: break; } } // We used modTrace before leveling, and we may now // want to turn it off now that we know the levelizations - if (v3Global.opt.traceDepth() - && m_modp - && (m_modp->level()-1) > v3Global.opt.traceDepth()) { + if (v3Global.opt.traceDepth() && m_modp + && (m_modp->level() - 1) > v3Global.opt.traceDepth()) { m_modp->modTrace(false); nodep->trace(false); } @@ -237,15 +236,13 @@ private: // Making an AstAssign (vs AstAssignW) to a wire is an error, suppress it FileLine* newfl = new FileLine(fl); newfl->warnOff(V3ErrorCode::PROCASSWIRE, true); - nodep->addNextHere - (new AstInitial - (newfl, new AstAssign(newfl, new AstVarRef(newfl, nodep->name(), true), - nodep->valuep()->unlinkFrBack()))); + nodep->addNextHere(new AstInitial( + newfl, new AstAssign(newfl, new AstVarRef(newfl, nodep->name(), true), + nodep->valuep()->unlinkFrBack()))); } // 3. Under blocks, it's an initial value to be under an assign else { - nodep->addNextHere - (new AstAssign(fl, new AstVarRef(fl, nodep->name(), true), - nodep->valuep()->unlinkFrBack())); + nodep->addNextHere(new AstAssign(fl, new AstVarRef(fl, nodep->name(), true), + nodep->valuep()->unlinkFrBack())); } } if (nodep->isIfaceRef() && !nodep->isIfaceParent()) { @@ -253,7 +250,9 @@ private: // haven't made additional ones for interconnect yet, so assert is simple // What breaks later is we don't have a Scope/Cell representing // the interface to attach to - if (m_modp->level()<=2) nodep->v3error("Unsupported: Interfaced port on top level module"); + if (m_modp->level() <= 2) { + nodep->v3error("Unsupported: Interfaced port on top level module"); + } } } @@ -265,69 +264,61 @@ private: UASSERT_OBJ(typep, nodep, "Attribute not attached to typedef"); typep->attrPublic(true); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } - else if (nodep->attrType() == AstAttrType::VAR_CLOCK) { + } else if (nodep->attrType() == AstAttrType::VAR_CLOCK) { UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); nodep->v3warn(DEPRECATED, "sc_clock is deprecated and will be removed"); m_varp->attrScClocked(true); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } - else if (nodep->attrType() == AstAttrType::VAR_CLOCK_ENABLE) { + } else if (nodep->attrType() == AstAttrType::VAR_CLOCK_ENABLE) { UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->attrClockEn(true); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } - else if (nodep->attrType() == AstAttrType::VAR_PUBLIC) { + } else if (nodep->attrType() == AstAttrType::VAR_PUBLIC) { UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); - m_varp->sigUserRWPublic(true); m_varp->sigModPublic(true); + m_varp->sigUserRWPublic(true); + m_varp->sigModPublic(true); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } - else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT) { + } else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT) { UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->sigUserRWPublic(true); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } - else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT_RD) { + } else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT_RD) { UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->sigUserRdPublic(true); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } - else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT_RW) { + } else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT_RW) { UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->sigUserRWPublic(true); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } - else if (nodep->attrType() == AstAttrType::VAR_ISOLATE_ASSIGNMENTS) { + } else if (nodep->attrType() == AstAttrType::VAR_ISOLATE_ASSIGNMENTS) { UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->attrIsolateAssign(true); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } - else if (nodep->attrType() == AstAttrType::VAR_SFORMAT) { + } else if (nodep->attrType() == AstAttrType::VAR_SFORMAT) { UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->attrSFormat(true); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } - else if (nodep->attrType() == AstAttrType::VAR_SPLIT_VAR) { + } else if (nodep->attrType() == AstAttrType::VAR_SPLIT_VAR) { UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); if (!VN_IS(m_modp, Module)) { - m_varp->v3warn(SPLITVAR, m_varp->prettyNameQ() << " has split_var metacomment, " - "but will not be split because it is not declared in a module."); + m_varp->v3warn( + SPLITVAR, + m_varp->prettyNameQ() + << " has split_var metacomment, " + "but will not be split because it is not declared in a module."); } else { m_varp->attrSplitVar(true); } VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } - else if (nodep->attrType() == AstAttrType::VAR_SC_BV) { + } else if (nodep->attrType() == AstAttrType::VAR_SC_BV) { UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->attrScBv(true); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } - else if (nodep->attrType() == AstAttrType::VAR_CLOCKER) { + } else if (nodep->attrType() == AstAttrType::VAR_CLOCKER) { UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->attrClocker(VVarAttrClocker::CLOCKER_YES); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } - else if (nodep->attrType() == AstAttrType::VAR_NO_CLOCKER) { + } else if (nodep->attrType() == AstAttrType::VAR_NO_CLOCKER) { UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->attrClocker(VVarAttrClocker::CLOCKER_NO); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); @@ -351,36 +342,38 @@ private: virtual void visit(AstDefImplicitDType* nodep) VL_OVERRIDE { cleanFileline(nodep); - UINFO(8," DEFIMPLICIT "<containerp(), nodep->name())); + ImplTypedefMap::iterator it + = m_implTypedef.find(make_pair(nodep->containerp(), nodep->name())); if (it != m_implTypedef.end()) { defp = it->second; } else { // Definition must be inserted right after the variable (etc) that needed it // AstVar, AstTypedef, AstNodeFTask are common containers AstNode* backp = nodep->backp(); - for (; backp; backp=backp->backp()) { - if (VN_IS(backp, Var)) break; - else if (VN_IS(backp, Typedef)) break; - else if (VN_IS(backp, NodeFTask)) break; + for (; backp; backp = backp->backp()) { + if (VN_IS(backp, Var) || VN_IS(backp, Typedef) || VN_IS(backp, NodeFTask)) break; } UASSERT_OBJ(backp, nodep, "Implicit enum/struct type created under unexpected node type"); - AstNodeDType* dtypep = nodep->childDTypep(); dtypep->unlinkFrBack(); - if (VN_IS(backp, Typedef)) { // A typedef doesn't need us to make yet another level of typedefing + AstNodeDType* dtypep = nodep->childDTypep(); + dtypep->unlinkFrBack(); + if (VN_IS(backp, Typedef)) { + // A typedef doesn't need us to make yet another level of typedefing // For typedefs just remove the AstRefDType level of abstraction nodep->replaceWith(dtypep); VL_DO_DANGLING(nodep->deleteTree(), nodep); return; } else { - defp = new AstTypedef(nodep->fileline(), nodep->name(), NULL, - VFlagChildDType(), dtypep); - m_implTypedef.insert(make_pair(make_pair(nodep->containerp(), defp->name()), defp)); + defp = new AstTypedef(nodep->fileline(), nodep->name(), NULL, VFlagChildDType(), + dtypep); + m_implTypedef.insert( + make_pair(make_pair(nodep->containerp(), defp->name()), defp)); backp->addNextHere(defp); } } @@ -391,19 +384,22 @@ private: virtual void visit(AstForeach* nodep) VL_OVERRIDE { // FOREACH(array,loopvars,body) // -> BEGIN(declare vars, loopa=lowest; WHILE(loopa<=highest, ... body)) - //nodep->dumpTree(cout, "-foreach-old:"); + // nodep->dumpTree(cout, "-foreach-old:"); AstNode* newp = nodep->bodysp()->unlinkFrBackWithNext(); AstNode* arrayp = nodep->arrayp(); int dimension = 1; // Must do innermost (last) variable first AstNode* firstVarsp = nodep->varsp()->unlinkFrBackWithNext(); AstNode* lastVarsp = firstVarsp; - while (lastVarsp->nextp()) { lastVarsp = lastVarsp->nextp(); dimension++; } - for (AstNode* varsp = lastVarsp; varsp; varsp=varsp->backp()) { - UINFO(9,"foreachVar "<nextp()) { + lastVarsp = lastVarsp->nextp(); + dimension++; + } + for (AstNode* varsp = lastVarsp; varsp; varsp = varsp->backp()) { + UINFO(9, "foreachVar " << varsp << endl); FileLine* fl = varsp->fileline(); - AstNode* varp = new AstVar(fl, AstVarType::BLOCKTEMP, - varsp->name(), nodep->findSigned32DType()); + AstNode* varp + = new AstVar(fl, AstVarType::BLOCKTEMP, varsp->name(), nodep->findSigned32DType()); // These will be the left and right dimensions and size of the array: AstNode* leftp = new AstAttrOf(fl, AstAttrType::DIM_LEFT, new AstVarRef(fl, arrayp->name(), false), @@ -416,19 +412,16 @@ private: new AstConst(fl, dimension)); AstNode* stmtsp = varp; // Assign left-dimension into the loop var: - stmtsp->addNext(new AstAssign - (fl, new AstVarRef(fl, varp->name(), true), leftp)); + stmtsp->addNext(new AstAssign(fl, new AstVarRef(fl, varp->name(), true), leftp)); // This will turn into a constant bool for static arrays AstNode* notemptyp = new AstGt(fl, sizep, new AstConst(fl, 0)); // This will turn into a bool constant, indicating whether // we count the loop variable up or down: - AstNode* countupp = new AstLte(fl, leftp->cloneTree(true), - rightp->cloneTree(true)); + AstNode* countupp = new AstLte(fl, leftp->cloneTree(true), rightp->cloneTree(true)); AstNode* comparep = new AstCond( fl, countupp->cloneTree(true), // Left increments up to right - new AstLte(fl, new AstVarRef(fl, varp->name(), false), - rightp->cloneTree(true)), + new AstLte(fl, new AstVarRef(fl, varp->name(), false), rightp->cloneTree(true)), // Left decrements down to right new AstGte(fl, new AstVarRef(fl, varp->name(), false), rightp)); // This will reduce to comparep for static arrays @@ -436,16 +429,15 @@ private: AstNode* incp = new AstAssign( fl, new AstVarRef(fl, varp->name(), true), new AstAdd(fl, new AstVarRef(fl, varp->name(), false), - new AstCond(fl, countupp, - new AstConst(fl, 1), - new AstConst(fl, -1)))); + new AstCond(fl, countupp, new AstConst(fl, 1), new AstConst(fl, -1)))); stmtsp->addNext(new AstWhile(fl, condp, newp, incp)); newp = new AstBegin(nodep->fileline(), "", stmtsp, false, true); dimension--; } - //newp->dumpTree(cout, "-foreach-new:"); + // newp->dumpTree(cout, "-foreach-new:"); VL_DO_DANGLING(firstVarsp->deleteTree(), firstVarsp); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { @@ -472,23 +464,15 @@ private: iterateChildren(nodep); m_valueModp = upperValueModp; } - virtual void visit(AstInitial* nodep) VL_OVERRIDE { - visitIterateNoValueMod(nodep); - } - virtual void visit(AstFinal* nodep) VL_OVERRIDE { - visitIterateNoValueMod(nodep); - } + virtual void visit(AstInitial* nodep) VL_OVERRIDE { visitIterateNoValueMod(nodep); } + virtual void visit(AstFinal* nodep) VL_OVERRIDE { visitIterateNoValueMod(nodep); } virtual void visit(AstAlways* nodep) VL_OVERRIDE { m_inAlways = true; visitIterateNoValueMod(nodep); m_inAlways = false; } - virtual void visit(AstCover* nodep) VL_OVERRIDE { - visitIterateNoValueMod(nodep); - } - virtual void visit(AstRestrict* nodep) VL_OVERRIDE { - visitIterateNoValueMod(nodep); - } + virtual void visit(AstCover* nodep) VL_OVERRIDE { visitIterateNoValueMod(nodep); } + virtual void visit(AstRestrict* nodep) VL_OVERRIDE { visitIterateNoValueMod(nodep); } virtual void visit(AstBegin* nodep) VL_OVERRIDE { V3Config::applyCoverageBlock(m_modp, nodep); @@ -502,10 +486,8 @@ private: // It's not FOR(BEGIN(...)) but we earlier changed it to BEGIN(FOR(...)) if (nodep->genforp() && nodep->name() == "") { nodep->name("genblk"); - } - else if (nodep->generate() && nodep->name() == "" - && (VN_IS(backp, CaseItem) || VN_IS(backp, GenIf)) - && !nestedIf) { + } else if (nodep->generate() && nodep->name() == "" + && (VN_IS(backp, CaseItem) || VN_IS(backp, GenIf)) && !nestedIf) { nodep->name("genblk"); } iterateChildren(nodep); @@ -542,9 +524,7 @@ public: // Link class functions void V3LinkParse::linkParse(AstNetlist* rootp) { - UINFO(4,__FUNCTION__<<": "<= 6); } diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index 6bea4587c..904c4882e 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -64,7 +64,7 @@ private: // TODO: could move to V3LinkParse to get them out of the way of elaboration virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { // Module: Create sim table for entire module and iterate - UINFO(8,"MODULE "<dead()) return; AstNodeModule* origModp = m_modp; int origSenitemCvtNum = m_senitemCvtNum; @@ -110,9 +110,7 @@ private: virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE { // VarRef: Resolve its reference - if (nodep->varp()) { - nodep->varp()->usedParam(true); - } + if (nodep->varp()) { nodep->varp()->usedParam(true); } iterateChildren(nodep); } @@ -123,9 +121,7 @@ private: m_ftaskp = nodep; iterateChildren(nodep); m_ftaskp = NULL; - if (nodep->dpiExport()) { - nodep->scopeNamep(new AstScopeName(nodep->fileline())); - } + if (nodep->dpiExport()) { nodep->scopeNamep(new AstScopeName(nodep->fileline())); } } virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { iterateChildren(nodep); @@ -142,34 +138,29 @@ private: // This is a bit unfortunate as we haven't done width resolution // and any width errors will look a bit odd, but it works. AstNode* sensp = nodep->sensp(); - if (sensp - && !VN_IS(sensp, NodeVarRef) - && !VN_IS(sensp, Const)) { + if (sensp && !VN_IS(sensp, NodeVarRef) && !VN_IS(sensp, Const)) { // Make a new temp wire - string newvarname = "__Vsenitemexpr"+cvtToStr(++m_senitemCvtNum); - AstVar* newvarp = new AstVar(sensp->fileline(), - AstVarType::MODULETEMP, newvarname, + string newvarname = "__Vsenitemexpr" + cvtToStr(++m_senitemCvtNum); + AstVar* newvarp = new AstVar(sensp->fileline(), AstVarType::MODULETEMP, newvarname, VFlagLogicPacked(), 1); // We can't just add under the module, because we may be // inside a generate, begin, etc. // We know a SenItem should be under a SenTree/Always etc, // we we'll just hunt upwards AstNode* addwherep = nodep; // Add to this element's next - while (VN_IS(addwherep, SenItem) - || VN_IS(addwherep, SenTree)) { + while (VN_IS(addwherep, SenItem) || VN_IS(addwherep, SenTree)) { addwherep = addwherep->backp(); } if (!VN_IS(addwherep, Always)) { // Assertion perhaps? - sensp->v3error("Unsupported: Non-single-bit pos/negedge clock statement under some complicated block"); + sensp->v3error("Unsupported: Non-single-bit pos/negedge clock statement under " + "some complicated block"); addwherep = m_modp; } addwherep->addNext(newvarp); sensp->replaceWith(new AstVarRef(sensp->fileline(), newvarp, false)); - AstAssignW* assignp = new AstAssignW - (sensp->fileline(), - new AstVarRef(sensp->fileline(), newvarp, true), - sensp); + AstAssignW* assignp = new AstAssignW( + sensp->fileline(), new AstVarRef(sensp->fileline(), newvarp, true), sensp); addwherep->addNext(assignp); } } else { // Old V1995 sensitivity list; we'll probably mostly ignore @@ -178,18 +169,21 @@ private: did = 0; if (AstNodeSel* selp = VN_CAST(nodep->sensp(), NodeSel)) { AstNode* fromp = selp->fromp()->unlinkFrBack(); - selp->replaceWith(fromp); VL_DO_DANGLING(selp->deleteTree(), selp); + selp->replaceWith(fromp); + VL_DO_DANGLING(selp->deleteTree(), selp); did = 1; } // NodeSel doesn't include AstSel.... if (AstSel* selp = VN_CAST(nodep->sensp(), Sel)) { AstNode* fromp = selp->fromp()->unlinkFrBack(); - selp->replaceWith(fromp); VL_DO_DANGLING(selp->deleteTree(), selp); + selp->replaceWith(fromp); + VL_DO_DANGLING(selp->deleteTree(), selp); did = 1; } if (AstNodePreSel* selp = VN_CAST(nodep->sensp(), NodePreSel)) { AstNode* fromp = selp->lhsp()->unlinkFrBack(); - selp->replaceWith(fromp); VL_DO_DANGLING(selp->deleteTree(), selp); + selp->replaceWith(fromp); + VL_DO_DANGLING(selp->deleteTree(), selp); did = 1; } } @@ -213,10 +207,12 @@ private: // So we replicate it in another node // Note that V3Param knows not to replace AstVarRef's under AstAttrOf's AstNode* basefromp = AstArraySel::baseFromp(nodep); - if (AstNodeVarRef* varrefp = VN_CAST(basefromp, NodeVarRef)) { // Maybe varxref - so need to clone + if (AstNodeVarRef* varrefp + = VN_CAST(basefromp, NodeVarRef)) { // Maybe varxref - so need to clone nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::VAR_BASE, varrefp->cloneTree(false))); - } else if (AstUnlinkedRef* uvxrp = VN_CAST(basefromp, UnlinkedRef)) { // Maybe unlinked - so need to clone + } else if (AstUnlinkedRef* uvxrp + = VN_CAST(basefromp, UnlinkedRef)) { // Maybe unlinked - so need to clone nodep->attrp(new AstAttrOf(nodep->fileline(), AstAttrType::VAR_BASE, uvxrp->cloneTree(false))); } else if (AstMemberSel* fromp = VN_CAST(basefromp, MemberSel)) { @@ -227,11 +223,11 @@ private: fromp->cloneTree(false))); } else if (VN_IS(basefromp, Replicate)) { // From {...}[...] syntax in IEEE 2017 - if (basefromp) { UINFO(1," Related node: "<v3error("Unsupported: Select of concatenation"); nodep = NULL; } else { - if (basefromp) { UINFO(1," Related node: "<v3fatalSrc("Illegal bit select; no signal/member being extracted from"); } } @@ -253,20 +249,21 @@ private: if (nodep->pragType() == AstPragmaType::PUBLIC_MODULE) { UASSERT_OBJ(m_modp, nodep, "PUBLIC_MODULE not under a module"); m_modp->modPublic(true); - nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - else if (nodep->pragType() == AstPragmaType::PUBLIC_TASK) { + nodep->unlinkFrBack(); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } else if (nodep->pragType() == AstPragmaType::PUBLIC_TASK) { UASSERT_OBJ(m_ftaskp, nodep, "PUBLIC_TASK not under a task"); m_ftaskp->taskPublic(true); m_modp->modPublic(true); // Need to get to the task... - nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - else if (nodep->pragType() == AstPragmaType::COVERAGE_BLOCK_OFF) { - if (!v3Global.opt.coverageLine()) { // No need for block statements; may optimize better without - nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); + nodep->unlinkFrBack(); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } else if (nodep->pragType() == AstPragmaType::COVERAGE_BLOCK_OFF) { + if (!v3Global.opt.coverageLine()) { // No need for block statements; may optimize + // better without + nodep->unlinkFrBack(); + VL_DO_DANGLING(pushDeletep(nodep), nodep); } - } - else { + } else { iterateChildren(nodep); } } @@ -278,10 +275,10 @@ private: string fmt; for (string::const_iterator it = format.begin(); it != format.end(); ++it) { char ch = *it; - if (!inPct && ch=='%') { + if (!inPct && ch == '%') { inPct = true; fmt = ch; - } else if (inPct && (isdigit(ch) || ch=='.' || ch=='-')) { + } else if (inPct && (isdigit(ch) || ch == '.' || ch == '-')) { fmt += ch; } else if (inPct) { inPct = false; @@ -290,15 +287,21 @@ private: case '%': // %% - just output a % break; case 'm': // %m - auto insert "name" - if (isScan) { nodep->v3error("Unsupported: %m in $fscanf"); fmt = ""; } + if (isScan) { + nodep->v3error("Unsupported: %m in $fscanf"); + fmt = ""; + } break; case 'l': // %l - auto insert "library" - if (isScan) { nodep->v3error("Unsupported: %l in $fscanf"); fmt = ""; } + if (isScan) { + nodep->v3error("Unsupported: %l in $fscanf"); + fmt = ""; + } if (m_modp) fmt = VString::quotePercent(m_modp->prettyName()); break; default: // Most operators, just move to next argument if (!V3Number::displayedFmtLegal(ch)) { - nodep->v3error("Unknown $display-like format code: '%"<v3error("Unknown $display-like format code: '%" << ch << "'"); } else { if (!argp) { nodep->v3error("Missing arguments for $display-like format"); @@ -322,10 +325,10 @@ private: skipCount--; continue; } - AstConst *constp = VN_CAST(argp, Const); + AstConst* constp = VN_CAST(argp, Const); bool isFromString = (constp) ? constp->num().isFromString() : false; if (isFromString) { - int numchars = argp->dtypep()->width()/8; + int numchars = argp->dtypep()->width() / 8; string str(numchars, ' '); // now scan for % operators bool inpercent = false; @@ -338,23 +341,18 @@ private: } else if (inpercent) { inpercent = 0; switch (c) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - case '.': - inpercent = true; - break; - case '%': - break; + case '0' ... '9': + case '.': inpercent = true; break; + case '%': break; default: - if (V3Number::displayedFmtLegal(c)) { - skipCount++; - } + if (V3Number::displayedFmtLegal(c)) { skipCount++; } } } } newFormat.append(str); - AstNode *nextp = argp->nextp(); - argp->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(argp), argp); + AstNode* nextp = argp->nextp(); + argp->unlinkFrBack(); + VL_DO_DANGLING(pushDeletep(argp), argp); argp = nextp; } else { newFormat.append("%?"); // V3Width to figure it out @@ -366,7 +364,9 @@ private: } void expectDescriptor(AstNode* nodep, AstNodeVarRef* filep) { - if (!filep) nodep->v3error("Unsupported: $fopen/$fclose/$f* descriptor must be a simple variable"); + if (!filep) { + nodep->v3error("Unsupported: $fopen/$fclose/$f* descriptor must be a simple variable"); + } if (filep && filep->varp()) filep->varp()->attrFileDescr(true); } @@ -402,7 +402,8 @@ private: iterateChildren(nodep); // Cleanup old-school displays without format arguments if (!nodep->hasFormat()) { - UASSERT_OBJ(nodep->text()=="", nodep, "Non-format $sformatf should have \"\" format"); + UASSERT_OBJ(nodep->text() == "", nodep, + "Non-format $sformatf should have \"\" format"); if (VN_IS(nodep->exprsp(), Const) && VN_CAST(nodep->exprsp(), Const)->num().isFromString()) { AstConst* fmtp = VN_CAST(nodep->exprsp()->unlinkFrBack(), Const); @@ -421,14 +422,14 @@ private: } virtual void visit(AstUdpTable* nodep) VL_OVERRIDE { - UINFO(5,"UDPTABLE "<stmtsp(); stmtp; stmtp=stmtp->nextp()) { + for (AstNode* stmtp = m_modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) { if (AstVar* varp = VN_CAST(stmtp, Var)) { if (varp->isReadOnly()) { } else if (varp->isWritable()) { @@ -438,16 +439,15 @@ private: varoutp = varp; // Tie off m_modp->addStmtp(new AstAssignW( - varp->fileline(), - new AstVarRef(varp->fileline(), varp, true), - new AstConst(varp->fileline(), - AstConst::LogicFalse()))); + varp->fileline(), new AstVarRef(varp->fileline(), varp, true), + new AstConst(varp->fileline(), AstConst::LogicFalse()))); } else { varp->v3error("Only inputs and outputs are allowed in udp modules"); } } } - nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); + nodep->unlinkFrBack(); + VL_DO_DANGLING(pushDeletep(nodep), nodep); } } @@ -531,7 +531,7 @@ public: // Link class functions void V3LinkResolve::linkResolve(AstNetlist* rootp) { - UINFO(4,__FUNCTION__<<": "<v3errorEnd(nsstr); } else { @@ -79,13 +82,13 @@ V3Number::V3Number(VerilogStringLiteral, AstNode* nodep, const string& str) { // Create a number using a verilog string as the value, thus 8 bits per character. // cppcheck bug - doesn't see init() resets these // cppcheck: Member variable 'm_sized/m_width' is not initialized in the constructor - init(nodep, str.length()*8); + init(nodep, str.length() * 8); m_fromString = true; - for (unsigned pos=0; posopAdd(product, addend); if (product.bitsValue(width(), 4)) { // Overflowed static int warned = 0; - v3error("Too many digits for "< 1) { - v3error("Mixing X/Z/? with digits not legal in decimal constant: "< 1) { + v3error("Mixing X/Z/? with digits not legal in decimal constant: " << value_startp); } - } - else { + } else { // Convert bin/octal number to hex - for (const char* cp=value_startp+strlen(value_startp)-1; - cp >= value_startp; - cp--) { - if (*cp!='_' && *cp!='0' && obit>=width()) { - v3error("Too many digits for "<= value_startp; cp--) { + if (*cp != '_' && *cp != '0' && obit >= width()) { + v3error("Too many digits for " << width() << " bit number: " << sourcep); break; } - switch(tolower(base)) { + switch (tolower(base)) { case 'b': { - switch(tolower(*cp)) { + switch (tolower(*cp)) { case '0': setBit(obit++, 0); break; case '1': setBit(obit++, 1); break; - case 'z': case '?': setBit(obit++, 'z'); break; + case 'z': + case '?': setBit(obit++, 'z'); break; case 'x': setBit(obit++, 'x'); break; case '_': break; - default: - v3error("Illegal character in binary constant: "<<*cp); + default: v3error("Illegal character in binary constant: " << *cp); } - break; + break; } case 'o': case 'c': { - switch(tolower(*cp)) { + switch (tolower(*cp)) { + // clang-format off case '0': setBit(obit++, 0); setBit(obit++, 0); setBit(obit++, 0); break; case '1': setBit(obit++, 1); setBit(obit++, 0); setBit(obit++, 0); break; case '2': setBit(obit++, 0); setBit(obit++, 1); setBit(obit++, 0); break; @@ -260,19 +274,19 @@ void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl) case '5': setBit(obit++, 1); setBit(obit++, 0); setBit(obit++, 1); break; case '6': setBit(obit++, 0); setBit(obit++, 1); setBit(obit++, 1); break; case '7': setBit(obit++, 1); setBit(obit++, 1); setBit(obit++, 1); break; - case 'z': case '?': - setBit(obit++, 'z'); setBit(obit++, 'z'); setBit(obit++, 'z'); break; - case 'x': - setBit(obit++, 'x'); setBit(obit++, 'x'); setBit(obit++, 'x'); break; + case 'z': + case '?': setBit(obit++, 'z'); setBit(obit++, 'z'); setBit(obit++, 'z'); break; + case 'x': setBit(obit++, 'x'); setBit(obit++, 'x'); setBit(obit++, 'x'); break; case '_': break; - default: - v3error("Illegal character in octal constant"); + // clang-format on + default: v3error("Illegal character in octal constant"); } break; } case 'h': { - switch(tolower(*cp)) { + switch (tolower(*cp)) { + // clang-format off case '0': setBit(obit++,0); setBit(obit++,0); setBit(obit++,0); setBit(obit++,0); break; case '1': setBit(obit++,1); setBit(obit++,0); setBit(obit++,0); setBit(obit++,0); break; case '2': setBit(obit++,0); setBit(obit++,1); setBit(obit++,0); setBit(obit++,0); break; @@ -289,31 +303,30 @@ void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl) case 'd': setBit(obit++,1); setBit(obit++,0); setBit(obit++,1); setBit(obit++,1); break; case 'e': setBit(obit++,0); setBit(obit++,1); setBit(obit++,1); setBit(obit++,1); break; case 'f': setBit(obit++,1); setBit(obit++,1); setBit(obit++,1); setBit(obit++,1); break; - case 'z': case '?': - setBit(obit++,'z'); setBit(obit++,'z'); setBit(obit++,'z'); setBit(obit++,'z'); break; - case 'x': - setBit(obit++,'x'); setBit(obit++,'x'); setBit(obit++,'x'); setBit(obit++,'x'); break; - case '_': break; - default: - v3error("Illegal character in hex constant: "<<*cp); + case 'z': + case '?': setBit(obit++,'z'); setBit(obit++,'z'); setBit(obit++,'z'); setBit(obit++,'z'); break; + case 'x': setBit(obit++,'x'); setBit(obit++,'x'); setBit(obit++,'x'); setBit(obit++,'x'); break; + // clang-format on + case '_': break; + default: v3error("Illegal character in hex constant: " << *cp); } break; } - default: - v3error("Illegal base character: "<0; bit--) if (num & (VL_ULL(1)< 0; bit--) { + if (num & (VL_ULL(1) << bit)) return bit; + } return 0; } @@ -335,65 +350,78 @@ int V3Number::log2b(uint32_t num) { // Setters V3Number& V3Number::setZero() { - for (int i=0; i>VL_ULL(32)) & VL_ULL(0xffffffff); + m_value[1] = (value >> VL_ULL(32)) & VL_ULL(0xffffffff); opCleanThis(); return *this; } V3Number& V3Number::setLong(uint32_t value) { - for (int i=0; i=0; bit--) { - if (bitIs0(bit)) str+='0'; - else if (bitIs1(bit)) str+='1'; - else if (bitIsZ(bit)) str+='z'; - else str+='x'; + int bit = width() - 1; + if (fmtsize == "0") + while (bit && bitIs0(bit)) bit--; + for (; bit >= 0; bit--) { + if (bitIs0(bit)) { + str += '0'; + } else if (bitIs1(bit)) { + str += '1'; + } else if (bitIsZ(bit)) { + str += 'z'; + } else { + str += 'x'; + } } return str; } case 'o': { - int bit = width()-1; - if (fmtsize == "0") while (bit && bitIs0(bit)) bit--; - while ((bit%3)!=2) bit++; - for (; bit>0; bit -= 3) { - int v = bitsValue(bit-2, 3); + int bit = width() - 1; + if (fmtsize == "0") + while (bit && bitIs0(bit)) bit--; + while ((bit % 3) != 2) bit++; + for (; bit > 0; bit -= 3) { + int v = bitsValue(bit - 2, 3); str += static_cast('0' + v); } return str; } case 'h': case 'x': { - int bit = width()-1; - if (fmtsize == "0") while (bit && bitIs0(bit)) bit--; - while ((bit%4)!=3) bit++; - for (; bit>0; bit -= 4) { - int v = bitsValue(bit-3, 4); - if (v>=10) str += static_cast('a' + v - 10); - else str += static_cast('0' + v); + int bit = width() - 1; + if (fmtsize == "0") + while (bit && bitIs0(bit)) bit--; + while ((bit % 4) != 3) bit++; + for (; bit > 0; bit -= 4) { + int v = bitsValue(bit - 3, 4); + if (v >= 10) { + str += static_cast('a' + v - 10); + } else { + str += static_cast('0' + v); + } } return str; } case 'c': { - if (width()>8) fl->v3warn(WIDTH, "$display-like format of %c format of > 8 bit value"); + if (width() > 8) fl->v3warn(WIDTH, "$display-like format of %c format of > 8 bit value"); unsigned int v = bitsValue(0, 8); - char strc[2]; strc[0] = v&0xff; strc[1] = '\0'; + char strc[2]; + strc[0] = v & 0xff; + strc[1] = '\0'; str = strc; return str; } case 's': { // Spec says always drop leading zeros, this isn't quite right, we space pad. - int bit = this->width()-1; + int bit = this->width() - 1; bool start = true; - while ((bit%8)!=7) bit++; - for (; bit>=0; bit -= 8) { - int v = bitsValue(bit-7, 8); + while ((bit % 8) != 7) bit++; + for (; bit >= 0; bit -= 8) { + int v = bitsValue(bit - 7, 8); if (!start || v) { - str += static_cast((v==0) ? ' ' : v); + str += static_cast((v == 0) ? ' ' : v); start = false; // Drop leading 0s } else { if (fmtsize != "0") str += ' '; @@ -605,7 +659,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { str = cvtToStr(toUQuad()); } } - bool zeropad = fmtsize.length()>0 && fmtsize[0]=='0'; + bool zeropad = fmtsize.length() > 0 && fmtsize[0] == '0'; // fmtsize might have changed since we parsed the %fmtsize size_t fmtsizen = static_cast(atoi(fmtsize.c_str())); str = displayPad(fmtsizen, (zeropad ? '0' : ' '), left, str); @@ -622,7 +676,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { // 'l' // Library - converted to text by V3LinkResolve // 'p' // Packed - converted to another code by V3Width case 'u': { // Packed 2-state - for (int i=0; i((m_value[i] >> 0) & 0xff); str += static_cast((m_value[i] >> 8) & 0xff); str += static_cast((m_value[i] >> 16) & 0xff); @@ -631,7 +685,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { return str; } case 'z': { // Packed 4-state - for (int i=0; i((m_value[i] >> 0) & 0xff); str += static_cast((m_value[i] >> 8) & 0xff); str += static_cast((m_value[i] >> 16) & 0xff); @@ -644,12 +698,18 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { return str; } case 'v': { // Strength - int bit = width()-1; - for (; bit>=0; bit--) { - if (bitIs0(bit)) str += "St0 "; // Yes, always a space even for bit 0 - else if (bitIs1(bit)) str += "St1 "; - else if (bitIsZ(bit)) str += "StZ "; - else str += "StX"; + int bit = width() - 1; + for (; bit >= 0; bit--) { + if (bitIs0(bit)) { + str += "St0 "; + } // Yes, always a space even for bit 0 + else if (bitIs1(bit)) { + str += "St1 "; + } else if (bitIsZ(bit)) { + str += "StZ "; + } else { + str += "StX"; + } } return str; } @@ -659,7 +719,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { return str; } default: - fl->v3fatalSrc("Unknown $display-like format code for number: %"<v3fatalSrc("Unknown $display-like format code for number: %" << pos[0]); return "ERR"; } } @@ -675,16 +735,16 @@ string V3Number::toDecimalS() const { } string V3Number::toDecimalU() const { - int maxdecwidth = (width()+3)*4/3; + int maxdecwidth = (width() + 3) * 4 / 3; // Or (maxdecwidth+7)/8], but can't have more than 4 BCD bits per word - V3Number bcd (this, maxdecwidth+4); - V3Number tmp (this, maxdecwidth+4); - V3Number tmp2 (this, maxdecwidth+4); + V3Number bcd(this, maxdecwidth + 4); + V3Number tmp(this, maxdecwidth + 4); + V3Number tmp2(this, maxdecwidth + 4); - int from_bit = width()-1; + int from_bit = width() - 1; // Skip all leading zeros - for (; from_bit >= 0 && bitIs0(from_bit); --from_bit); + for (; from_bit >= 0 && bitIs0(from_bit); --from_bit) {} // Double-dabble algorithm for (; from_bit >= 0; --from_bit) { // Any digits >= 5 need an add 3 (via tmp) @@ -692,7 +752,7 @@ string V3Number::toDecimalU() const { if (bcd.bitsValue(nibble_bit, 4) >= 5) { tmp2.setAllBits0(); tmp2.setBit(nibble_bit, 1); // Add 3, decomposed as two bits - tmp2.setBit(nibble_bit+1, 1); + tmp2.setBit(nibble_bit + 1, 1); tmp.opAssign(bcd); bcd.opAdd(tmp, tmp2); } @@ -705,11 +765,11 @@ string V3Number::toDecimalU() const { } string output; - int lsb = (maxdecwidth-1) & ~3; - for (; lsb>0; lsb-=4) { // Skip leading zeros + int lsb = (maxdecwidth - 1) & ~3; + for (; lsb > 0; lsb -= 4) { // Skip leading zeros if (bcd.bitsValue(lsb, 4)) break; } - for (; lsb>=0; lsb-=4) { + for (; lsb >= 0; lsb -= 4) { output += ('0' + bcd.bitsValue(lsb, 4)); // 0..9 } return output; @@ -719,11 +779,11 @@ string V3Number::toDecimalU() const { // ACCESSORS - as numbers uint32_t V3Number::toUInt() const { - UASSERT(!isFourState(), "toUInt with 4-state "<<*this); + UASSERT(!isFourState(), "toUInt with 4-state " << *this); // We allow wide numbers that represent values <= 32 bits - for (int i=1; i(extended); } else { @@ -753,52 +817,50 @@ vlsint32_t V3Number::toSInt() const { } vluint64_t V3Number::toUQuad() const { - UASSERT(!isFourState(), "toUQuad with 4-state "<<*this); + UASSERT(!isFourState(), "toUQuad with 4-state " << *this); // We allow wide numbers that represent values <= 64 bits if (isDouble()) return static_cast(toDouble()); - for (int i=2; i(toUInt())); - return ((static_cast(m_value[1])<(toUInt())); + return ((static_cast(m_value[1]) << VL_ULL(32)) | (static_cast(m_value[0]))); } vlsint64_t V3Number::toSQuad() const { if (isDouble()) return static_cast(toDouble()); vluint64_t v = toUQuad(); - vluint64_t signExtend = (-(v & (VL_ULL(1)<<(width()-1)))); + vluint64_t signExtend = (-(v & (VL_ULL(1) << (width() - 1)))); vluint64_t extended = v | signExtend; return static_cast(extended); } string V3Number::toString() const { - UASSERT(!isFourState(), "toString with 4-state "<<*this); + UASSERT(!isFourState(), "toString with 4-state " << *this); // Spec says always drop leading zeros, this isn't quite right, we space pad. if (isString()) return m_stringVal; - int bit = this->width()-1; + int bit = this->width() - 1; bool start = true; - while ((bit%8)!=7) bit++; + while ((bit % 8) != 7) bit++; string str; - for (; bit>=0; bit -= 8) { - int v = bitsValue(bit-7, 8); + for (; bit >= 0; bit -= 8) { + int v = bitsValue(bit - 7, 8); if (!start || v) { - str += static_cast((v==0) ? ' ' : v); + str += static_cast((v == 0) ? ' ' : v); start = false; // Drop leading 0s } } return str; } -uint32_t V3Number::toHash() const { - return m_value[0]; -} +uint32_t V3Number::toHash() const { return m_value[0]; } uint32_t V3Number::edataWord(int eword) const { - UASSERT(!isFourState(), "edataWord with 4-state "<<*this); + UASSERT(!isFourState(), "edataWord with 4-state " << *this); return m_value[eword]; } @@ -807,53 +869,53 @@ uint8_t V3Number::dataByte(int byte) const { } bool V3Number::isEqZero() const { - for (int i=0; iwidth(), rhs.width()); bit++) { + for (int bit = 0; bit < std::max(this->width(), rhs.width()); bit++) { if (this->bitIs1(bit) && rhs.bitIs0(bit)) { return 1; } if (rhs.bitIs1(bit) && this->bitIs0(bit)) { return 0; } if (this->bitIsXZ(bit)) { return 0; } @@ -863,7 +925,7 @@ bool V3Number::isLt(const V3Number& rhs) const { } bool V3Number::isLtXZ(const V3Number& rhs) const { // Include X/Z in comparisons for sort ordering - for (int bit=0; bit < std::max(this->width(), rhs.width()); bit++) { + for (int bit = 0; bit < std::max(this->width(), rhs.width()); bit++) { if (this->bitIs1(bit) && rhs.bitIs0(bit)) { return 1; } if (rhs.bitIs1(bit) && this->bitIs0(bit)) { return 0; } if (this->bitIsXZ(bit)) { return 1; } @@ -873,23 +935,23 @@ bool V3Number::isLtXZ(const V3Number& rhs) const { } int V3Number::widthMin() const { - for (int bit=width()-1; bit>0; bit--) { - if (!bitIs0(bit)) return bit+1; + for (int bit = width() - 1; bit > 0; bit--) { + if (!bitIs0(bit)) return bit + 1; } return 1; // one bit even if number is == 0 } uint32_t V3Number::countOnes() const { int n = 0; - for (int bit=0; bitwidth(); bit++) { + for (int bit = 0; bit < this->width(); bit++) { if (bitIs1(bit)) n++; } return n; } uint32_t V3Number::mostSetBitP1() const { - for (int bit=this->width()-1; bit>=0; bit--) { - if (bitIs1(bit)) return bit+1; + for (int bit = this->width() - 1; bit >= 0; bit--) { + if (bitIs1(bit)) return bit + 1; } return 0; } @@ -900,8 +962,8 @@ V3Number& V3Number::opBitsNonX(const V3Number& lhs) { // 0/1->1, X/Z->0 NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_LOGIC_ARGS1(lhs); setZero(); - for (int bit=0; bitwidth(); bit++) { - if (lhs.bitIs0(bit) || lhs.bitIs1(bit)) { setBit(bit, 1); } + for (int bit = 0; bit < this->width(); bit++) { + if (lhs.bitIs0(bit) || lhs.bitIs1(bit)) setBit(bit, 1); } return *this; } @@ -910,8 +972,8 @@ V3Number& V3Number::opBitsOne(const V3Number& lhs) { // 1->1, 0/X/Z->0 NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_LOGIC_ARGS1(lhs); setZero(); - for (int bit=0; bitwidth(); bit++) { - if (lhs.bitIs1(bit)) { setBit(bit, 1); } + for (int bit = 0; bit < this->width(); bit++) { + if (lhs.bitIs1(bit)) setBit(bit, 1); } return *this; } @@ -920,8 +982,8 @@ V3Number& V3Number::opBitsXZ(const V3Number& lhs) { // 0/1->1, X/Z->0 NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_LOGIC_ARGS1(lhs); setZero(); - for (int bit=0; bitwidth(); bit++) { - if (lhs.bitIsXZ(bit)) { setBit(bit, 1); } + for (int bit = 0; bit < this->width(); bit++) { + if (lhs.bitIsXZ(bit)) setBit(bit, 1); } return *this; } @@ -930,8 +992,8 @@ V3Number& V3Number::opBitsZ(const V3Number& lhs) { // 0/1->1, X/Z->0 NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_LOGIC_ARGS1(lhs); setZero(); - for (int bit=0; bitwidth(); bit++) { - if (lhs.bitIsZ(bit)) { setBit(bit, 1); } + for (int bit = 0; bit < this->width(); bit++) { + if (lhs.bitIsZ(bit)) setBit(bit, 1); } return *this; } @@ -940,8 +1002,8 @@ V3Number& V3Number::opBitsNonZ(const V3Number& lhs) { // 0/1->1, X/Z->0 NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_LOGIC_ARGS1(lhs); setZero(); - for (int bit=0; bitwidth(); bit++) { - if (!lhs.bitIsZ(bit)) { setBit(bit, 1); } + for (int bit = 0; bit < this->width(); bit++) { + if (!lhs.bitIsZ(bit)) setBit(bit, 1); } return *this; } @@ -954,10 +1016,13 @@ V3Number& V3Number::opRedOr(const V3Number& lhs) { NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_LOGIC_ARGS1(lhs); char outc = 0; - for (int bit=0; bit=0; bit--) { + int adjust = (lhs.countOnes() == 1) ? 0 : 1; + for (int bit = lhs.width() - 1; bit >= 0; bit--) { if (lhs.bitIs1(bit)) { - setLong(bit+adjust); + setLong(bit + adjust); return *this; } } @@ -1045,12 +1127,16 @@ V3Number& V3Number::opLogNot(const V3Number& lhs) { NUM_ASSERT_LOGIC_ARGS1(lhs); // op i, 1 bit return char outc = 1; - for (int bit=0; bitwidth(); bit++) { - if (lhs.bitIs0(bit)) { setBit(bit, 1); } - else if (lhs.bitIsXZ(bit)) { setBit(bit,'x'); } + for (int bit = 0; bit < this->width(); bit++) { + if (lhs.bitIs0(bit)) { + setBit(bit, 1); + } else if (lhs.bitIsXZ(bit)) { + setBit(bit, 'x'); + } } return *this; } @@ -1071,10 +1160,13 @@ V3Number& V3Number::opAnd(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); // i op j, max(L(lhs),L(rhs)) bit return, careful need to X/Z extend. setZero(); - for (int bit=0; bitwidth(); bit++) { - if (lhs.bitIs1(bit) && rhs.bitIs1(bit)) { setBit(bit, 1); } - else if (lhs.bitIs0(bit) || rhs.bitIs0(bit)) ; // 0 - else { setBit(bit,'x'); } + for (int bit = 0; bit < this->width(); bit++) { + if (lhs.bitIs1(bit) && rhs.bitIs1(bit)) { + setBit(bit, 1); + } else if (lhs.bitIs0(bit) || rhs.bitIs0(bit)) { // 0 + } else { + setBit(bit, 'x'); + } } return *this; } @@ -1084,10 +1176,14 @@ V3Number& V3Number::opOr(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); // i op j, max(L(lhs),L(rhs)) bit return, careful need to X/Z extend. setZero(); - for (int bit=0; bitwidth(); bit++) { - if (lhs.bitIs1(bit) || rhs.bitIs1(bit)) { setBit(bit, 1); } - else if (lhs.bitIs0(bit) && rhs.bitIs0(bit)) ; // 0 - else { setBit(bit,'x'); } + for (int bit = 0; bit < this->width(); bit++) { + if (lhs.bitIs1(bit) || rhs.bitIs1(bit)) { + setBit(bit, 1); + } else if (lhs.bitIs0(bit) && rhs.bitIs0(bit)) { + ; // 0 + } else { + setBit(bit, 'x'); + } } return *this; } @@ -1105,10 +1201,14 @@ V3Number& V3Number::opXor(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_OP_ARGS2(lhs, rhs); NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); setZero(); - for (int bit=0; bitwidth(); bit++) { - if (lhs.bitIs1(bit) && rhs.bitIs0(bit)) { setBit(bit, 1); } - else if (lhs.bitIs0(bit) && rhs.bitIs1(bit)) { setBit(bit, 1); } - else if (lhs.bitIsXZ(bit) && rhs.bitIsXZ(bit)) { setBit(bit,'x'); } + for (int bit = 0; bit < this->width(); bit++) { + if (lhs.bitIs1(bit) && rhs.bitIs0(bit)) { + setBit(bit, 1); + } else if (lhs.bitIs0(bit) && rhs.bitIs1(bit)) { + setBit(bit, 1); + } else if (lhs.bitIsXZ(bit) && rhs.bitIsXZ(bit)) { + setBit(bit, 'x'); + } // else zero } return *this; @@ -1119,10 +1219,14 @@ V3Number& V3Number::opXnor(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_OP_ARGS2(lhs, rhs); NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); setZero(); - for (int bit=0; bitwidth(); bit++) { - if (lhs.bitIs1(bit) && rhs.bitIs1(bit)) { setBit(bit, 1); } - else if (lhs.bitIs0(bit) && rhs.bitIs0(bit)) { setBit(bit, 1); } - else if (lhs.bitIsXZ(bit) && rhs.bitIsXZ(bit)) { setBit(bit,'x'); } + for (int bit = 0; bit < this->width(); bit++) { + if (lhs.bitIs1(bit) && rhs.bitIs1(bit)) { + setBit(bit, 1); + } else if (lhs.bitIs0(bit) && rhs.bitIs0(bit)) { + setBit(bit, 1); + } else if (lhs.bitIsXZ(bit) && rhs.bitIsXZ(bit)) { + setBit(bit, 'x'); + } // else zero } return *this; @@ -1137,11 +1241,11 @@ V3Number& V3Number::opConcat(const V3Number& lhs, const V3Number& rhs) { v3warn(WIDTHCONCAT, "Unsized numbers/parameters not allowed in concatenations."); } int obit = 0; - for (int bit=0; bit 8192) { - v3warn(WIDTHCONCAT, "More than a 8k bit replication is probably wrong: "<(lhs.width())); - for (int istart=0; istartwidth() != rhs.width()) return false; - for (int bit=0; bit < std::max(this->width(), rhs.width()); bit++) { + for (int bit = 0; bit < std::max(this->width(), rhs.width()); bit++) { if (this->bitIs(bit) != rhs.bitIs(bit)) { return false; } } return true; @@ -1375,17 +1508,23 @@ bool V3Number::isCaseEq(const V3Number& rhs) const { V3Number& V3Number::opCaseEq(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_OP_ARGS2(lhs, rhs); - return setSingleBits(lhs.isCaseEq(rhs) ? 1:0); + return setSingleBits(lhs.isCaseEq(rhs) ? 1 : 0); } V3Number& V3Number::opCaseNeq(const V3Number& lhs, const V3Number& rhs) { // i op j, 1 bit return, max(L(lhs),L(rhs)) calculation, careful need to X/Z extend. NUM_ASSERT_OP_ARGS2(lhs, rhs); char outc = 0; - if (lhs.isString()) return opNeqN(lhs, rhs); - else if (lhs.isDouble()) return opNeqD(lhs, rhs); - for (int bit=0; bit < std::max(lhs.width(), rhs.width()); bit++) { - if (lhs.bitIs(bit) != rhs.bitIs(bit)) { outc=1; goto last; } + if (lhs.isString()) { + return opNeqN(lhs, rhs); + } else if (lhs.isDouble()) { + return opNeqD(lhs, rhs); + } + for (int bit = 0; bit < std::max(lhs.width(), rhs.width()); bit++) { + if (lhs.bitIs(bit) != rhs.bitIs(bit)) { + outc = 1; + goto last; + } } last: return setSingleBits(outc); @@ -1395,10 +1534,12 @@ V3Number& V3Number::opWildEq(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_OP_ARGS2(lhs, rhs); NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); char outc = 1; - for (int bit=0; bit < std::max(lhs.width(), rhs.width()); bit++) { - if (!rhs.bitIsXZ(bit) - && lhs.bitIs(bit) != rhs.bitIs(bit)) { outc = 0; goto last; } - if (lhs.bitIsXZ(bit)) outc='x'; + for (int bit = 0; bit < std::max(lhs.width(), rhs.width()); bit++) { + if (!rhs.bitIsXZ(bit) && lhs.bitIs(bit) != rhs.bitIs(bit)) { + outc = 0; + goto last; + } + if (lhs.bitIsXZ(bit)) outc = 'x'; } last: return setSingleBits(outc); @@ -1408,10 +1549,12 @@ V3Number& V3Number::opWildNeq(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_OP_ARGS2(lhs, rhs); NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); char outc = 0; - for (int bit=0; bit < std::max(lhs.width(), rhs.width()); bit++) { - if (!rhs.bitIsXZ(bit) - && lhs.bitIs(bit) != rhs.bitIs(bit)) { outc=1; goto last; } - if (lhs.bitIsXZ(bit)) outc='x'; + for (int bit = 0; bit < std::max(lhs.width(), rhs.width()); bit++) { + if (!rhs.bitIsXZ(bit) && lhs.bitIs(bit) != rhs.bitIs(bit)) { + outc = 1; + goto last; + } + if (lhs.bitIsXZ(bit)) outc = 'x'; } last: return setSingleBits(outc); @@ -1422,11 +1565,11 @@ V3Number& V3Number::opGt(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_OP_ARGS2(lhs, rhs); NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); char outc = 0; - for (int bit=0; bit < std::max(lhs.width(), rhs.width()); bit++) { - if (lhs.bitIs1(bit) && rhs.bitIs0(bit)) { outc=1; } - if (rhs.bitIs1(bit) && lhs.bitIs0(bit)) { outc = 0; } - if (lhs.bitIsXZ(bit)) { outc='x'; } - if (rhs.bitIsXZ(bit)) { outc='x'; } + for (int bit = 0; bit < std::max(lhs.width(), rhs.width()); bit++) { + if (lhs.bitIs1(bit) && rhs.bitIs0(bit)) outc = 1; + if (rhs.bitIs1(bit) && lhs.bitIs0(bit)) outc = 0; + if (lhs.bitIsXZ(bit)) outc = 'x'; + if (rhs.bitIsXZ(bit)) outc = 'x'; } return setSingleBits(outc); } @@ -1437,18 +1580,22 @@ V3Number& V3Number::opGtS(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); char outc = 0; { - int mbit = std::max(lhs.width()-1, rhs.width()-1); - if (lhs.bitIsXZ(mbit)) { outc='x'; } - else if (rhs.bitIsXZ(mbit)) { outc='x'; } - else if (lhs.bitIs0(mbit) && rhs.bitIs1Extend(mbit)) { outc = 1; } // + > - - else if (lhs.bitIs1Extend(mbit) && rhs.bitIs0(mbit)) { outc = 0; } // - !> + - else { + int mbit = std::max(lhs.width() - 1, rhs.width() - 1); + if (lhs.bitIsXZ(mbit)) { + outc = 'x'; + } else if (rhs.bitIsXZ(mbit)) { + outc = 'x'; + } else if (lhs.bitIs0(mbit) && rhs.bitIs1Extend(mbit)) { + outc = 1; // + > - + } else if (lhs.bitIs1Extend(mbit) && rhs.bitIs0(mbit)) { + outc = 0; // - !> + + } else { // both positive or negative, normal > - for (int bit=0; bit < std::max(lhs.width()-1, rhs.width()-1); bit++) { - if (lhs.bitIs1Extend(bit) && rhs.bitIs0(bit)) { outc = 1; } - if (rhs.bitIs1Extend(bit) && lhs.bitIs0(bit)) { outc = 0; } - if (lhs.bitIsXZ(bit)) { outc = 'x'; } - if (rhs.bitIsXZ(bit)) { outc = 'x'; } + for (int bit = 0; bit < std::max(lhs.width() - 1, rhs.width() - 1); bit++) { + if (lhs.bitIs1Extend(bit) && rhs.bitIs0(bit)) outc = 1; + if (rhs.bitIs1Extend(bit) && lhs.bitIs0(bit)) outc = 0; + if (lhs.bitIsXZ(bit)) outc = 'x'; + if (rhs.bitIsXZ(bit)) outc = 'x'; } } } @@ -1471,18 +1618,10 @@ V3Number& V3Number::opGteS(const V3Number& lhs, const V3Number& rhs) { return opGtS(lhs, rhs); } -V3Number& V3Number::opLt(const V3Number& lhs, const V3Number& rhs) { - return opGt(rhs, lhs); -} -V3Number& V3Number::opLte(const V3Number& lhs, const V3Number& rhs) { - return opGte(rhs, lhs); -} -V3Number& V3Number::opLtS(const V3Number& lhs, const V3Number& rhs) { - return opGtS(rhs, lhs); -} -V3Number& V3Number::opLteS(const V3Number& lhs, const V3Number& rhs) { - return opGteS(rhs, lhs); -} +V3Number& V3Number::opLt(const V3Number& lhs, const V3Number& rhs) { return opGt(rhs, lhs); } +V3Number& V3Number::opLte(const V3Number& lhs, const V3Number& rhs) { return opGte(rhs, lhs); } +V3Number& V3Number::opLtS(const V3Number& lhs, const V3Number& rhs) { return opGtS(rhs, lhs); } +V3Number& V3Number::opLteS(const V3Number& lhs, const V3Number& rhs) { return opGteS(rhs, lhs); } V3Number& V3Number::opRotR(const V3Number& lhs, const V3Number& rhs) { // L(lhs) bit return @@ -1491,7 +1630,7 @@ V3Number& V3Number::opRotR(const V3Number& lhs, const V3Number& rhs) { if (rhs.isFourState()) return setAllBitsX(); setZero(); uint32_t rhsval = rhs.toUInt(); - for (int bit=0; bitwidth(); bit++) { + for (int bit = 0; bit < this->width(); bit++) { setBit(bit, lhs.bitIs((bit + rhsval) % this->width())); } return *this; @@ -1504,7 +1643,7 @@ V3Number& V3Number::opRotL(const V3Number& lhs, const V3Number& rhs) { if (rhs.isFourState()) return setAllBitsX(); setZero(); uint32_t rhsval = rhs.toUInt(); - for (int bit=0; bitwidth(); bit++) { + for (int bit = 0; bit < this->width(); bit++) { if (bit >= static_cast(rhsval)) { setBit(bit, lhs.bitIs((bit - rhsval) % this->width())); } @@ -1518,14 +1657,12 @@ V3Number& V3Number::opShiftR(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); if (rhs.isFourState()) return setAllBitsX(); setZero(); - for (int bit=32; bit(lhs.width())) { - for (int bit=0; bitwidth(); bit++) { - setBit(bit, lhs.bitIs(bit + rhsval)); - } + for (int bit = 0; bit < this->width(); bit++) setBit(bit, lhs.bitIs(bit + rhsval)); } return *this; } @@ -1538,21 +1675,21 @@ V3Number& V3Number::opShiftRS(const V3Number& lhs, const V3Number& rhs, uint32_t NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); if (rhs.isFourState()) return setAllBitsX(); setZero(); - for (int bit=32; bitwidth(); sbit++) { setBit(sbit, lhs.bitIs(lbits - 1)); // 0/1/X/Z } - if (rhs.bitIs1(lbits-1)) setAllBits1(); // -1 else 0 + if (rhs.bitIs1(lbits - 1)) setAllBits1(); // -1 else 0 return *this; // shift of over 2^32 must be -1/0 } uint32_t rhsval = rhs.toUInt(); if (rhsval < static_cast(lhs.width())) { - for (int bit=0; bitwidth(); bit++) { + for (int bit = 0; bit < this->width(); bit++) { setBit(bit, lhs.bitIsExtend(bit + rhsval, lbits)); } } else { - for (int bit=0; bitwidth(); bit++) { - setBit(bit, lhs.bitIs(lbits-1)); // 0/1/X/Z + for (int bit = 0; bit < this->width(); bit++) { + setBit(bit, lhs.bitIs(lbits - 1)); // 0/1/X/Z } } return *this; @@ -1564,14 +1701,12 @@ V3Number& V3Number::opShiftL(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); if (rhs.isFourState()) return setAllBitsX(); setZero(); - for (int bit=32; bitwidth(); bit++) { - if (bit >= static_cast(rhsval)) { - setBit(bit, lhs.bitIs(bit - rhsval)); - } + for (int bit = 0; bit < this->width(); bit++) { + if (bit >= static_cast(rhsval)) setBit(bit, lhs.bitIs(bit - rhsval)); } return *this; } @@ -1594,9 +1729,9 @@ V3Number& V3Number::opNegate(const V3Number& lhs) { NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_LOGIC_ARGS1(lhs); if (lhs.isFourState()) return setAllBitsX(); - V3Number notlhs (&lhs, width()); + V3Number notlhs(&lhs, width()); notlhs.opNot(lhs); - V3Number one (&lhs, width(), 1); + V3Number one(&lhs, width(), 1); opAdd(notlhs, one); return *this; } @@ -1607,12 +1742,10 @@ V3Number& V3Number::opAdd(const V3Number& lhs, const V3Number& rhs) { if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX(); setZero(); // Addem - int carry=0; - for (int bit=0; bitwidth(); bit++) { - int sum = ((lhs.bitIs1(bit)?1:0) + (rhs.bitIs1(bit)?1:0) + carry); - if (sum & 1) { - setBit(bit, 1); - } + int carry = 0; + for (int bit = 0; bit < this->width(); bit++) { + int sum = ((lhs.bitIs1(bit) ? 1 : 0) + (rhs.bitIs1(bit) ? 1 : 0) + carry); + if (sum & 1) setBit(bit, 1); carry = (sum >= 2); } return *this; @@ -1622,7 +1755,7 @@ V3Number& V3Number::opSub(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_OP_ARGS2(lhs, rhs); NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX(); - V3Number negrhs (&rhs, rhs.width()); + V3Number negrhs(&rhs, rhs.width()); negrhs.opNegate(rhs); return opAdd(lhs, negrhs); } @@ -1636,11 +1769,11 @@ V3Number& V3Number::opMul(const V3Number& lhs, const V3Number& rhs) { setQuad(lhs.toUQuad() * rhs.toUQuad()); opCleanThis(); // Mult produces extra bits in result } else { - for (int lword=0; lword(lhs.m_value[lword]) - * static_cast(rhs.m_value[rword]); - for (int qword=lword+rword; qwordwords(); qword++) { + * static_cast(rhs.m_value[rword]); + for (int qword = lword + rword; qword < this->words(); qword++) { mul += static_cast(m_value[qword]); m_value[qword] = (mul & VL_ULL(0xffffffff)); mul = (mul >> VL_ULL(32)) & VL_ULL(0xffffffff); @@ -1656,11 +1789,12 @@ V3Number& V3Number::opMulS(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_OP_ARGS2(lhs, rhs); NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX(); - V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs); - V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs); + V3Number lhsNoSign = lhs; + if (lhs.isNegative()) lhsNoSign.opNegate(lhs); + V3Number rhsNoSign = rhs; + if (rhs.isNegative()) rhsNoSign.opNegate(rhs); V3Number qNoSign = opMul(lhsNoSign, rhsNoSign); - if ((lhs.isNegative() && !rhs.isNegative()) - || (!lhs.isNegative() && rhs.isNegative())) { + if ((lhs.isNegative() && !rhs.isNegative()) || (!lhs.isNegative() && rhs.isNegative())) { opNegate(qNoSign); } else { opAssign(qNoSign); @@ -1671,10 +1805,10 @@ V3Number& V3Number::opDiv(const V3Number& lhs, const V3Number& rhs) { // i op j, max(L(lhs),L(rhs)) bit return, if any 4-state, 4-state return NUM_ASSERT_OP_ARGS2(lhs, rhs); NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); - //UINFO(9, "opdiv "<>divs-start "<>divs-start "<divs-mid "<divs-mid "<> 32 won't mask the value - for (int i = vw-1; i>0; i--) { - vn[i] = (rhs.m_value[i] << s) | (shift_mask & (rhs.m_value[i-1] >> (32-s))); + for (int i = vw - 1; i > 0; i--) { + vn[i] = (rhs.m_value[i] << s) | (shift_mask & (rhs.m_value[i - 1] >> (32 - s))); } vn[0] = rhs.m_value[0] << s; // Copy and shift dividend by same amount; may set new upper word - if (s) un[uw] = lhs.m_value[uw-1] >> (32-s); - else un[uw] = 0; - for (int i=uw-1; i>0; i--) { - un[i] = (lhs.m_value[i] << s) | (shift_mask & (lhs.m_value[i-1] >> (32-s))); + if (s) { + un[uw] = lhs.m_value[uw - 1] >> (32 - s); + } else { + un[uw] = 0; + } + for (int i = uw - 1; i > 0; i--) { + un[i] = (lhs.m_value[i] << s) | (shift_mask & (lhs.m_value[i - 1] >> (32 - s))); } un[0] = lhs.m_value[0] << s; - //printf(" un="); for (int i=5; i>=0; i--) printf(" %08x",un[i]); printf("\n"); - //printf(" vn="); for (int i=5; i>=0; i--) printf(" %08x",vn[i]); printf("\n"); - //printf(" mv="); for (int i=5; i>=0; i--) printf(" %08x",m_value[i]); printf("\n"); + // printf(" un="); for (int i=5; i>=0; i--) printf(" %08x",un[i]); printf("\n"); + // printf(" vn="); for (int i=5; i>=0; i--) printf(" %08x",vn[i]); printf("\n"); + // printf(" mv="); for (int i=5; i>=0; i--) printf(" %08x",m_value[i]); printf("\n"); // Main loop for (int j = uw - vw; j >= 0; j--) { // Estimate - vluint64_t unw64 = (static_cast(un[j+vw])<(un[j+vw-1])); - vluint64_t qhat = unw64 / static_cast(vn[vw-1]); - vluint64_t rhat = unw64 - qhat*static_cast(vn[vw-1]); + vluint64_t unw64 = (static_cast(un[j + vw]) << VL_ULL(32) + | static_cast(un[j + vw - 1])); + vluint64_t qhat = unw64 / static_cast(vn[vw - 1]); + vluint64_t rhat = unw64 - qhat * static_cast(vn[vw - 1]); - again: + again: if (qhat >= VL_ULL(0x100000000) - || ((qhat*vn[vw-2]) > ((rhat< ((rhat << VL_ULL(32)) + un[j + vw - 2]))) { qhat = qhat - 1; - rhat = rhat + vn[vw-1]; + rhat = rhat + vn[vw - 1]; if (rhat < VL_ULL(0x100000000)) goto again; } vlsint64_t t = 0; // Must be signed vluint64_t k = 0; - for (int i=0; i> VL_ULL(32)) - (t >> VL_ULL(32)); } - t = un[j+vw] - k; - un[j+vw] = t; + t = un[j + vw] - k; + un[j + vw] = t; this->m_value[j] = qhat; // Save quotient digit if (t < 0) { // Over subtracted; correct by adding back this->m_value[j]--; k = 0; - for (int i=0; i(un[i+j]) + static_cast(vn[i]) + k; - un[i+j] = t; + for (int i = 0; i < vw; i++) { + t = static_cast(un[i + j]) + static_cast(vn[i]) + k; + un[i + j] = t; k = t >> VL_ULL(32); } - un[j+vw] = un[j+vw] + k; + un[j + vw] = un[j + vw] + k; } } - //printf(" un="); for (int i=5; i>=0; i--) printf(" %08x",un[i]); printf("\n"); - //printf(" vn="); for (int i=5; i>=0; i--) printf(" %08x",vn[i]); printf("\n"); - //printf(" mv="); for (int i=5; i>=0; i--) printf(" %08x",m_value[i]); printf("\n"); + // printf(" un="); for (int i=5; i>=0; i--) printf(" %08x",un[i]); printf("\n"); + // printf(" vn="); for (int i=5; i>=0; i--) printf(" %08x",vn[i]); printf("\n"); + // printf(" mv="); for (int i=5; i>=0; i--) printf(" %08x",m_value[i]); printf("\n"); if (is_modulus) { // modulus // Need to reverse normalization on copy to output - for (int i=0; i> s) | (shift_mask & (un[i+1] << (32-s))); + for (int i = 0; i < vw; i++) { + m_value[i] = (un[i] >> s) | (shift_mask & (un[i + 1] << (32 - s))); } - for (int i=vw; iwidth(); bit++) { - if (ibit>=0 && ibit(msbval)) { + for (int bit = 0; bit < this->width(); bit++) { + if (ibit >= 0 && ibit < lhs.width() && ibit <= static_cast(msbval)) { setBit(bit, lhs.bitIs(ibit)); } else { setBit(bit, 'x'); } ++ibit; } - //UINFO(0,"RANGE "<width(); bit++) { - if (if0s.bitIs1(bit) && if1s.bitIs1(bit)) { setBit(bit, 1); } - else if (if0s.bitIs0(bit) && if1s.bitIs0(bit)) { setBit(bit, 0); } - else setBit(bit,'x'); + for (int bit = 0; bit < this->width(); bit++) { + if (if0s.bitIs1(bit) && if1s.bitIs1(bit)) { + setBit(bit, 1); + } else if (if0s.bitIs0(bit) && if1s.bitIs0(bit)) { + setBit(bit, 0); + } else { + setBit(bit, 'x'); + } } } return *this; @@ -2063,8 +2218,12 @@ V3Number& V3Number::opRToIRoundS(const V3Number& lhs) { NUM_ASSERT_DOUBLE_ARGS1(lhs); double v = VL_ROUND(lhs.toDouble()); setZero(); - union { double d; vluint64_t q; } u; - u.d = v; if (u.d == 0.0) {} + union { + double d; + vluint64_t q; + } u; + u.d = v; + if (u.d == 0.0) {} int exp = static_cast((u.q >> VL_ULL(52)) & VL_MASK_Q(11)) - 1023; int lsb = exp - 52; @@ -2089,7 +2248,7 @@ V3Number& V3Number::opRealToBits(const V3Number& lhs) { NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_DOUBLE_ARGS1(lhs); // Conveniently our internal format is identical so we can copy bits... - if (lhs.width()!=64 || this->width()!=64) { + if (lhs.width() != 64 || this->width() != 64) { v3fatalSrc("Real operation on wrong sized number"); } opAssign(lhs); @@ -2099,7 +2258,7 @@ V3Number& V3Number::opRealToBits(const V3Number& lhs) { V3Number& V3Number::opBitsToRealD(const V3Number& lhs) { NUM_ASSERT_OP_ARGS1(lhs); // Conveniently our internal format is identical so we can copy bits... - if (lhs.width()!=64 || this->width()!=64) { + if (lhs.width() != 64 || this->width() != 64) { v3fatalSrc("Real operation on wrong sized number"); } opAssign(lhs); @@ -2109,7 +2268,7 @@ V3Number& V3Number::opBitsToRealD(const V3Number& lhs) { V3Number& V3Number::opNegateD(const V3Number& lhs) { NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_DOUBLE_ARGS1(lhs); - return setDouble(- lhs.toDouble()); + return setDouble(-lhs.toDouble()); } V3Number& V3Number::opAddD(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_OP_ARGS2(lhs, rhs); @@ -2180,34 +2339,30 @@ V3Number& V3Number::opConcatN(const V3Number& lhs, const V3Number& rhs) { return setString(lhs.toString() + rhs.toString()); } V3Number& V3Number::opReplN(const V3Number& lhs, const V3Number& rhs) { - NUM_ASSERT_STRING_ARGS1(lhs); NUM_ASSERT_LOGIC_ARGS1(rhs); + NUM_ASSERT_STRING_ARGS1(lhs); + NUM_ASSERT_LOGIC_ARGS1(rhs); return opReplN(lhs, rhs.toUInt()); } V3Number& V3Number::opReplN(const V3Number& lhs, uint32_t rhsval) { NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_STRING_ARGS1(lhs); - string out; out.reserve(lhs.toString().length() * rhsval); - for (unsigned times=0; times m_value; // The Value, with bit 0 being in bit 0 of this vector (unless X/Z) + int m_width; // Width as specified/calculated. + bool m_sized : 1; // True if the user specified the width, else we track it. + bool m_signed : 1; // True if signed value + bool m_double : 1; // True if double real value + bool m_isString : 1; // True if string + bool m_fromString : 1; // True if from string literal + bool m_autoExtend : 1; // True if SystemVerilog extend-to-any-width + FileLine* m_fileline; + AstNode* m_nodep; // Parent node + std::vector m_value; // Value, with bit 0 in bit 0 of this vector (unless X/Z) std::vector m_valueX; // Each bit is true if it's X or Z, 10=z, 11=x - string m_stringVal; // If isString, the value of the string + string m_stringVal; // If isString, the value of the string // METHODS V3Number& setSingleBits(char value); - V3Number& setString(const string& str) { m_isString = true; m_stringVal = str; return *this; } + V3Number& setString(const string& str) { + m_isString = true; + m_stringVal = str; + return *this; + } void opCleanThis(bool warnOnTruncation = false); + public: void nodep(AstNode* nodep) { setNames(nodep); } FileLine* fileline() const { return m_fileline; } @@ -64,79 +69,87 @@ public: V3Number& setLongS(vlsint32_t value); V3Number& setDouble(double value); void setBit(int bit, char value) { // Note must be pre-zeroed! - if (bit>=m_width) return; - uint32_t mask = (1UL<<(bit&31)); - if (value=='0' || value==0) { - m_value [bit/32] &= ~mask; - m_valueX[bit/32] &= ~mask; - } else if (value=='1'|| value==1) { - m_value [bit/32] |= mask; - m_valueX[bit/32] &= ~mask; - } else if (value=='z'|| value==2) { - m_value [bit/32] &= ~mask; - m_valueX[bit/32] |= mask; + if (bit >= m_width) return; + uint32_t mask = (1UL << (bit & 31)); + if (value == '0' || value == 0) { + m_value[bit / 32] &= ~mask; + m_valueX[bit / 32] &= ~mask; + } else if (value == '1' || value == 1) { + m_value[bit / 32] |= mask; + m_valueX[bit / 32] &= ~mask; + } else if (value == 'z' || value == 2) { + m_value[bit / 32] &= ~mask; + m_valueX[bit / 32] |= mask; } else { // X - m_value [bit/32] |= mask; - m_valueX[bit/32] |= mask; + m_value[bit / 32] |= mask; + m_valueX[bit / 32] |= mask; } } + private: char bitIs(int bit) const { - if (bit>=m_width || bit<0) { + if (bit >= m_width || bit < 0) { // We never sign extend return '0'; } - return ( "01zx"[(((m_value[bit/32] & (1UL<<(bit&31)))?1:0) - | ((m_valueX[bit/32] & (1UL<<(bit&31)))?2:0))] ); } + return ("01zx"[(((m_value[bit / 32] & (1UL << (bit & 31))) ? 1 : 0) + | ((m_valueX[bit / 32] & (1UL << (bit & 31))) ? 2 : 0))]); + } char bitIsExtend(int bit, int lbits) const { // lbits usually = width, but for C optimizations width=32_bits, lbits = 32_or_less - if (bit<0) return '0'; - UASSERT(lbits<=m_width, "Extend of wrong size"); - if (bit>=lbits) { - bit = lbits ? lbits-1 : 0; + if (bit < 0) return '0'; + UASSERT(lbits <= m_width, "Extend of wrong size"); + if (bit >= lbits) { + bit = lbits ? lbits - 1 : 0; // We do sign extend - return ( "01zx"[(((m_value[bit/32] & (1UL<<(bit&31)))?1:0) - | ((m_valueX[bit/32] & (1UL<<(bit&31)))?2:0))] ); + return ("01zx"[(((m_value[bit / 32] & (1UL << (bit & 31))) ? 1 : 0) + | ((m_valueX[bit / 32] & (1UL << (bit & 31))) ? 2 : 0))]); } - return ( "01zx"[(((m_value[bit/32] & (1UL<<(bit&31)))?1:0) - | ((m_valueX[bit/32] & (1UL<<(bit&31)))?2:0))] ); } + return ("01zx"[(((m_value[bit / 32] & (1UL << (bit & 31))) ? 1 : 0) + | ((m_valueX[bit / 32] & (1UL << (bit & 31))) ? 2 : 0))]); + } bool bitIs0(int bit) const { - if (bit<0) return false; - if (bit>=m_width) return !bitIsXZ(m_width-1); - return ( (m_value[bit/32] & (1UL<<(bit&31)))==0 - && !(m_valueX[bit/32] & (1UL<<(bit&31))) ); } + if (bit < 0) return false; + if (bit >= m_width) return !bitIsXZ(m_width - 1); + return ((m_value[bit / 32] & (1UL << (bit & 31))) == 0 + && !(m_valueX[bit / 32] & (1UL << (bit & 31)))); + } bool bitIs1(int bit) const { - if (bit<0) return false; - if (bit>=m_width) return false; - return ( (m_value[bit/32] & (1UL<<(bit&31))) - && !(m_valueX[bit/32] & (1UL<<(bit&31))) ); } + if (bit < 0) return false; + if (bit >= m_width) return false; + return ((m_value[bit / 32] & (1UL << (bit & 31))) + && !(m_valueX[bit / 32] & (1UL << (bit & 31)))); + } bool bitIs1Extend(int bit) const { - if (bit<0) return false; - if (bit>=m_width) return bitIs1Extend(m_width-1); - return ( (m_value[bit/32] & (1UL<<(bit&31))) - && !(m_valueX[bit/32] & (1UL<<(bit&31))) ); } + if (bit < 0) return false; + if (bit >= m_width) return bitIs1Extend(m_width - 1); + return ((m_value[bit / 32] & (1UL << (bit & 31))) + && !(m_valueX[bit / 32] & (1UL << (bit & 31)))); + } bool bitIsX(int bit) const { - if (bit<0) return false; - if (bit>=m_width) return bitIsZ(m_width-1); - return ( (m_value[bit/32] & (1UL<<(bit&31))) - && (m_valueX[bit/32] & (1UL<<(bit&31))) ); } + if (bit < 0) return false; + if (bit >= m_width) return bitIsZ(m_width - 1); + return ((m_value[bit / 32] & (1UL << (bit & 31))) + && (m_valueX[bit / 32] & (1UL << (bit & 31)))); + } bool bitIsXZ(int bit) const { - if (bit<0) return false; - if (bit>=m_width) return bitIsXZ(m_width-1); - return ( (m_valueX[bit/32] & (1UL<<(bit&31)))); + if (bit < 0) return false; + if (bit >= m_width) return bitIsXZ(m_width - 1); + return ((m_valueX[bit / 32] & (1UL << (bit & 31)))); } bool bitIsZ(int bit) const { - if (bit<0) return false; - if (bit>=m_width) return bitIsZ(m_width-1); - return ( (~m_value[bit/32] & (1UL<<(bit&31))) - && (m_valueX[bit/32] & (1UL<<(bit&31))) ); } + if (bit < 0) return false; + if (bit >= m_width) return bitIsZ(m_width - 1); + return ((~m_value[bit / 32] & (1UL << (bit & 31))) + && (m_valueX[bit / 32] & (1UL << (bit & 31)))); + } uint32_t bitsValue(int lsb, int nbits) const { uint32_t v = 0; - for (int bitn=0; bitnfileline(); @@ -169,7 +187,7 @@ public: private: void V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl); - void init(AstNode* nodep, int swidth, bool sized=true) { + void init(AstNode* nodep, int swidth, bool sized = true) { setNames(nodep); m_signed = false; m_double = false; @@ -177,23 +195,27 @@ private: m_autoExtend = false; m_fromString = false; width(swidth, sized); - for (int i=0; i0b11, if 3->0b111 etc // ACCESSORS - string ascii(bool prefixed=true, bool cleanVerilog=false) const; + string ascii(bool prefixed = true, bool cleanVerilog = false) const; string displayed(AstNode* nodep, const string& vformat) const; static bool displayedFmtLegal(char format); // Is this a valid format letter? int width() const { return m_width; } @@ -214,26 +236,35 @@ public: bool sized() const { return m_sized; } bool autoExtend() const { return m_autoExtend; } bool isFromString() const { return m_fromString; } - bool isSigned() const { return m_signed; } // Only correct for parsing of numbers from strings, otherwise not used (use AstConst::isSigned()) - bool isDouble() const { return m_double; } // Only correct for parsing of numbers from strings, otherwise not used (use AstConst::isSigned()) - void isDouble(bool flag) { m_double = flag; } // Only if have 64 bit value loaded, and want to indicate it's real + // Only correct for parsing of numbers from strings, otherwise not used + // (use AstConst::isSigned()) + bool isSigned() const { return m_signed; } + // Only correct for parsing of numbers from strings, otherwise not used + // (use AstConst::isSigned()) + bool isDouble() const { return m_double; } + // Only if have 64 bit value loaded, and want to indicate it's real + void isDouble(bool flag) { m_double = flag; } bool isString() const { return m_isString; } - void isString(bool flag) { m_isString = flag; } - bool isNegative() const { return bitIs1(width()-1); } + void isString(bool flag) { m_isString = flag; } + bool isNegative() const { return bitIs1(width() - 1); } bool isFourState() const; bool hasZ() const { - for(int i=0;i1, X/Z->0 - V3Number& opBitsOne (const V3Number& lhs); // 1->1, 0/X/Z->0 - V3Number& opBitsXZ (const V3Number& lhs); // 0/1->0, X/Z->1 - V3Number& opBitsZ (const V3Number& lhs); // Z->1, 0/1/X->0 + V3Number& opBitsOne(const V3Number& lhs); // 1->1, 0/X/Z->0 + V3Number& opBitsXZ(const V3Number& lhs); // 0/1->0, X/Z->1 + V3Number& opBitsZ(const V3Number& lhs); // Z->1, 0/1/X->0 V3Number& opBitsNonZ(const V3Number& lhs); // Z->0, 0/1/X->1 // - V3Number& opAssign (const V3Number& lhs); + V3Number& opAssign(const V3Number& lhs); V3Number& opAssignNonXZ(const V3Number& lhs, bool ignoreXZ = true); - V3Number& opExtendS (const V3Number& lhs, uint32_t lbits); // Sign extension + V3Number& opExtendS(const V3Number& lhs, uint32_t lbits); // Sign extension V3Number& opExtendXZ(const V3Number& lhs, uint32_t lbits); // X/Z extension - V3Number& opRedOr (const V3Number& lhs); - V3Number& opRedAnd (const V3Number& lhs); - V3Number& opRedXor (const V3Number& lhs); - V3Number& opRedXnor (const V3Number& lhs); + V3Number& opRedOr(const V3Number& lhs); + V3Number& opRedAnd(const V3Number& lhs); + V3Number& opRedXor(const V3Number& lhs); + V3Number& opRedXnor(const V3Number& lhs); V3Number& opCountOnes(const V3Number& lhs); V3Number& opIsUnknown(const V3Number& lhs); - V3Number& opOneHot (const V3Number& lhs); - V3Number& opOneHot0 (const V3Number& lhs); - V3Number& opCLog2 (const V3Number& lhs); - V3Number& opClean (const V3Number& lhs, uint32_t bits); - V3Number& opConcat (const V3Number& lhs, const V3Number& rhs); - V3Number& opLenN (const V3Number& lhs); - V3Number& opRepl (const V3Number& lhs, const V3Number& rhs); - V3Number& opRepl (const V3Number& lhs, uint32_t rhsval); - V3Number& opStreamL (const V3Number& lhs, const V3Number& rhs); - V3Number& opSel (const V3Number& lhs, const V3Number& msb, const V3Number& lsb); - V3Number& opSel (const V3Number& lhs, uint32_t msbval, uint32_t lsbval); - V3Number& opSelInto (const V3Number& lhs, const V3Number& lsb, int width); - V3Number& opSelInto (const V3Number& lhs, int lsbval, int width); + V3Number& opOneHot(const V3Number& lhs); + V3Number& opOneHot0(const V3Number& lhs); + V3Number& opCLog2(const V3Number& lhs); + V3Number& opClean(const V3Number& lhs, uint32_t bits); + V3Number& opConcat(const V3Number& lhs, const V3Number& rhs); + V3Number& opLenN(const V3Number& lhs); + V3Number& opRepl(const V3Number& lhs, const V3Number& rhs); + V3Number& opRepl(const V3Number& lhs, uint32_t rhsval); + V3Number& opStreamL(const V3Number& lhs, const V3Number& rhs); + V3Number& opSel(const V3Number& lhs, const V3Number& msb, const V3Number& lsb); + V3Number& opSel(const V3Number& lhs, uint32_t msbval, uint32_t lsbval); + V3Number& opSelInto(const V3Number& lhs, const V3Number& lsb, int width); + V3Number& opSelInto(const V3Number& lhs, int lsbval, int width); V3Number& opToLowerN(const V3Number& lhs); V3Number& opToUpperN(const V3Number& lhs); - V3Number& opCond (const V3Number& lhs, const V3Number& if1s, const V3Number& if0s); - V3Number& opCaseEq (const V3Number& lhs, const V3Number& rhs); - V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs); - V3Number& opWildEq (const V3Number& lhs, const V3Number& rhs); - V3Number& opWildNeq (const V3Number& lhs, const V3Number& rhs); - V3Number& opBufIf1 (const V3Number& ens, const V3Number& if1s); + V3Number& opCond(const V3Number& lhs, const V3Number& if1s, const V3Number& if0s); + V3Number& opCaseEq(const V3Number& lhs, const V3Number& rhs); + V3Number& opCaseNeq(const V3Number& lhs, const V3Number& rhs); + V3Number& opWildEq(const V3Number& lhs, const V3Number& rhs); + V3Number& opWildNeq(const V3Number& lhs, const V3Number& rhs); + V3Number& opBufIf1(const V3Number& ens, const V3Number& if1s); // "standard" math - V3Number& opNot (const V3Number& lhs); - V3Number& opLogNot (const V3Number& lhs); - V3Number& opLogAnd (const V3Number& lhs, const V3Number& rhs); - V3Number& opLogOr (const V3Number& lhs, const V3Number& rhs); - V3Number& opLogEq (const V3Number& lhs, const V3Number& rhs); - V3Number& opLogIf (const V3Number& lhs, const V3Number& rhs); - V3Number& opAbsS (const V3Number& lhs); - V3Number& opNegate (const V3Number& lhs); - V3Number& opAdd (const V3Number& lhs, const V3Number& rhs); - V3Number& opSub (const V3Number& lhs, const V3Number& rhs); - V3Number& opMul (const V3Number& lhs, const V3Number& rhs); - V3Number& opMulS (const V3Number& lhs, const V3Number& rhs); // Signed - V3Number& opDiv (const V3Number& lhs, const V3Number& rhs); - V3Number& opDivS (const V3Number& lhs, const V3Number& rhs); // Signed - V3Number& opModDiv (const V3Number& lhs, const V3Number& rhs); - V3Number& opModDivS (const V3Number& lhs, const V3Number& rhs); // Signed - V3Number& opPow (const V3Number& lhs, const V3Number& rhs, bool lsign=false, bool rsign=false); - V3Number& opPowSU (const V3Number& lhs, const V3Number& rhs); // Signed lhs, unsigned rhs - V3Number& opPowSS (const V3Number& lhs, const V3Number& rhs); // Signed lhs, signed rhs - V3Number& opPowUS (const V3Number& lhs, const V3Number& rhs); // Unsigned lhs, signed rhs - V3Number& opAnd (const V3Number& lhs, const V3Number& rhs); + V3Number& opNot(const V3Number& lhs); + V3Number& opLogNot(const V3Number& lhs); + V3Number& opLogAnd(const V3Number& lhs, const V3Number& rhs); + V3Number& opLogOr(const V3Number& lhs, const V3Number& rhs); + V3Number& opLogEq(const V3Number& lhs, const V3Number& rhs); + V3Number& opLogIf(const V3Number& lhs, const V3Number& rhs); + V3Number& opAbsS(const V3Number& lhs); + V3Number& opNegate(const V3Number& lhs); + V3Number& opAdd(const V3Number& lhs, const V3Number& rhs); + V3Number& opSub(const V3Number& lhs, const V3Number& rhs); + V3Number& opMul(const V3Number& lhs, const V3Number& rhs); + V3Number& opMulS(const V3Number& lhs, const V3Number& rhs); // Signed + V3Number& opDiv(const V3Number& lhs, const V3Number& rhs); + V3Number& opDivS(const V3Number& lhs, const V3Number& rhs); // Signed + V3Number& opModDiv(const V3Number& lhs, const V3Number& rhs); + V3Number& opModDivS(const V3Number& lhs, const V3Number& rhs); // Signed + V3Number& opPow(const V3Number& lhs, const V3Number& rhs, bool lsign = false, + bool rsign = false); + V3Number& opPowSU(const V3Number& lhs, const V3Number& rhs); // Signed lhs, unsigned rhs + V3Number& opPowSS(const V3Number& lhs, const V3Number& rhs); // Signed lhs, signed rhs + V3Number& opPowUS(const V3Number& lhs, const V3Number& rhs); // Unsigned lhs, signed rhs + V3Number& opAnd(const V3Number& lhs, const V3Number& rhs); V3Number& opChangeXor(const V3Number& lhs, const V3Number& rhs); - V3Number& opXor (const V3Number& lhs, const V3Number& rhs); - V3Number& opXnor (const V3Number& lhs, const V3Number& rhs); - V3Number& opOr (const V3Number& lhs, const V3Number& rhs); - V3Number& opRotR (const V3Number& lhs, const V3Number& rhs); - V3Number& opRotL (const V3Number& lhs, const V3Number& rhs); - V3Number& opShiftR (const V3Number& lhs, const V3Number& rhs); - V3Number& opShiftRS (const V3Number& lhs, const V3Number& rhs, uint32_t lbits); // Arithmetic w/carry - V3Number& opShiftL (const V3Number& lhs, const V3Number& rhs); + V3Number& opXor(const V3Number& lhs, const V3Number& rhs); + V3Number& opXnor(const V3Number& lhs, const V3Number& rhs); + V3Number& opOr(const V3Number& lhs, const V3Number& rhs); + V3Number& opRotR(const V3Number& lhs, const V3Number& rhs); + V3Number& opRotL(const V3Number& lhs, const V3Number& rhs); + V3Number& opShiftR(const V3Number& lhs, const V3Number& rhs); + V3Number& opShiftRS(const V3Number& lhs, const V3Number& rhs, // Arithmetic w/carry + uint32_t lbits); + V3Number& opShiftL(const V3Number& lhs, const V3Number& rhs); // Comparisons - V3Number& opEq (const V3Number& lhs, const V3Number& rhs); - V3Number& opNeq (const V3Number& lhs, const V3Number& rhs); - V3Number& opGt (const V3Number& lhs, const V3Number& rhs); - V3Number& opGtS (const V3Number& lhs, const V3Number& rhs); // Signed - V3Number& opGte (const V3Number& lhs, const V3Number& rhs); - V3Number& opGteS (const V3Number& lhs, const V3Number& rhs); // Signed - V3Number& opLt (const V3Number& lhs, const V3Number& rhs); - V3Number& opLtS (const V3Number& lhs, const V3Number& rhs); // Signed - V3Number& opLte (const V3Number& lhs, const V3Number& rhs); - V3Number& opLteS (const V3Number& lhs, const V3Number& rhs); // Signed + V3Number& opEq(const V3Number& lhs, const V3Number& rhs); + V3Number& opNeq(const V3Number& lhs, const V3Number& rhs); + V3Number& opGt(const V3Number& lhs, const V3Number& rhs); + V3Number& opGtS(const V3Number& lhs, const V3Number& rhs); // Signed + V3Number& opGte(const V3Number& lhs, const V3Number& rhs); + V3Number& opGteS(const V3Number& lhs, const V3Number& rhs); // Signed + V3Number& opLt(const V3Number& lhs, const V3Number& rhs); + V3Number& opLtS(const V3Number& lhs, const V3Number& rhs); // Signed + V3Number& opLte(const V3Number& lhs, const V3Number& rhs); + V3Number& opLteS(const V3Number& lhs, const V3Number& rhs); // Signed // "D" - double (aka real) math - V3Number& opIToRD (const V3Number& lhs); - V3Number& opRToIS (const V3Number& lhs); + V3Number& opIToRD(const V3Number& lhs); + V3Number& opRToIS(const V3Number& lhs); V3Number& opRToIRoundS(const V3Number& lhs); V3Number& opRealToBits(const V3Number& lhs); V3Number& opBitsToRealD(const V3Number& lhs); - V3Number& opNegateD (const V3Number& lhs); - V3Number& opAddD (const V3Number& lhs, const V3Number& rhs); - V3Number& opSubD (const V3Number& lhs, const V3Number& rhs); - V3Number& opMulD (const V3Number& lhs, const V3Number& rhs); - V3Number& opDivD (const V3Number& lhs, const V3Number& rhs); - V3Number& opPowD (const V3Number& lhs, const V3Number& rhs); + V3Number& opNegateD(const V3Number& lhs); + V3Number& opAddD(const V3Number& lhs, const V3Number& rhs); + V3Number& opSubD(const V3Number& lhs, const V3Number& rhs); + V3Number& opMulD(const V3Number& lhs, const V3Number& rhs); + V3Number& opDivD(const V3Number& lhs, const V3Number& rhs); + V3Number& opPowD(const V3Number& lhs, const V3Number& rhs); // Comparisons - V3Number& opEqD (const V3Number& lhs, const V3Number& rhs); - V3Number& opNeqD (const V3Number& lhs, const V3Number& rhs); - V3Number& opGtD (const V3Number& lhs, const V3Number& rhs); - V3Number& opGteD (const V3Number& lhs, const V3Number& rhs); - V3Number& opLtD (const V3Number& lhs, const V3Number& rhs); - V3Number& opLteD (const V3Number& lhs, const V3Number& rhs); + V3Number& opEqD(const V3Number& lhs, const V3Number& rhs); + V3Number& opNeqD(const V3Number& lhs, const V3Number& rhs); + V3Number& opGtD(const V3Number& lhs, const V3Number& rhs); + V3Number& opGteD(const V3Number& lhs, const V3Number& rhs); + V3Number& opLtD(const V3Number& lhs, const V3Number& rhs); + V3Number& opLteD(const V3Number& lhs, const V3Number& rhs); // "N" - string operations - V3Number& opAtoN (const V3Number& lhs, int base); - V3Number& opPutcN (const V3Number& lhs, const V3Number& rhs, const V3Number& ths); - V3Number& opGetcN (const V3Number& lhs, const V3Number& rhs); - V3Number& opSubstrN (const V3Number& lhs, const V3Number& rhs, const V3Number& ths); - V3Number& opCompareNN(const V3Number& lhs,const V3Number& rhs, bool ignoreCase); - V3Number& opConcatN (const V3Number& lhs, const V3Number& rhs); - V3Number& opReplN (const V3Number& lhs, const V3Number& rhs); - V3Number& opReplN (const V3Number& lhs, uint32_t rhsval); - V3Number& opEqN (const V3Number& lhs, const V3Number& rhs); - V3Number& opNeqN (const V3Number& lhs, const V3Number& rhs); - V3Number& opGtN (const V3Number& lhs, const V3Number& rhs); - V3Number& opGteN (const V3Number& lhs, const V3Number& rhs); - V3Number& opLtN (const V3Number& lhs, const V3Number& rhs); - V3Number& opLteN (const V3Number& lhs, const V3Number& rhs); + V3Number& opAtoN(const V3Number& lhs, int base); + V3Number& opPutcN(const V3Number& lhs, const V3Number& rhs, const V3Number& ths); + V3Number& opGetcN(const V3Number& lhs, const V3Number& rhs); + V3Number& opSubstrN(const V3Number& lhs, const V3Number& rhs, const V3Number& ths); + V3Number& opCompareNN(const V3Number& lhs, const V3Number& rhs, bool ignoreCase); + V3Number& opConcatN(const V3Number& lhs, const V3Number& rhs); + V3Number& opReplN(const V3Number& lhs, const V3Number& rhs); + V3Number& opReplN(const V3Number& lhs, uint32_t rhsval); + V3Number& opEqN(const V3Number& lhs, const V3Number& rhs); + V3Number& opNeqN(const V3Number& lhs, const V3Number& rhs); + V3Number& opGtN(const V3Number& lhs, const V3Number& rhs); + V3Number& opGteN(const V3Number& lhs, const V3Number& rhs); + V3Number& opLtN(const V3Number& lhs, const V3Number& rhs); + V3Number& opLteN(const V3Number& lhs, const V3Number& rhs); }; -inline std::ostream& operator<<(std::ostream& os, const V3Number& rhs) { return os<(vertexp)) { - std::cerr<nodep()->fileline()->warnOther() - <<" Example path: " - <nodep()->typeName()<nodep()->fileline()->warnOther() + << " Example path: " << vvertexp->nodep()->typeName() << endl; } if (OrderVarVertex* vvertexp = dynamic_cast(vertexp)) { - std::cerr<varScp()->fileline()->warnOther() - <<" Example path: " - <varScp()->prettyName()<varScp()->fileline()->warnOther() + << " Example path: " << vvertexp->varScp()->prettyName() << endl; } } @@ -130,35 +128,38 @@ void OrderGraph::loopsVertexCb(V3GraphVertex* vertexp) { class OrderMoveDomScope { // Information stored for each unique loop, domain & scope trifecta public: - V3ListEnt m_readyDomScopeE;// List of next ready dom scope - V3List m_readyVertices; // Ready vertices with same domain & scope + V3ListEnt m_readyDomScopeE; // List of next ready dom scope + V3List m_readyVertices; // Ready vertices with same domain & scope private: - bool m_onReadyList; // True if DomScope is already on list of ready dom/scopes - const AstSenTree* m_domainp; // Domain all vertices belong to - const AstScope* m_scopep; // Scope all vertices belong to + bool m_onReadyList; // True if DomScope is already on list of ready dom/scopes + const AstSenTree* m_domainp; // Domain all vertices belong to + const AstScope* m_scopep; // Scope all vertices belong to typedef std::pair DomScopeKey; typedef std::map DomScopeMap; - static DomScopeMap s_dsMap; // Structure registered for each dom/scope pairing + static DomScopeMap s_dsMap; // Structure registered for each dom/scope pairing public: OrderMoveDomScope(const AstSenTree* domainp, const AstScope* scopep) - : m_onReadyList(false), m_domainp(domainp), m_scopep(scopep) {} + : m_onReadyList(false) + , m_domainp(domainp) + , m_scopep(scopep) {} OrderMoveDomScope* readyDomScopeNextp() const { return m_readyDomScopeE.nextp(); } const AstSenTree* domainp() const { return m_domainp; } const AstScope* scopep() const { return m_scopep; } void ready(OrderVisitor* ovp); // Check the domScope is on ready list, add if not - void movedVertex(OrderVisitor* ovp, OrderMoveVertex* vertexp); // Mark one vertex as finished, remove from ready list if done + void movedVertex( + OrderVisitor* ovp, + OrderMoveVertex* vertexp); // Mark one vertex as finished, remove from ready list if done // STATIC MEMBERS (for lookup) static void clear() { - for (DomScopeMap::iterator it=s_dsMap.begin(); it!=s_dsMap.end(); ++it) { + for (DomScopeMap::iterator it = s_dsMap.begin(); it != s_dsMap.end(); ++it) { delete it->second; } s_dsMap.clear(); } V3List& readyVertices() { return m_readyVertices; } - static OrderMoveDomScope* findCreate(const AstSenTree* domainp, - const AstScope* scopep) { + static OrderMoveDomScope* findCreate(const AstSenTree* domainp, const AstScope* scopep) { const DomScopeKey key = make_pair(domainp, scopep); DomScopeMap::iterator iter = s_dsMap.find(key); if (iter != s_dsMap.end()) { @@ -170,16 +171,14 @@ public: } } string name() const { - return (string("MDS:") - +" d="+cvtToHex(domainp()) - +" s="+cvtToHex(scopep())); + return (string("MDS:") + " d=" + cvtToHex(domainp()) + " s=" + cvtToHex(scopep())); } }; -OrderMoveDomScope::DomScopeMap OrderMoveDomScope::s_dsMap; +OrderMoveDomScope::DomScopeMap OrderMoveDomScope::s_dsMap; -inline std::ostream& operator<< (std::ostream& lhs, const OrderMoveDomScope& rhs) { - lhs<v3fatalSrc("Bad case"); } @@ -222,26 +220,24 @@ public: public: // CONSTRUCTORS OrderUser() { - for (int i=0; ivarScp()->varp()->width() - > vsv2p->varScp()->varp()->width(); + bool operator()(OrderVarStdVertex* vsv1p, OrderVarStdVertex* vsv2p) { + return vsv1p->varScp()->varp()->width() > vsv2p->varScp()->varp()->width(); } }; //! Comparator for fanout of vertex struct OrderVarFanoutCmp { - bool operator() (OrderVarStdVertex* vsv1p, OrderVarStdVertex* vsv2p) { + bool operator()(OrderVarStdVertex* vsv1p, OrderVarStdVertex* vsv2p) { return vsv1p->fanout() > vsv2p->fanout(); } }; @@ -261,12 +257,12 @@ struct OrderVarFanoutCmp { // class OrderClkMarkVisitor : public AstNVisitor { private: - bool m_hasClk; // flag indicating whether there is clock signal on rhs - bool m_inClocked; // Currently inside a sequential block - bool m_newClkMarked; // Flag for deciding whether a new run is needed - bool m_inAss; // Currently inside of a assignment - int m_childClkWidth; // If in hasClk, width of clock signal in child - int m_rightClkWidth; // Clk width on the RHS + bool m_hasClk; // flag indicating whether there is clock signal on rhs + bool m_inClocked; // Currently inside a sequential block + bool m_newClkMarked; // Flag for deciding whether a new run is needed + bool m_inAss; // Currently inside of a assignment + int m_childClkWidth; // If in hasClk, width of clock signal in child + int m_rightClkWidth; // Clk width on the RHS // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -278,11 +274,12 @@ private: m_rightClkWidth = varrefp->width(); if (varrefp->varp()->attrClocker() == VVarAttrClocker::CLOCKER_YES) { if (m_inClocked) { - varrefp->v3warn(CLKDATA, "Clock used as data (on rhs of assignment) in sequential block " - <prettyNameQ()<v3warn( + CLKDATA, "Clock used as data (on rhs of assignment) in sequential block " + << varrefp->prettyNameQ() << endl); } else { m_hasClk = true; - UINFO(5, "node is already marked as clocker "<lhsp()->width() > m_rightClkWidth) { - nodep->v3warn(CLKDATA, "Clock is assigned to part of data signal " - <lhsp()<lhsp()->width() <v3warn(CLKDATA, "Clock is assigned to part of data signal " << nodep->lhsp() + << endl); + UINFO(4, "CLKDATA: lhs with width " << nodep->lhsp()->width() << endl); + UINFO(4, " but rhs clock with width " << m_rightClkWidth << endl); return; // skip the marking } @@ -307,7 +304,7 @@ private: if (lhsp && (lhsp->varp()->attrClocker() == VVarAttrClocker::CLOCKER_UNKNOWN)) { lhsp->varp()->attrClocker(VVarAttrClocker::CLOCKER_YES); // mark as clocker m_newClkMarked = true; // enable a further run since new clocker is marked - UINFO(5, "node is newly marked as clocker by assignment "<v3warn(CLKDATA, "Clock used as data (on rhs of assignment) in sequential block " - <prettyNameQ()); + << nodep->prettyNameQ()); } else { m_hasClk = true; m_childClkWidth = nodep->width(); // Pass up - UINFO(5, "node is already marked as clocker "<lhsp(), VarRef)) { if (varrefp->varp()->attrClocker() == VVarAttrClocker::CLOCKER_YES) { m_clkAss = true; - UINFO(6, "node was marked as clocker "<rhsp()); @@ -419,8 +416,7 @@ public: //###################################################################### // ProcessMoveBuildGraph -template -class ProcessMoveBuildGraph { +template class ProcessMoveBuildGraph { // ProcessMoveBuildGraph takes as input the fine-grained graph of // OrderLogicVertex, OrderVarVertex, etc; this is 'm_graph' in // OrderVisitor. It produces a slightly coarsened graph to drive the @@ -449,29 +445,29 @@ public: // Clients of ProcessMoveBuildGraph must supply MoveVertexMaker // which creates new T_MoveVertex's. Each new vertex wraps lvertexp // (which may be NULL.) - virtual T_MoveVertex* makeVertexp(OrderLogicVertex* lvertexp, - const OrderEitherVertex* varVertexp, - const AstScope* scopep, - const AstSenTree* domainp) = 0; + virtual T_MoveVertex* makeVertexp( // + OrderLogicVertex* lvertexp, const OrderEitherVertex* varVertexp, + const AstScope* scopep, const AstSenTree* domainp) + = 0; virtual void freeVertexp(T_MoveVertex* freeMep) = 0; }; private: // MEMBERS - const V3Graph* m_graphp; // Input graph of OrderLogicVertex's etc - V3Graph* m_outGraphp; // Output graph of T_MoveVertex's - MoveVertexMaker* m_vxMakerp; // Factory class for T_MoveVertex's - Logic2Move m_logic2move; // Map Logic to Vertex - Var2Move m_var2move; // Map Vars to Vertex + const V3Graph* m_graphp; // Input graph of OrderLogicVertex's etc + V3Graph* m_outGraphp; // Output graph of T_MoveVertex's + MoveVertexMaker* m_vxMakerp; // Factory class for T_MoveVertex's + Logic2Move m_logic2move; // Map Logic to Vertex + Var2Move m_var2move; // Map Vars to Vertex public: // CONSTRUCTORS ProcessMoveBuildGraph(const V3Graph* logicGraphp, // Input graph of OrderLogicVertex etc. V3Graph* outGraphp, // Output graph of T_MoveVertex's MoveVertexMaker* vxMakerp) - : m_graphp(logicGraphp), - m_outGraphp(outGraphp), - m_vxMakerp(vxMakerp) {} + : m_graphp(logicGraphp) + , m_outGraphp(outGraphp) + , m_vxMakerp(vxMakerp) {} virtual ~ProcessMoveBuildGraph() {} // METHODS @@ -489,12 +485,10 @@ public: // done the forward search, so stop. // For each logic node, make a T_MoveVertex - for (V3GraphVertex* itp = m_graphp->verticesBeginp(); itp; - itp=itp->verticesNextp()) { + for (V3GraphVertex* itp = m_graphp->verticesBeginp(); itp; itp = itp->verticesNextp()) { if (OrderLogicVertex* lvertexp = dynamic_cast(itp)) { - T_MoveVertex* moveVxp = - m_vxMakerp->makeVertexp(lvertexp, NULL, lvertexp->scopep(), - lvertexp->domainp()); + T_MoveVertex* moveVxp = m_vxMakerp->makeVertexp(lvertexp, NULL, lvertexp->scopep(), + lvertexp->domainp()); if (moveVxp) { // Cross link so we can find it later m_logic2move[lvertexp] = moveVxp; @@ -502,31 +496,27 @@ public: } } // Build edges between logic vertices - for (V3GraphVertex* itp = m_graphp->verticesBeginp(); itp; - itp=itp->verticesNextp()) { + for (V3GraphVertex* itp = m_graphp->verticesBeginp(); itp; itp = itp->verticesNextp()) { if (OrderLogicVertex* lvertexp = dynamic_cast(itp)) { T_MoveVertex* moveVxp = m_logic2move[lvertexp]; - if (moveVxp) { - iterate(moveVxp, lvertexp, lvertexp->domainp()); - } + if (moveVxp) { iterate(moveVxp, lvertexp, lvertexp->domainp()); } } } } private: // Return true if moveVxp has downstream dependencies - bool iterate(T_MoveVertex* moveVxp, const V3GraphVertex* origVxp, - const AstSenTree* domainp) { + bool iterate(T_MoveVertex* moveVxp, const V3GraphVertex* origVxp, const AstSenTree* domainp) { bool madeDeps = false; // Search forward from given original vertex, making new edges from // moveVxp forward - for (V3GraphEdge* edgep = origVxp->outBeginp(); edgep; edgep=edgep->outNextp()) { - if (edgep->weight()==0) { // Was cut + for (V3GraphEdge* edgep = origVxp->outBeginp(); edgep; edgep = edgep->outNextp()) { + if (edgep->weight() == 0) { // Was cut continue; } int weight = edgep->weight(); - if (const OrderLogicVertex* toLVertexp = - dynamic_cast(edgep->top())) { + if (const OrderLogicVertex* toLVertexp + = dynamic_cast(edgep->top())) { // Do not construct dependencies across exclusive domains. if (domainsExclusive(domainp, toLVertexp->domainp())) continue; @@ -534,8 +524,7 @@ private: // Path from vertexp to a logic vertex; new edge. // Note we use the last edge's weight, not some function of // multiple edges - new OrderEdge(m_outGraphp, moveVxp, - m_logic2move[toLVertexp], weight); + new OrderEdge(m_outGraphp, moveVxp, m_logic2move[toLVertexp], weight); madeDeps = true; } else { // This is an OrderVarVertex or other vertex representing @@ -543,10 +532,10 @@ private: const V3GraphVertex* nonLogicVxp = edgep->top(); VxDomPair key(nonLogicVxp, domainp); if (!m_var2move[key]) { - const OrderEitherVertex* eithp = - dynamic_cast(nonLogicVxp); - T_MoveVertex* newMoveVxp = - m_vxMakerp->makeVertexp(NULL, eithp, eithp->scopep(), domainp); + const OrderEitherVertex* eithp + = dynamic_cast(nonLogicVxp); + T_MoveVertex* newMoveVxp + = m_vxMakerp->makeVertexp(NULL, eithp, eithp->scopep(), domainp); m_var2move[key] = newMoveVxp; // Find downstream logics that depend on (var, domain) @@ -573,24 +562,20 @@ private: //###################################################################### // OrderMoveVertexMaker and related -class OrderMoveVertexMaker - : public ProcessMoveBuildGraph::MoveVertexMaker { +class OrderMoveVertexMaker : public ProcessMoveBuildGraph::MoveVertexMaker { // MEMBERS V3Graph* m_pomGraphp; V3List* m_pomWaitingp; + public: // CONSTRUCTORS - OrderMoveVertexMaker(V3Graph* pomGraphp, - V3List* pomWaitingp) - : m_pomGraphp(pomGraphp), - m_pomWaitingp(pomWaitingp) {} + OrderMoveVertexMaker(V3Graph* pomGraphp, V3List* pomWaitingp) + : m_pomGraphp(pomGraphp) + , m_pomWaitingp(pomWaitingp) {} // METHODS - OrderMoveVertex* makeVertexp(OrderLogicVertex* lvertexp, - const OrderEitherVertex*, - const AstScope* scopep, - const AstSenTree* domainp) { - OrderMoveVertex* resultp = - new OrderMoveVertex(m_pomGraphp, lvertexp); + OrderMoveVertex* makeVertexp(OrderLogicVertex* lvertexp, const OrderEitherVertex*, + const AstScope* scopep, const AstSenTree* domainp) { + OrderMoveVertex* resultp = new OrderMoveVertex(m_pomGraphp, lvertexp); resultp->domScopep(OrderMoveDomScope::findCreate(domainp, scopep)); resultp->m_pomWaitingE.pushBack(*m_pomWaitingp, resultp); return resultp; @@ -599,39 +584,35 @@ public: freeMep->m_pomWaitingE.unlink(*m_pomWaitingp, freeMep); freeMep->unlinkDelete(m_pomGraphp); } + private: VL_UNCOPYABLE(OrderMoveVertexMaker); }; -class OrderMTaskMoveVertexMaker - : public ProcessMoveBuildGraph::MoveVertexMaker { +class OrderMTaskMoveVertexMaker : public ProcessMoveBuildGraph::MoveVertexMaker { V3Graph* m_pomGraphp; + public: explicit OrderMTaskMoveVertexMaker(V3Graph* pomGraphp) : m_pomGraphp(pomGraphp) {} - MTaskMoveVertex* makeVertexp(OrderLogicVertex* lvertexp, - const OrderEitherVertex* varVertexp, - const AstScope* scopep, - const AstSenTree* domainp) { + MTaskMoveVertex* makeVertexp(OrderLogicVertex* lvertexp, const OrderEitherVertex* varVertexp, + const AstScope* scopep, const AstSenTree* domainp) { // Exclude initial/settle logic from the mtasks graph. // We'll output time-zero logic separately. - if (domainp->hasInitial() || domainp->hasSettle()) { - return NULL; - } + if (domainp->hasInitial() || domainp->hasSettle()) return NULL; return new MTaskMoveVertex(m_pomGraphp, lvertexp, varVertexp, scopep, domainp); } - void freeVertexp(MTaskMoveVertex* freeMep) { - freeMep->unlinkDelete(m_pomGraphp); - } + void freeVertexp(MTaskMoveVertex* freeMep) { freeMep->unlinkDelete(m_pomGraphp); } + private: VL_UNCOPYABLE(OrderMTaskMoveVertexMaker); }; class OrderVerticesByDomainThenScope { PartPtrIdMap m_ids; + public: - virtual bool operator()(const V3GraphVertex* lhsp, - const V3GraphVertex* rhsp) const { + virtual bool operator()(const V3GraphVertex* lhsp, const V3GraphVertex* rhsp) const { const MTaskMoveVertex* l_vxp = dynamic_cast(lhsp); const MTaskMoveVertex* r_vxp = dynamic_cast(rhsp); vluint64_t l_id = m_ids.findId(l_vxp->domainp()); @@ -651,12 +632,9 @@ public: // Sort vertex's, which must be AbstractMTask's, into a deterministic // order by comparing their serial IDs. - virtual bool operator()(const V3GraphVertex* lhsp, - const V3GraphVertex* rhsp) const { - const AbstractMTask* lmtaskp = - dynamic_cast(lhsp); - const AbstractMTask* rmtaskp = - dynamic_cast(rhsp); + virtual bool operator()(const V3GraphVertex* lhsp, const V3GraphVertex* rhsp) const { + const AbstractMTask* lmtaskp = dynamic_cast(lhsp); + const AbstractMTask* rmtaskp = dynamic_cast(rhsp); return lmtaskp->id() < rmtaskp->id(); } }; @@ -678,61 +656,61 @@ private: // AstNodeModule::user3() -> Number of routines created // Each call to V3Const::constify // AstNode::user4() Used by V3Const::constify, called below - AstUser1InUse m_inuser1; - AstUser2InUse m_inuser2; - AstUser3InUse m_inuser3; - //AstUser4InUse m_inuser4; // Used only when building tree, so below + AstUser1InUse m_inuser1; + AstUser2InUse m_inuser2; + AstUser3InUse m_inuser3; + // AstUser4InUse m_inuser4; // Used only when building tree, so below // STATE - OrderGraph m_graph; // Scoreboard of var usages/dependencies - SenTreeFinder m_finder; // Find global sentree's and add them - AstSenTree* m_comboDomainp; // Combo activation tree - AstSenTree* m_deleteDomainp;// Delete this from tree - AstSenTree* m_settleDomainp;// Initial activation tree - OrderInputsVertex* m_inputsVxp; // Top level vertex all inputs point from - OrderSettleVertex* m_settleVxp; // Top level vertex all settlement vertexes point from - OrderLogicVertex* m_logicVxp; // Current statement being tracked, NULL=ignored - AstTopScope* m_topScopep; // Current top scope being processed - AstScope* m_scopetopp; // Scope under TOPSCOPE - AstNodeModule* m_modp; // Current module - AstScope* m_scopep; // Current scope being processed - AstActive* m_activep; // Current activation block - bool m_inSenTree; // Underneath AstSenItem; any varrefs are clocks - bool m_inClocked; // Underneath clocked block - bool m_inClkAss; // Underneath AstAssign - bool m_inPre; // Underneath AstAssignPre - bool m_inPost; // Underneath AstAssignPost - OrderLogicVertex* m_activeSenVxp; // Sensitivity vertex - std::deque m_orderUserps; // All created OrderUser's for later deletion. + OrderGraph m_graph; // Scoreboard of var usages/dependencies + SenTreeFinder m_finder; // Find global sentree's and add them + AstSenTree* m_comboDomainp; // Combo activation tree + AstSenTree* m_deleteDomainp; // Delete this from tree + AstSenTree* m_settleDomainp; // Initial activation tree + OrderInputsVertex* m_inputsVxp; // Top level vertex all inputs point from + OrderSettleVertex* m_settleVxp; // Top level vertex all settlement vertexes point from + OrderLogicVertex* m_logicVxp; // Current statement being tracked, NULL=ignored + AstTopScope* m_topScopep; // Current top scope being processed + AstScope* m_scopetopp; // Scope under TOPSCOPE + AstNodeModule* m_modp; // Current module + AstScope* m_scopep; // Current scope being processed + AstActive* m_activep; // Current activation block + bool m_inSenTree; // Underneath AstSenItem; any varrefs are clocks + bool m_inClocked; // Underneath clocked block + bool m_inClkAss; // Underneath AstAssign + bool m_inPre; // Underneath AstAssignPre + bool m_inPost; // Underneath AstAssignPost + OrderLogicVertex* m_activeSenVxp; // Sensitivity vertex + std::deque m_orderUserps; // All created OrderUser's for later deletion. // STATE... for inside process - AstCFunc* m_pomNewFuncp; // Current function being created - int m_pomNewStmts; // Statements in function being created - V3Graph m_pomGraph; // Graph of logic elements to move - V3List m_pomWaiting; // List of nodes needing inputs to become ready + AstCFunc* m_pomNewFuncp; // Current function being created + int m_pomNewStmts; // Statements in function being created + V3Graph m_pomGraph; // Graph of logic elements to move + V3List m_pomWaiting; // List of nodes needing inputs to become ready protected: friend class OrderMoveDomScope; - V3List m_pomReadyDomScope; // List of ready domain/scope pairs, by loopId - std::vector m_unoptflatVars; // Vector of variables in UNOPTFLAT loop + V3List m_pomReadyDomScope; // List of ready domain/scope pairs, by loopId + std::vector m_unoptflatVars; // Vector of variables in UNOPTFLAT loop private: // STATS VDouble0 m_statCut[OrderVEdgeType::_ENUM_END]; // Count of each edge type cut // TYPES - enum VarUsage { VU_NONE=0, VU_CON=1, VU_GEN=2 }; + enum VarUsage { VU_NONE = 0, VU_CON = 1, VU_GEN = 2 }; // METHODS VL_DEBUG_FUNC; // Declare debug() void iterateNewStmt(AstNode* nodep) { if (m_scopep) { - UINFO(4," STMT "<sensesp(), nodep, "NULL"); // If inside combo logic, ignore the domain, we'll assign one based on interconnect AstSenTree* startDomainp = m_activep->sensesp(); - if (startDomainp->hasCombo()) startDomainp=NULL; + if (startDomainp->hasCombo()) startDomainp = NULL; m_logicVxp = new OrderLogicVertex(&m_graph, m_scopep, startDomainp, nodep); if (m_activeSenVxp) { // If in a clocked activation, add a link from the sensitivity to this block @@ -745,7 +723,8 @@ private: } } - OrderVarVertex* newVarUserVertex(AstVarScope* varscp, WhichVertex type, bool* createdp=NULL) { + OrderVarVertex* newVarUserVertex(AstVarScope* varscp, WhichVertex type, + bool* createdp = NULL) { if (!varscp->user1p()) { OrderUser* newup = new OrderUser(); m_orderUserps.push_back(newup); @@ -775,8 +754,8 @@ private: void processMoveReadyOne(OrderMoveVertex* vertexp); void processMoveDoneOne(OrderMoveVertex* vertexp); void processMoveOne(OrderMoveVertex* vertexp, OrderMoveDomScope* domScopep, int level); - AstActive* processMoveOneLogic(const OrderLogicVertex* lvertexp, - AstCFunc*& newFuncpr, int& newStmtsr); + AstActive* processMoveOneLogic(const OrderLogicVertex* lvertexp, AstCFunc*& newFuncpr, + int& newStmtsr); // processMTask* routines schedule threaded execution struct MTaskState { @@ -784,23 +763,28 @@ private: AstMTaskBody* m_mtaskBodyp; Logics m_logics; ExecMTask* m_execMTaskp; - MTaskState() : m_mtaskBodyp(NULL), m_execMTaskp(NULL) {} + MTaskState() + : m_mtaskBodyp(NULL) + , m_execMTaskp(NULL) {} }; void processMTasks(); - typedef enum {LOGIC_INITIAL, LOGIC_SETTLE} InitialLogicE; + typedef enum { LOGIC_INITIAL, LOGIC_SETTLE } InitialLogicE; void processMTasksInitial(InitialLogicE logic_type); - string cfuncName(AstNodeModule* modp, AstSenTree* domainp, - AstScope* scopep, AstNode* forWhatp) { + string cfuncName(AstNodeModule* modp, AstSenTree* domainp, AstScope* scopep, + AstNode* forWhatp) { modp->user3Inc(); int funcnum = modp->user3(); - string name = (domainp->hasCombo() ? "_combo" - : (domainp->hasInitial() ? "_initial" - : (domainp->hasSettle() ? "_settle" - : (domainp->isMulti() ? "_multiclk" : "_sequent")))); - name = name+"__"+scopep->nameDotless()+"__"+cvtToStr(funcnum); + string name = (domainp->hasCombo() + ? "_combo" + : (domainp->hasInitial() + ? "_initial" + : (domainp->hasSettle() + ? "_settle" + : (domainp->isMulti() ? "_multiclk" : "_sequent")))); + name = name + "__" + scopep->nameDotless() + "__" + cvtToStr(funcnum); if (v3Global.opt.profCFuncs()) { - name += "__PROF__"+forWhatp->fileline()->profileFuncname(); + name += "__PROF__" + forWhatp->fileline()->profileFuncname(); } return name; } @@ -819,46 +803,54 @@ private: // IEEE does not specify ordering between initial blocks, so we // can do whatever we want. We especially do not want to // evaluate multiple times, so do not mark the edge circular - } - else { + } else { nodep->circular(true); ++m_statCut[vertexp->type()]; if (edgep) ++m_statCut[edgep->type()]; // if (vertexp->isClock()) { // Seems obvious; no warning yet - //nodep->v3warn(GENCLK, "Signal unoptimizable: Generated clock: "<prettyNameQ()); + // nodep->v3warn(GENCLK, "Signal unoptimizable: Generated clock: + // "<prettyNameQ()); } else if (nodep->varp()->isSigPublic()) { - nodep->v3warn(UNOPT, "Signal unoptimizable: Feedback to public clock or circular logic: " - <prettyNameQ()); + nodep->v3warn(UNOPT, + "Signal unoptimizable: Feedback to public clock or circular logic: " + << nodep->prettyNameQ()); if (!nodep->fileline()->warnIsOff(V3ErrorCode::UNOPT)) { - nodep->fileline()->modifyWarnOff(V3ErrorCode::UNOPT, true); // Complain just once + nodep->fileline()->modifyWarnOff(V3ErrorCode::UNOPT, + true); // Complain just once // Give the user an example. - bool tempWeight = (edgep && edgep->weight()==0); - if (tempWeight) edgep->weight(1); // Else the below loop detect can't see the loop - m_graph.reportLoops(&OrderEdge::followComboConnected, vertexp); // calls OrderGraph::loopsVertexCb + bool tempWeight = (edgep && edgep->weight() == 0); + // Else the below loop detect can't see the loop + if (tempWeight) edgep->weight(1); + // Calls OrderGraph::loopsVertexCb + m_graph.reportLoops(&OrderEdge::followComboConnected, vertexp); if (tempWeight) edgep->weight(0); } } else { // We don't use UNOPT, as there are lots of V2 places where // it was needed, that aren't any more // First v3warn not inside warnIsOff so we can see the suppressions with --debug - nodep->v3warn(UNOPTFLAT, "Signal unoptimizable: Feedback to clock or circular logic: " - <prettyNameQ()); + nodep->v3warn(UNOPTFLAT, + "Signal unoptimizable: Feedback to clock or circular logic: " + << nodep->prettyNameQ()); if (!nodep->fileline()->warnIsOff(V3ErrorCode::UNOPTFLAT)) { - nodep->fileline()->modifyWarnOff(V3ErrorCode::UNOPTFLAT, true); // Complain just once + nodep->fileline()->modifyWarnOff(V3ErrorCode::UNOPTFLAT, + true); // Complain just once // Give the user an example. - bool tempWeight = (edgep && edgep->weight()==0); - if (tempWeight) edgep->weight(1); // Else the below loop detect can't see the loop - m_graph.reportLoops(&OrderEdge::followComboConnected, vertexp); // calls OrderGraph::loopsVertexCb + bool tempWeight = (edgep && edgep->weight() == 0); + // Else the below loop detect can't see the loop + if (tempWeight) edgep->weight(1); + // Calls OrderGraph::loopsVertexCb + m_graph.reportLoops(&OrderEdge::followComboConnected, vertexp); if (tempWeight) edgep->weight(0); if (v3Global.opt.reportUnoptflat()) { // Report candidate variables for splitting reportLoopVars(vertexp); // Do a subgraph for the UNOPTFLAT loop OrderGraph loopGraph; - m_graph.subtreeLoops(&OrderEdge::followComboConnected, - vertexp, &loopGraph); + m_graph.subtreeLoops(&OrderEdge::followComboConnected, vertexp, + &loopGraph); loopGraph.dumpDotFilePrefixedAlways("unoptflat"); } } @@ -898,16 +890,14 @@ private: << varp->prettyName() << std::dec << ", width " << varp->width() << ", fanout " << vsvertexp->fanout(); if (canSplit) { - std::cerr <<", can split_var"; + std::cerr << ", can split_var"; canSplitList.insert(varp); } std::cerr << std::endl; } // Up to 10 of the most fanned out - std::cerr << V3Error::warnMore() - << "... Most fanned out candidate vars to split:" << endl; - std::stable_sort(m_unoptflatVars.begin(), m_unoptflatVars.end(), - OrderVarFanoutCmp()); + std::cerr << V3Error::warnMore() << "... Most fanned out candidate vars to split:" << endl; + std::stable_sort(m_unoptflatVars.begin(), m_unoptflatVars.end(), OrderVarFanoutCmp()); lim = m_unoptflatVars.size() < 10 ? m_unoptflatVars.size() : 10; for (int i = 0; i < lim; i++) { OrderVarStdVertex* vsvertexp = m_unoptflatVars[i]; @@ -920,7 +910,7 @@ private: std::cerr << ", can split_var"; canSplitList.insert(varp); } - std::cerr<varScp()->varp(); if (!varp->user3()) { string name = varp->prettyName(); - if ((varp->width() != 1) - && (name.find("__Vdly") == string::npos) + if ((varp->width() != 1) && (name.find("__Vdly") == string::npos) && (name.find("__Vcell") == string::npos)) { // Variable to report on and not yet done m_unoptflatVars.push_back(vsvertexp); @@ -949,33 +938,30 @@ private: } } // Iterate through all the to and from vertices of the same color - for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; - edgep = edgep->outNextp()) { - if (edgep->top()->color() == color) { - reportLoopVarsIterate(edgep->top(), color); - } + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { + if (edgep->top()->color() == color) reportLoopVarsIterate(edgep->top(), color); } - for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; - edgep = edgep->inNextp()) { - if (edgep->fromp()->color() == color) { - reportLoopVarsIterate(edgep->fromp(), color); - } + for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { + if (edgep->fromp()->color() == color) reportLoopVarsIterate(edgep->fromp(), color); } } // VISITORS virtual void visit(AstNetlist* nodep) VL_OVERRIDE { { - AstUser4InUse m_inuser4; // Used only when building tree, so below + AstUser4InUse m_inuser4; // Used only when building tree, so below iterateChildren(nodep); } // We're finished, complete the topscopes - if (m_topScopep) { process(); m_topScopep=NULL; } + if (m_topScopep) { + process(); + m_topScopep = NULL; + } } virtual void visit(AstTopScope* nodep) VL_OVERRIDE { // Process the last thing we're finishing UASSERT_OBJ(!m_topScopep, nodep, "Only one topscope should ever be created"); - UINFO(2," Loading tree...\n"); - //VV***** We reset userp() + UINFO(2, " Loading tree...\n"); + // VV***** We reset userp() AstNode::user1ClearTree(); AstNode::user3ClearTree(); m_graph.clear(); @@ -986,20 +972,21 @@ private: m_finder.main(m_topScopep); // ProcessDomainsIterate will use these when it needs to move // something to a combodomain. This saves a ton of find() operations. - AstSenTree* combp = new AstSenTree(nodep->fileline(), // Gets cloned() so ok if goes out of scope - new AstSenItem(nodep->fileline(), AstSenItem::Combo())); + AstSenTree* combp + = new AstSenTree(nodep->fileline(), // Gets cloned() so ok if goes out of scope + new AstSenItem(nodep->fileline(), AstSenItem::Combo())); m_comboDomainp = m_finder.getSenTree(nodep->fileline(), combp); pushDeletep(combp); // Cleanup when done - AstSenTree* settlep = new AstSenTree(nodep->fileline(), // Gets cloned() so ok if goes out of scope - new AstSenItem(nodep->fileline(), - AstSenItem::Settle())); + AstSenTree* settlep + = new AstSenTree(nodep->fileline(), // Gets cloned() so ok if goes out of scope + new AstSenItem(nodep->fileline(), AstSenItem::Settle())); m_settleDomainp = m_finder.getSenTree(nodep->fileline(), settlep); pushDeletep(settlep); // Cleanup when done // Fake AstSenTree we set domainp to indicate needs deletion m_deleteDomainp = new AstSenTree(nodep->fileline(), new AstSenItem(nodep->fileline(), AstSenItem::Settle())); pushDeletep(m_deleteDomainp); // Cleanup when done - UINFO(5," DeleteDomain = "<hasClocked(); @@ -1089,19 +1076,17 @@ private: // clock_enable attribute: user's worrying about it for us con = false; } - if (m_inClkAss && (varscp->varp()->attrClocker() - != VVarAttrClocker::CLOCKER_YES)) { + if (m_inClkAss + && (varscp->varp()->attrClocker() != VVarAttrClocker::CLOCKER_YES)) { con = false; - UINFO(4, "nodep used as clock_enable "<nodep()<nodep() << endl); } } if (gen) varscp->user4(varscp->user4() | VU_GEN); if (con) varscp->user4(varscp->user4() | VU_CON); // Add edges - if (!m_inClocked - || m_inPost - ) { + if (!m_inClocked || m_inPost) { // Combo logic { // not settle and (combo or inPost) if (gen) { @@ -1113,8 +1098,8 @@ private: // internal clocks circular, which must only // happen if they are generated by delayed // assignment. - UINFO(5, " Found delayed assignment (post) " - << varVxp << endl); + UINFO(5, + " Found delayed assignment (post) " << varVxp << endl); varVxp->isDelayed(true); } else { // If the lhs is a clocker, avoid marking that as circular by @@ -1197,20 +1182,14 @@ private: m_inSenTree = false; } } - virtual void visit(AstAlways* nodep) VL_OVERRIDE { - iterateNewStmt(nodep); - } virtual void visit(AstAlwaysPost* nodep) VL_OVERRIDE { m_inPost = true; iterateNewStmt(nodep); m_inPost = false; } - virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE { - iterateNewStmt(nodep); - } - virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { - iterateNewStmt(nodep); - } + virtual void visit(AstAlways* nodep) VL_OVERRIDE { iterateNewStmt(nodep); } + virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE { iterateNewStmt(nodep); } + virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { iterateNewStmt(nodep); } virtual void visit(AstAssignW* nodep) VL_OVERRIDE { OrderClkAssVisitor visitor(nodep); m_inClkAss = visitor.isClkAss(); @@ -1233,9 +1212,7 @@ private: m_inPost = false; m_inClkAss = false; } - virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE { - iterateNewStmt(nodep); - } + virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE { iterateNewStmt(nodep); } virtual void visit(AstInitial* nodep) VL_OVERRIDE { // We use initials to setup parameters and static consts's which may be referenced // in user initial blocks. So use ordering to sort them all out. @@ -1275,22 +1252,20 @@ public: } virtual ~OrderVisitor() { // Stats - for (int type=0; type::iterator it=m_orderUserps.begin(); + for (std::deque::iterator it = m_orderUserps.begin(); it != m_orderUserps.end(); ++it) { delete *it; } m_graph.debug(V3Error::debugDefault()); } - void main(AstNode* nodep) { - iterate(nodep); - } + void main(AstNode* nodep) { iterate(nodep); } }; //###################################################################### @@ -1313,9 +1288,7 @@ static bool domainsExclusive(const AstSenTree* fromp, const AstSenTree* top) { bool toInitial = top->hasInitial() || top->hasSettle(); bool fromInitial = fromp->hasInitial() || fromp->hasSettle(); - if (toInitial != fromInitial) { - return true; - } + if (toInitial != fromInitial) return true; const AstSenItem* fromSenListp = VN_CAST(fromp->sensesp(), SenItem); const AstSenItem* toSenListp = VN_CAST(top->sensesp(), SenItem); @@ -1363,13 +1336,15 @@ inline void OrderMoveDomScope::movedVertex(OrderVisitor* ovp, OrderMoveVertex* v // OrderVisitor - Clock propagation void OrderVisitor::processInputs() { - m_graph.userClearVertices(); // Vertex::user() // 1 if input recursed, 2 if marked as input, 3 if out-edges recursed + m_graph.userClearVertices(); // Vertex::user() // 1 if input recursed, 2 if marked as input, + // 3 if out-edges recursed // Start at input vertex, process from input-to-output order VertexVec todoVec; // List of newly-input marked vectors we need to process todoVec.push_front(m_inputsVxp); m_inputsVxp->isFromInput(true); // By definition while (!todoVec.empty()) { - OrderEitherVertex* vertexp = todoVec.back(); todoVec.pop_back(); + OrderEitherVertex* vertexp = todoVec.back(); + todoVec.pop_back(); processInputsOutIterate(vertexp, todoVec); } } @@ -1377,8 +1352,8 @@ void OrderVisitor::processInputs() { void OrderVisitor::processInputsInIterate(OrderEitherVertex* vertexp, VertexVec& todoVec) { // Propagate PrimaryIn through simple assignments if (vertexp->user()) return; // Already processed - if (0 && debug()>=9) { - UINFO(9," InIIter "<= 9) { + UINFO(9, " InIIter " << vertexp << endl); if (OrderLogicVertex* vvertexp = dynamic_cast(vertexp)) { vvertexp->nodep()->dumpTree(cout, "- TT: "); } @@ -1387,22 +1362,23 @@ void OrderVisitor::processInputsInIterate(OrderEitherVertex* vertexp, VertexVec& // First handle all inputs to this vertex, in most cases they'll be already processed earlier // Also, determine if this vertex is an input int inonly = 1; // 0=no, 1=maybe, 2=yes until a no - for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep=edgep->inNextp()) { + for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { OrderEitherVertex* frVertexp = static_cast(edgep->fromp()); processInputsInIterate(frVertexp, todoVec); if (frVertexp->isFromInput()) { - if (inonly==1) inonly = 2; + if (inonly == 1) inonly = 2; } else if (dynamic_cast(frVertexp)) { // Ignore post assignments, just for ordering } else { - //UINFO(9," InItStopDueTo "<user()<2) { // Set it. Note may have already been set earlier, too - UINFO(9," Input reassignment: "<user() < 2) { // Set it. Note may have already been set earlier, too + UINFO(9, " Input reassignment: " << vertexp << endl); vertexp->isFromInput(true); vertexp->user(2); // 2 means on list // Can't work on out-edges of a node we know is an input immediately, @@ -1410,12 +1386,12 @@ void OrderVisitor::processInputsInIterate(OrderEitherVertex* vertexp, VertexVec& // So push to list and work on it later when all in-edges known resolved todoVec.push_back(vertexp); } - //UINFO(9," InIdone "<user()==3) return; // Already out processed - //UINFO(9," InOIter "<user() == 3) return; // Already out processed + // UINFO(9, " InOIter " << vertexp << endl); // First make sure input path is fully recursed processInputsInIterate(vertexp, todoVec); // Propagate PrimaryIn through simple assignments @@ -1425,7 +1401,7 @@ void OrderVisitor::processInputsOutIterate(OrderEitherVertex* vertexp, VertexVec { // Propagate PrimaryIn through simple assignments, following target of vertex - for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { OrderEitherVertex* toVertexp = static_cast(edgep->top()); if (OrderVarStdVertex* vvertexp = dynamic_cast(toVertexp)) { processInputsInIterate(vvertexp, todoVec); @@ -1445,7 +1421,7 @@ void OrderVisitor::processInputsOutIterate(OrderEitherVertex* vertexp, VertexVec void OrderVisitor::processCircular() { // Take broken edges and add circular flags // The change detect code will use this to force changedets - for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) { + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { if (OrderVarStdVertex* vvertexp = dynamic_cast(itp)) { if (vvertexp->isClock() && !vvertexp->isFromInput()) { // If a clock is generated internally, we need to do another @@ -1457,31 +1433,29 @@ void OrderVisitor::processCircular() { // it is combinatorial, we do not (and indeed it will break // other tests such as t_gated_clk_1. if (!v3Global.opt.orderClockDly()) { - UINFO(5,"Circular Clock, no-order-clock-delay "<isDelayed()) { - UINFO(5,"Circular Clock, delayed "<isDelayed()) { + UINFO(5, "Circular Clock, delayed " << vvertexp << endl); nodeMarkCircular(vvertexp, NULL); - } - else { - UINFO(5,"Circular Clock, not delayed "<outBeginp(); edgep; edgep=edgep->outNextp()) { - if (edgep->weight()==0) { // was cut + for (V3GraphEdge* edgep = vvertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { + if (edgep->weight() == 0) { // was cut OrderEdge* oedgep = dynamic_cast(edgep); UASSERT_OBJ(oedgep, vvertexp->varScp(), "Cutable edge not of proper type"); - UINFO(6," CutCircularO: "<name()<name() << endl); nodeMarkCircular(vvertexp, oedgep); } } for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { - if (edgep->weight()==0) { // was cut + if (edgep->weight() == 0) { // was cut OrderEdge* oedgep = dynamic_cast(edgep); UASSERT_OBJ(oedgep, vvertexp->varScp(), "Cutable edge not of proper type"); - UINFO(6," CutCircularI: "<name()<name() << endl); nodeMarkCircular(vvertexp, oedgep); } } @@ -1492,15 +1466,16 @@ void OrderVisitor::processCircular() { void OrderVisitor::processSensitive() { // Sc sensitives are required on all inputs that go to a combo // block. (Not inputs that go only to clocked blocks.) - for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) { + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { if (OrderVarStdVertex* vvertexp = dynamic_cast(itp)) { if (vvertexp->varScp()->varp()->isNonOutput()) { - //UINFO(0," scsen "<outBeginp(); edgep; edgep=edgep->outNextp()) { + // UINFO(0, " scsen " << vvertexp << endl); + for (V3GraphEdge* edgep = vvertexp->outBeginp(); edgep; + edgep = edgep->outNextp()) { if (OrderEitherVertex* toVertexp = dynamic_cast(edgep->top())) { if (edgep->weight() && toVertexp->domainp()) { - //UINFO(0," "<domainp()<domainp() << endl); if (toVertexp->domainp()->hasCombo()) { vvertexp->varScp()->varp()->scSensitive(true); } @@ -1513,7 +1488,7 @@ void OrderVisitor::processSensitive() { } void OrderVisitor::processDomains() { - for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) { + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { OrderEitherVertex* vertexp = dynamic_cast(itp); UASSERT(vertexp, "Null or vertex not derived from EitherVertex"); processDomainsIterate(vertexp); @@ -1528,49 +1503,39 @@ void OrderVisitor::processDomainsIterate(OrderEitherVertex* vertexp) { // else, if all inputs are from flops, it's end-of-sequential code // else, it's full combo code if (vertexp->domainp()) return; // Already processed, or sequential logic - UINFO(5," pdi: "<(vertexp); AstSenTree* domainp = NULL; UASSERT(m_comboDomainp, "not preset"); - if (vvertexp && vvertexp->varScp()->varp()->isNonOutput()) { - domainp = m_comboDomainp; - } - if (vvertexp && vvertexp->varScp()->isCircular()) { - domainp = m_comboDomainp; - } + if (vvertexp && vvertexp->varScp()->varp()->isNonOutput()) domainp = m_comboDomainp; + if (vvertexp && vvertexp->varScp()->isCircular()) domainp = m_comboDomainp; if (!domainp) { for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { OrderEitherVertex* fromVertexp = static_cast(edgep->fromp()); - if (edgep->weight() - && fromVertexp->domainMatters() - ) { - UINFO(9," from d="<domainp()) - <<" "<weight() && fromVertexp->domainMatters()) { + UINFO(9, " from d=" << cvtToHex(fromVertexp->domainp()) << " " << fromVertexp + << endl); if (!domainp // First input to this vertex || domainp->hasSettle() // or, we can ignore being in the settle domain || domainp->hasInitial()) { domainp = fromVertexp->domainp(); - } - else if (domainp->hasCombo()) { + } else if (domainp->hasCombo()) { // Once in combo, keep in combo; already as severe as we can get - } - else if (fromVertexp->domainp()->hasCombo()) { + } else if (fromVertexp->domainp()->hasCombo()) { // Any combo input means this vertex must remain combo domainp = m_comboDomainp; - } - else if (fromVertexp->domainp()->hasSettle() - || fromVertexp->domainp()->hasInitial()) { + } else if (fromVertexp->domainp()->hasSettle() + || fromVertexp->domainp()->hasInitial()) { // Ignore that we have a constant (initial) input - } - else if (domainp != fromVertexp->domainp()) { + } else if (domainp != fromVertexp->domainp()) { // Make a domain that merges the two domains - bool ddebug = debug()>=9; + bool ddebug = debug() >= 9; if (ddebug) { - cout<domainp()->isMulti()?" [MULT]":"") - <<" "<domainp()->isMulti() ? " [MULT]" : "") << " " + << vertexp << endl); } } @@ -1617,32 +1580,37 @@ void OrderVisitor::processDomainsIterate(OrderEitherVertex* vertexp) { void OrderVisitor::processEdgeReport() { // Make report of all signal names and what clock edges they have string filename = v3Global.debugFilename("order_edges.txt"); - const vl_unique_ptr logp (V3File::new_ofstream(filename)); - if (logp->fail()) v3fatal("Can't write "< logp(V3File::new_ofstream(filename)); + if (logp->fail()) v3fatal("Can't write " << filename); + // Testing emitter: V3EmitV::verilogForTree(v3Global.rootp(), *logp); std::deque report; - for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) { + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { if (OrderVarVertex* vvertexp = dynamic_cast(itp)) { - string name (vvertexp->varScp()->prettyName()); - if (dynamic_cast(itp)) name += " {PRE}"; - else if (dynamic_cast(itp)) name += " {POST}"; - else if (dynamic_cast(itp)) name += " {PORD}"; - else if (dynamic_cast(itp)) name += " {STL}"; + string name(vvertexp->varScp()->prettyName()); + if (dynamic_cast(itp)) { + name += " {PRE}"; + } else if (dynamic_cast(itp)) { + name += " {POST}"; + } else if (dynamic_cast(itp)) { + name += " {PORD}"; + } else if (dynamic_cast(itp)) { + name += " {STL}"; + } std::ostringstream os; os.setf(std::ios::left); - os<<" "<varScp())<<" "<varScp()) << " " << std::setw(50) << name << " "; AstSenTree* sentreep = vvertexp->domainp(); if (sentreep) V3EmitV::verilogForTree(sentreep, os); report.push_back(os.str()); } } - *logp<<"Signals and their clock domains:"<::iterator it=report.begin(); it!=report.end(); ++it) { - *logp<<(*it)<::iterator it = report.begin(); it != report.end(); ++it) { + *logp << (*it) << endl; } } @@ -1655,13 +1623,14 @@ void OrderVisitor::processMoveClear() { void OrderVisitor::processMoveBuildGraph() { // Build graph of only vertices - UINFO(5," MoveBuildGraph\n"); + UINFO(5, " MoveBuildGraph\n"); processMoveClear(); - m_pomGraph.userClearVertices(); // Vertex::user() // OrderMoveVertex*, last edge added or NULL for none + m_pomGraph + .userClearVertices(); // Vertex::user->OrderMoveVertex*, last edge added or NULL=none OrderMoveVertexMaker createOrderMoveVertex(&m_pomGraph, &m_pomWaiting); - ProcessMoveBuildGraph serialPMBG( - &m_graph, &m_pomGraph, &createOrderMoveVertex); + ProcessMoveBuildGraph serialPMBG(&m_graph, &m_pomGraph, + &createOrderMoveVertex); serialPMBG.build(); } @@ -1684,7 +1653,7 @@ void OrderVisitor::processMove() { processMovePrepReady(); // New domain... another loop - UINFO(5," MoveIterate\n"); + UINFO(5, " MoveIterate\n"); while (!m_pomReadyDomScope.empty()) { // Start with top node on ready list's domain & scope OrderMoveDomScope* domScopep = m_pomReadyDomScope.begin(); @@ -1692,16 +1661,17 @@ void OrderVisitor::processMove() { UASSERT(topVertexp, "domScope on ready list without any nodes ready under it"); // Work on all scopes ready inside this domain while (domScopep) { - UINFO(6," MoveDomain l="<domainp()<pomWaitingNextp(); - if (vertexp->isWait() && vertexp->inEmpty()) { - processMoveReadyOne(vertexp); - } + if (vertexp->isWait() && vertexp->inEmpty()) { processMoveReadyOne(vertexp); } vertexp = nextp; } } @@ -1754,11 +1723,11 @@ void OrderVisitor::processMoveDoneOne(OrderMoveVertex* vertexp) { } // Don't need to add it to another list, as we're done with it // Mark our outputs as one closer to ready - for (V3GraphEdge* edgep = vertexp->outBeginp(), *nextp; edgep; edgep=nextp) { + for (V3GraphEdge *edgep = vertexp->outBeginp(), *nextp; edgep; edgep = nextp) { nextp = edgep->outNextp(); OrderMoveVertex* toVertexp = static_cast(edgep->top()); - UINFO(9," Clear to "<<(toVertexp->inEmpty()?"[EMP] ":" ") - <inEmpty() ? "[EMP] " : " ") << toVertexp + << endl); // Delete this edge VL_DO_DANGLING(edgep->unlinkDelete(), edgep); if (toVertexp->inEmpty()) { @@ -1770,22 +1739,21 @@ void OrderVisitor::processMoveDoneOne(OrderMoveVertex* vertexp) { } } -void OrderVisitor::processMoveOne(OrderMoveVertex* vertexp, - OrderMoveDomScope* domScopep, int level) { +void OrderVisitor::processMoveOne(OrderMoveVertex* vertexp, OrderMoveDomScope* domScopep, + int level) { UASSERT_OBJ(vertexp->domScopep() == domScopep, vertexp, "Domain mismatch; list misbuilt?"); const OrderLogicVertex* lvertexp = vertexp->logicp(); const AstScope* scopep = lvertexp->scopep(); - UINFO(5," POSmove l"<addActivep(newActivep); processMoveDoneOne(vertexp); } AstActive* OrderVisitor::processMoveOneLogic(const OrderLogicVertex* lvertexp, - AstCFunc*& newFuncpr, - int& newStmtsr) { + AstCFunc*& newFuncpr, int& newStmtsr) { AstActive* activep = NULL; AstScope* scopep = lvertexp->scopep(); AstSenTree* domainp = lvertexp->domainp(); @@ -1794,8 +1762,7 @@ AstActive* OrderVisitor::processMoveOneLogic(const OrderLogicVertex* lvertexp, UASSERT(modp, "NULL"); if (VN_IS(nodep, SenTree)) { // Just ignore sensitivities, we'll deal with them when we move statements that need them - } - else { // Normal logic + } else { // Normal logic // Make or borrow a CFunc to contain the new statements if (v3Global.opt.profCFuncs() || (v3Global.opt.outputSplitCFuncs() @@ -1817,13 +1784,13 @@ AstActive* OrderVisitor::processMoveOneLogic(const OrderLogicVertex* lvertexp, AstCCall* callp = new AstCCall(nodep->fileline(), newFuncpr); callp->argTypes("vlSymsp"); activep->addStmtsp(callp); - UINFO(6," New "<unlinkFrBack(); if (domainp == m_deleteDomainp) { - UINFO(4," Ordering deleting pre-settled "<addStmtsp(nodep); @@ -1844,20 +1811,18 @@ void OrderVisitor::processMTasksInitial(InitialLogicE logic_type) { int initStmts = 0; AstCFunc* initCFunc = NULL; AstScope* lastScopep = NULL; - for (V3GraphVertex* initVxp = m_graph.verticesBeginp(); - initVxp; initVxp = initVxp->verticesNextp()) { + for (V3GraphVertex* initVxp = m_graph.verticesBeginp(); initVxp; + initVxp = initVxp->verticesNextp()) { OrderLogicVertex* initp = dynamic_cast(initVxp); if (!initp) continue; - if ((logic_type == LOGIC_INITIAL) - && !initp->domainp()->hasInitial()) continue; - if ((logic_type == LOGIC_SETTLE) - && !initp->domainp()->hasSettle()) continue; + if ((logic_type == LOGIC_INITIAL) && !initp->domainp()->hasInitial()) continue; + if ((logic_type == LOGIC_SETTLE) && !initp->domainp()->hasSettle()) continue; if (initp->scopep() != lastScopep) { // Start new cfunc, don't let the cfunc cross scopes initCFunc = NULL; lastScopep = initp->scopep(); } - AstActive* newActivep = processMoveOneLogic(initp, initCFunc/*ref*/, initStmts/*ref*/); + AstActive* newActivep = processMoveOneLogic(initp, initCFunc /*ref*/, initStmts /*ref*/); if (newActivep) m_scopetopp->addActivep(newActivep); } } @@ -1877,8 +1842,7 @@ void OrderVisitor::processMTasks() { // This is quite similar to the 'm_pomGraph' of the serial code gen: V3Graph logicGraph; OrderMTaskMoveVertexMaker create_mtask_vertex(&logicGraph); - ProcessMoveBuildGraph mtask_pmbg( - &m_graph, &logicGraph, &create_mtask_vertex); + ProcessMoveBuildGraph mtask_pmbg(&m_graph, &logicGraph, &create_mtask_vertex); mtask_pmbg.build(); // Needed? We do this for m_pomGraph in serial mode, so do it here too: @@ -1901,11 +1865,9 @@ void OrderVisitor::processMTasks() { GraphStream emit_logic(&logicGraph); const V3GraphVertex* moveVxp; while ((moveVxp = emit_logic.nextp())) { - const MTaskMoveVertex* movep = - dynamic_cast(moveVxp); + const MTaskMoveVertex* movep = dynamic_cast(moveVxp); unsigned mtaskId = movep->color(); - UASSERT(mtaskId > 0, - "Every MTaskMoveVertex should have an mtask assignment >0"); + UASSERT(mtaskId > 0, "Every MTaskMoveVertex should have an mtask assignment >0"); if (movep->logicp()) { // Add this logic to the per-mtask order mtaskStates[mtaskId].m_logics.push_back(movep->logicp()); @@ -1915,18 +1877,17 @@ void OrderVisitor::processMTasks() { // of mtasks that consume it and produce it. We'll use this // information in V3EmitC when we lay out var's in memory. const OrderLogicVertex* logicp = movep->logicp(); - for (const V3GraphEdge* edgep = logicp->inBeginp(); - edgep; edgep = edgep->inNextp()) { - const OrderVarVertex* pre_varp = - dynamic_cast(edgep->fromp()); + for (const V3GraphEdge* edgep = logicp->inBeginp(); edgep; edgep = edgep->inNextp()) { + const OrderVarVertex* pre_varp + = dynamic_cast(edgep->fromp()); if (!pre_varp) continue; AstVar* varp = pre_varp->varScp()->varp(); // varp depends on logicp, so logicp produces varp, // and vice-versa below varp->addProducingMTaskId(mtaskId); } - for (const V3GraphEdge* edgep = logicp->outBeginp(); - edgep; edgep = edgep->outNextp()) { + for (const V3GraphEdge* edgep = logicp->outBeginp(); edgep; + edgep = edgep->outNextp()) { const OrderVarVertex* post_varp = dynamic_cast(edgep->top()); if (!post_varp) continue; @@ -1949,8 +1910,7 @@ void OrderVisitor::processMTasks() { GraphStream emit_mtasks(&mtasks); const V3GraphVertex* mtaskVxp; while ((mtaskVxp = emit_mtasks.nextp())) { - const AbstractLogicMTask* mtaskp = - dynamic_cast(mtaskVxp); + const AbstractLogicMTask* mtaskp = dynamic_cast(mtaskVxp); // Create a body for this mtask AstMTaskBody* bodyp = new AstMTaskBody(rootFlp); @@ -1963,8 +1923,8 @@ void OrderVisitor::processMTasks() { const AstSenTree* last_domainp = NULL; AstCFunc* leafCFuncp = NULL; int leafStmts = 0; - for (MTaskState::Logics::iterator it = state.m_logics.begin(); - it != state.m_logics.end(); ++it) { + for (MTaskState::Logics::iterator it = state.m_logics.begin(); it != state.m_logics.end(); + ++it) { const OrderLogicVertex* logicp = *it; if (logicp->domainp() != last_domainp) { // Start a new leaf function. @@ -1972,8 +1932,8 @@ void OrderVisitor::processMTasks() { } last_domainp = logicp->domainp(); - AstActive* newActivep = processMoveOneLogic(logicp, leafCFuncp/*ref*/, - leafStmts/*ref*/); + AstActive* newActivep + = processMoveOneLogic(logicp, leafCFuncp /*ref*/, leafStmts /*ref*/); if (newActivep) bodyp->addStmtsp(newActivep); } @@ -1984,22 +1944,18 @@ void OrderVisitor::processMTasks() { // and OrderLogicVertex's which are ephemeral to V3Order. // - The ExecMTask graph and the AstMTaskBody's produced here // persist until code generation time. - state.m_execMTaskp = - new ExecMTask(execGraphp->mutableDepGraphp(), - bodyp, mtaskp->id()); + state.m_execMTaskp = new ExecMTask(execGraphp->mutableDepGraphp(), bodyp, mtaskp->id()); // Cross-link each ExecMTask and MTaskBody // Q: Why even have two objects? // A: One is an AstNode, the other is a GraphVertex, // to combine them would involve multiple inheritance... state.m_mtaskBodyp->execMTaskp(state.m_execMTaskp); - for (V3GraphEdge* inp = mtaskp->inBeginp(); - inp; inp = inp->inNextp()) { + for (V3GraphEdge* inp = mtaskp->inBeginp(); inp; inp = inp->inNextp()) { const V3GraphVertex* fromVxp = inp->fromp(); - const AbstractLogicMTask* fromp = - dynamic_cast(fromVxp); + const AbstractLogicMTask* fromp = dynamic_cast(fromVxp); MTaskState& fromState = mtaskStates[fromp->id()]; - new V3GraphEdge(execGraphp->mutableDepGraphp(), - fromState.m_execMTaskp, state.m_execMTaskp, 1); + new V3GraphEdge(execGraphp->mutableDepGraphp(), fromState.m_execMTaskp, + state.m_execMTaskp, 1); } execGraphp->addMTaskBody(bodyp); } @@ -2016,7 +1972,7 @@ void OrderVisitor::process() { // edges) will have its own color, and corresponds to a loop in the // original graph. However the new graph will be acyclic (the removed // edges are actually still there, just with weight 0). - UINFO(2," Acyclic & Order...\n"); + UINFO(2, " Acyclic & Order...\n"); m_graph.acyclic(&V3GraphEdge::followAlwaysTrue); m_graph.dumpDotFilePrefixed("orderg_acyc"); @@ -2028,43 +1984,45 @@ void OrderVisitor::process() { // This finds everything that can be traced from an input (which by // definition are the source clocks). After this any vertex which was // traced has isFromInput() true. - UINFO(2," Process Clocks...\n"); + UINFO(2, " Process Clocks...\n"); processInputs(); // must be before processCircular - UINFO(2," Process Circulars...\n"); + UINFO(2, " Process Circulars...\n"); processCircular(); // must be before processDomains // Assign logic vertices to new domains - UINFO(2," Domains...\n"); + UINFO(2, " Domains...\n"); processDomains(); m_graph.dumpDotFilePrefixed("orderg_domain"); if (debug() && v3Global.opt.dumpTree()) processEdgeReport(); if (!v3Global.opt.mtasks()) { - UINFO(2," Construct Move Graph...\n"); + UINFO(2, " Construct Move Graph...\n"); processMoveBuildGraph(); - if (debug()>=4) m_pomGraph.dumpDotFilePrefixed("ordermv_start"); // Different prefix (ordermv) as it's not the same graph + if (debug() >= 4) + m_pomGraph.dumpDotFilePrefixed( + "ordermv_start"); // Different prefix (ordermv) as it's not the same graph m_pomGraph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue); - if (debug()>=4) m_pomGraph.dumpDotFilePrefixed("ordermv_simpl"); + if (debug() >= 4) m_pomGraph.dumpDotFilePrefixed("ordermv_simpl"); - UINFO(2," Move...\n"); + UINFO(2, " Move...\n"); processMove(); } else { - UINFO(2," Set up mtasks...\n"); + UINFO(2, " Set up mtasks...\n"); processMTasks(); } // Any SC inputs feeding a combo domain must be marked, so we can make them sc_sensitive - UINFO(2," Sensitive...\n"); + UINFO(2, " Sensitive...\n"); processSensitive(); // must be after processDomains // Dump data m_graph.dumpDotFilePrefixed("orderg_done"); if (0 && debug()) { - string dfilename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"_INT_order"; - const vl_unique_ptr logp (V3File::new_ofstream(dfilename)); - if (logp->fail()) v3fatal("Can't write "< logp(V3File::new_ofstream(dfilename)); + if (logp->fail()) v3fatal("Can't write " << dfilename); m_graph.dump(*logp); } } @@ -2073,7 +2031,7 @@ void OrderVisitor::process() { // Order class functions void V3Order::orderAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "< > IfaceRefRefs; // Note may have duplicate entries + // Note may have duplicate entries + typedef std::deque > IfaceRefRefs; // STATE - typedef std::map CloneMap; + typedef std::map CloneMap; struct ModInfo { - AstNodeModule* m_modp; // Module with specified name - CloneMap m_cloneMap; // Map of old-varp -> new cloned varp + AstNodeModule* m_modp; // Module with specified name + CloneMap m_cloneMap; // Map of old-varp -> new cloned varp explicit ModInfo(AstNodeModule* modp) { m_modp = modp; } }; - typedef std::map ModNameMap; - ModNameMap m_modNameMap; // Hash of created module flavors by name + typedef std::map ModNameMap; + ModNameMap m_modNameMap; // Hash of created module flavors by name - typedef std::map LongMap; - LongMap m_longMap; // Hash of very long names to unique identity number - int m_longId; + typedef std::map LongMap; + LongMap m_longMap; // Hash of very long names to unique identity number + int m_longId; - typedef std::pair ValueMapValue; - typedef std::map ValueMap; - ValueMap m_valueMap; // Hash of node hash to (param value, name) - int m_nextValue; // Next value to use in m_valueMap + typedef std::pair ValueMapValue; + typedef std::map ValueMap; + ValueMap m_valueMap; // Hash of node hash to (param value, name) + int m_nextValue; // Next value to use in m_valueMap - typedef std::multimap LevelModMap; - LevelModMap m_todoModps; // Modules left to process + typedef std::multimap LevelModMap; + LevelModMap m_todoModps; // Modules left to process typedef std::deque CellList; - CellList m_cellps; // Cells left to process (in this module) + CellList m_cellps; // Cells left to process (in this module) AstNodeModule* m_modp; // Current module being processed - string m_unlinkedTxt; // Text for AstUnlinkedRef + string m_unlinkedTxt; // Text for AstUnlinkedRef UnrollStateful m_unroller; // Loop unroller @@ -118,32 +119,32 @@ private: VL_DEBUG_FUNC; // Declare debug() void makeSmallNames(AstNodeModule* modp) { - std::vector usedLetter; usedLetter.resize(256); + std::vector usedLetter; + usedLetter.resize(256); // Pass 1, assign first letter to each gparam's name - for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp=stmtp->nextp()) { + for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) { if (AstVar* varp = VN_CAST(stmtp, Var)) { - if (varp->isGParam()||varp->isIfaceRef()) { + if (varp->isGParam() || varp->isIfaceRef()) { char ch = varp->name()[0]; - ch = toupper(ch); if (ch<'A' || ch>'Z') ch='Z'; - varp->user4(usedLetter[static_cast(ch)]*256 + ch); + ch = toupper(ch); + if (ch < 'A' || ch > 'Z') ch = 'Z'; + varp->user4(usedLetter[static_cast(ch)] * 256 + ch); usedLetter[static_cast(ch)]++; } } else if (AstParamTypeDType* typep = VN_CAST(stmtp, ParamTypeDType)) { char ch = 'T'; - typep->user4(usedLetter[static_cast(ch)]*256 + ch); + typep->user4(usedLetter[static_cast(ch)] * 256 + ch); usedLetter[static_cast(ch)]++; } } } string paramSmallName(AstNodeModule* modp, AstNode* varp) { - if (varp->user4()<=1) { - makeSmallNames(modp); - } - int index = varp->user4()/256; - char ch = varp->user4()&255; + if (varp->user4() <= 1) makeSmallNames(modp); + int index = varp->user4() / 256; + char ch = varp->user4() & 255; string st = cvtToStr(ch); while (index) { - st += cvtToStr(char((index%25)+'A')); + st += cvtToStr(char((index % 25) + 'A')); index /= 26; } return st; @@ -155,19 +156,17 @@ private: key = ifrtp->cellp()->modp()->name(); } else if (ifrtp->ifacep()) { key = ifrtp->ifacep()->name(); - } else { + } else { nodep->v3fatalSrc("Can't parameterize interface without module name"); } } else if (AstBasicDType* bdtp = VN_CAST(nodep, BasicDType)) { if (bdtp->isRanged()) { - key += "["+cvtToStr(bdtp->left())+":"+cvtToStr(bdtp->right())+"]"; + key += "[" + cvtToStr(bdtp->left()) + ":" + cvtToStr(bdtp->right()) + "]"; } } V3Hash hash = V3Hashed::uncachedHash(nodep); // Force hash collisions -- for testing only - if (VL_UNLIKELY(v3Global.opt.debugCollision())) { - hash = V3Hash(); - } + if (VL_UNLIKELY(v3Global.opt.debugCollision())) hash = V3Hash(); int num; ValueMap::iterator it = m_valueMap.find(hash); if (it != m_valueMap.end() && it->second.second == key) { @@ -176,20 +175,20 @@ private: num = m_nextValue++; m_valueMap[hash] = make_pair(num, key); } - return string("z")+cvtToStr(num); + return string("z") + cvtToStr(num); } void collectPins(CloneMap* clonemapp, AstNodeModule* modp) { // Grab all I/O so we can remap our pins later - for (AstNode* stmtp=modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) { + for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) { if (AstVar* varp = VN_CAST(stmtp, Var)) { if (varp->isIO() || varp->isGParam() || varp->isIfaceRef()) { // Cloning saved a pointer to the new node for us, so just follow that link. AstVar* oldvarp = varp->clonep(); - //UINFO(8,"Clone list 0x"< 0x"<<(uint32_t)varp< 0x"<<(uint32_t)varp<insert(make_pair(oldvarp, varp)); } - } - else if (AstParamTypeDType* ptp = VN_CAST(stmtp, ParamTypeDType)) { + } else if (AstParamTypeDType* ptp = VN_CAST(stmtp, ParamTypeDType)) { if (ptp->isGParam()) { AstParamTypeDType* oldptp = ptp->clonep(); clonemapp->insert(make_pair(oldptp, ptp)); @@ -198,22 +197,20 @@ private: } } void relinkPins(CloneMap* clonemapp, AstPin* startpinp) { - for (AstPin* pinp = startpinp; pinp; pinp=VN_CAST(pinp->nextp(), Pin)) { + for (AstPin* pinp = startpinp; pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { if (pinp->modVarp()) { // Find it in the clone structure - //UINFO(8,"Clone find 0x"<modVarp()<modVarp()<find(pinp->modVarp()); UASSERT_OBJ(cloneiter != clonemapp->end(), pinp, "Couldn't find pin in clone list"); pinp->modVarp(VN_CAST(cloneiter->second, Var)); - } - else if (pinp->modPTypep()) { + } else if (pinp->modPTypep()) { CloneMap::iterator cloneiter = clonemapp->find(pinp->modPTypep()); UASSERT_OBJ(cloneiter != clonemapp->end(), pinp, "Couldn't find pin in clone list"); pinp->modPTypep(VN_CAST(cloneiter->second, ParamTypeDType)); - } - else { + } else { pinp->v3fatalSrc("Not linked?"); } } @@ -227,30 +224,31 @@ private: LevelModMap::iterator itm = m_todoModps.begin(); AstNodeModule* nodep = itm->second; m_todoModps.erase(itm); - if (!nodep->user5SetOnce()) { // Process once; note clone() must clear so we do it again + if (!nodep->user5SetOnce()) { // Process once; note clone() must clear so we do it + // again m_modp = nodep; - UINFO(4," MOD "<hierName().empty()) m_modp->hierName(m_modp->origName()); iterateChildren(nodep); // Note above iterate may add to m_todoModps // // Process interface cells, then non-interface which may ref an interface cell - for (int nonIf=0; nonIf<2; ++nonIf) { - for (CellList::iterator it=m_cellps.begin(); it!=m_cellps.end(); ++it) { + for (int nonIf = 0; nonIf < 2; ++nonIf) { + for (CellList::iterator it = m_cellps.begin(); it != m_cellps.end(); ++it) { AstCell* cellp = *it; - if ((nonIf==0 && VN_IS(cellp->modp(), Iface)) - || (nonIf==1 && !VN_IS(cellp->modp(), Iface))) { - string fullName (m_modp->hierName()); - if (string* genHierNamep = (string *) cellp->user5p()) { + if ((nonIf == 0 && VN_IS(cellp->modp(), Iface)) + || (nonIf == 1 && !VN_IS(cellp->modp(), Iface))) { + string fullName(m_modp->hierName()); + if (string* genHierNamep = (string*)cellp->user5p()) { fullName += *genHierNamep; } visitCell(cellp, fullName); } } } - for (CellList::iterator it=m_cellps.begin(); it!=m_cellps.end(); ++it) { + for (CellList::iterator it = m_cellps.begin(); it != m_cellps.end(); ++it) { AstCell* cellp = *it; - if (string* genHierNamep = (string *) cellp->user5p()) { + if (string* genHierNamep = (string*)cellp->user5p()) { cellp->user5p(NULL); VL_DO_DANGLING(delete genHierNamep, genHierNamep); } @@ -268,9 +266,10 @@ private: } virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { if (nodep->dead()) { - UINFO(4," MOD-dead. "<recursiveClone()) { - UINFO(4," MOD-recursive-dead. "<dead(true); // So Dead checks won't count references to it } else if (nodep->level() <= 2 // Haven't added top yet, so level 2 is the top || VN_IS(nodep, Package)) { // Likewise haven't done wrapTopPackages yet @@ -279,9 +278,10 @@ private: m_generateHierName = ""; visitModules(); } else if (nodep->user5()) { - UINFO(4," MOD-done "<isParam()) { if (!nodep->valuep()) { nodep->v3error("Parameter without initial value is never given value" - <<" (IEEE 1800-2017 6.20.1): " - <prettyNameQ()); + << " (IEEE 1800-2017 6.20.1): " << nodep->prettyNameQ()); } else { V3Const::constifyParamsEdit(nodep); // The variable, not just the var->init() if (!VN_IS(nodep->valuep(), Const)) { // Complex init, like an array // Make a new INITIAL to set the value. // This allows the normal array/struct handling code to properly // initialize the parameter. - nodep->addNext( - new AstInitial(nodep->fileline(), - new AstAssign( - nodep->fileline(), - new AstVarRef(nodep->fileline(), nodep, true), - nodep->valuep()->cloneTree(true)))); + nodep->addNext(new AstInitial( + nodep->fileline(), + new AstAssign(nodep->fileline(), + new AstVarRef(nodep->fileline(), nodep, true), + nodep->valuep()->cloneTree(true)))); } } } @@ -325,11 +323,11 @@ private: for (; candp; candp = candp->nextp()) { if (nodep->name() == candp->name()) { if (AstVar* varp = VN_CAST(candp, Var)) { - UINFO(9,"Found interface parameter: "<varp(varp); return true; } else if (AstPin* pinp = VN_CAST(candp, Pin)) { - UINFO(9,"Found interface parameter: "<exprp(), pinp, "Interface parameter pin missing expression"); VL_DO_DANGLING(nodep->replaceWith(pinp->exprp()->cloneTree(false)), nodep); return true; @@ -345,11 +343,10 @@ private: AstNode* backp = nodep; while ((backp = backp->backp())) { if (VN_IS(backp, NodeModule)) { - UINFO(9,"Hit module boundary, done looking for interface"<isIfaceRef() + if (VN_IS(backp, Var) && VN_CAST(backp, Var)->isIfaceRef() && VN_CAST(backp, Var)->childDTypep() && (VN_CAST(VN_CAST(backp, Var)->childDTypep(), IfaceRefDType) || (VN_CAST(VN_CAST(backp, Var)->childDTypep(), UnpackArrayDType) @@ -364,8 +361,8 @@ private: // Interfaces passed in on the port map have ifaces if (AstIface* ifacep = ifacerefp->ifacep()) { if (dotted == backp->name()) { - UINFO(9,"Iface matching scope: "<stmtsp())) { + UINFO(9, "Iface matching scope: " << ifacep << endl); + if (ifaceParamReplace(nodep, ifacep->stmtsp())) { // return; } } @@ -373,8 +370,8 @@ private: // Interfaces declared in this module have cells else if (AstCell* cellp = ifacerefp->cellp()) { if (dotted == cellp->name()) { - UINFO(9,"Iface matching scope: "<paramsp())) { + UINFO(9, "Iface matching scope: " << cellp << endl); + if (ifaceParamReplace(nodep, cellp->paramsp())) { // return; } } @@ -414,21 +411,21 @@ private: size_t pos = m_unlinkedTxt.find(replacestr); if (pos == string::npos) { nodep->v3error("Could not find array index in unlinked text: '" - <name()+"__BRA__"+index+"__KET__"); + nodep->name() + "__BRA__" + index + "__KET__"); } else { nodep->v3error("Could not expand constant selection inside dotted reference: " - <selp()->prettyNameQ()); + << nodep->selp()->prettyNameQ()); return; } } // Generate Statements virtual void visit(AstGenIf* nodep) VL_OVERRIDE { - UINFO(9," GENIF "<condp()); // We suppress errors when widthing params since short-circuiting in // the conditional evaluation may mean these error can never occur. We @@ -437,9 +434,7 @@ private: // NOT recurse the body. V3Const::constifyGenerateParamsEdit(nodep->condp()); // condp may change if (const AstConst* constp = VN_CAST(nodep->condp(), Const)) { - AstNode* keepp = (constp->isZero() - ? nodep->elsesp() - : nodep->ifsp()); + AstNode* keepp = (constp->isZero() ? nodep->elsesp() : nodep->ifsp()); if (keepp) { keepp->unlinkFrBackWithNext(); nodep->replaceWith(keepp); @@ -463,8 +458,8 @@ private: UASSERT_OBJ(forp, nodep, "Non-GENFOR under generate-for BEGIN"); // We should have a GENFOR under here. We will be replacing the begin, // so process here rather than at the generate to avoid iteration problems - UINFO(9," BEGIN "<v3fatalSrc("GENFOR should have been wrapped in BEGIN"); } virtual void visit(AstGenCase* nodep) VL_OVERRIDE { - UINFO(9," GENCASE "<exprp()); V3Case::caseLint(nodep); @@ -503,9 +498,9 @@ private: V3Const::constifyParamsEdit(nodep->exprp()); // exprp may change AstConst* exprp = VN_CAST(nodep->exprp(), Const); // Constify - for (AstCaseItem* itemp = nodep->itemsp(); - itemp; itemp = VN_CAST(itemp->nextp(), CaseItem)) { - for (AstNode* ep = itemp->condsp(); ep; ) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; + itemp = VN_CAST(itemp->nextp(), CaseItem)) { + for (AstNode* ep = itemp->condsp(); ep;) { AstNode* nextp = ep->nextp(); // May edit list iterateAndNextNull(ep); VL_DO_DANGLING(V3Const::constifyParamsEdit(ep), ep); // ep may change @@ -513,16 +508,14 @@ private: } } // Item match - for (AstCaseItem* itemp = nodep->itemsp(); - itemp; itemp = VN_CAST(itemp->nextp(), CaseItem)) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; + itemp = VN_CAST(itemp->nextp(), CaseItem)) { if (!itemp->isDefault()) { - for (AstNode* ep = itemp->condsp(); ep; ep=ep->nextp()) { + for (AstNode* ep = itemp->condsp(); ep; ep = ep->nextp()) { if (const AstConst* ccondp = VN_CAST(ep, Const)) { - V3Number match (nodep, 1); + V3Number match(nodep, 1); match.opEq(ccondp->num(), exprp->num()); - if (!keepp && match.isNeqZero()) { - keepp = itemp->bodysp(); - } + if (!keepp && match.isNeqZero()) keepp = itemp->bodysp(); } else { itemp->v3error("Generate Case item does not evaluate to constant"); } @@ -530,8 +523,8 @@ private: } } // Else default match - for (AstCaseItem* itemp = nodep->itemsp(); - itemp; itemp = VN_CAST(itemp->nextp(), CaseItem)) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; + itemp = VN_CAST(itemp->nextp(), CaseItem)) { if (itemp->isDefault()) { if (!keepp) keepp = itemp->bodysp(); } @@ -540,8 +533,9 @@ private: if (keepp) { keepp->unlinkFrBackWithNext(); nodep->replaceWith(keepp); + } else { + nodep->unlinkFrBack(); } - else nodep->unlinkFrBack(); VL_DO_DANGLING(nodep->deleteTree(), nodep); } @@ -569,9 +563,9 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { // We always run this, even if no parameters, as need to look for interfaces, // and remove any recursive references { - UINFO(4,"De-parameterize: "<=10) nodep->dumpTree(cout, "-cell: "); + if (debug() >= 10) nodep->dumpTree(cout, "-cell: "); // Evaluate all module constants V3Const::constifyParamsEdit(nodep); AstNodeModule* srcModp = nodep->modp(); @@ -579,18 +573,19 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { // Make sure constification worked // Must be a separate loop, as constant conversion may have changed some pointers. - //if (debug()) nodep->dumpTree(cout, "-cel2: "); + // if (debug()) nodep->dumpTree(cout, "-cel2: "); string longname = srcModp->name(); bool any_overrides = false; - if (nodep->recursive()) any_overrides = true; // Must always clone __Vrcm (recursive modules) + // Must always clone __Vrcm (recursive modules) + if (nodep->recursive()) any_overrides = true; longname += "_"; - if (debug()>8) nodep->paramsp()->dumpTreeAndNext(cout, "-cellparams: "); - for (AstPin* pinp = nodep->paramsp(); pinp; pinp=VN_CAST(pinp->nextp(), Pin)) { + if (debug() > 8) nodep->paramsp()->dumpTreeAndNext(cout, "-cellparams: "); + for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { if (!pinp->exprp()) continue; // No-connect if (AstVar* modvarp = pinp->modVarp()) { if (!modvarp->isGParam()) { pinp->v3error("Attempted parameter setting of non-parameter: Param " - <prettyNameQ()<<" of "<prettyNameQ()); + << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); } else if (VN_IS(pinp->exprp(), InitArray) && VN_IS(modvarp->subDTypep(), UnpackArrayDType)) { // Array assigned to array @@ -601,21 +596,19 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { AstConst* exprp = VN_CAST(pinp->exprp(), Const); AstConst* origp = VN_CAST(modvarp->valuep(), Const); if (!exprp) { - //if (debug()) pinp->dumpTree(cout, "error:"); + // if (debug()) pinp->dumpTree(cout, "error:"); pinp->v3error("Can't convert defparam value to constant: Param " - <prettyNameQ()<<" of "<prettyNameQ()); - pinp->exprp()->replaceWith( - new AstConst(pinp->fileline(), - AstConst::WidthedValue(), modvarp->width(), 0)); + << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); + pinp->exprp()->replaceWith(new AstConst( + pinp->fileline(), AstConst::WidthedValue(), modvarp->width(), 0)); } else if (origp && exprp->sameTree(origp)) { // Setting parameter to its default value. Just ignore it. // This prevents making additional modules, and makes coverage more // obvious as it won't show up under a unique module page name. - } else if (exprp->num().isDouble() - || exprp->num().isString() - || exprp->num().isFourState()) { - longname += ("_" + paramSmallName(srcModp, modvarp) - + paramValueNumber(exprp)); + } else if (exprp->num().isDouble() || exprp->num().isString() + || exprp->num().isFourState()) { + longname + += ("_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp)); any_overrides = true; } else { longname += ("_" + paramSmallName(srcModp, modvarp) @@ -628,75 +621,92 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { AstNodeDType* origp = modvarp->subDTypep(); if (!exprp) { pinp->v3error("Parameter type pin value isn't a type: Param " - <prettyNameQ()<<" of "<prettyNameQ()); + << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); } else if (!origp) { pinp->v3error("Parameter type variable isn't a type: Param " - <prettyNameQ()); + << modvarp->prettyNameQ()); } else { - UINFO(9,"Parameter type assignment expr="<sameTree(origp)) { // Setting parameter to its default value. Just ignore it. // This prevents making additional modules, and makes coverage more // obvious as it won't show up under a unique module page name. } else { V3Const::constifyParamsEdit(exprp); - longname += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp); + longname + += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp); any_overrides = true; } } } else { pinp->v3error("Parameter not found in sub-module: Param " - <prettyNameQ()<<" of "<prettyNameQ()); + << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); } } IfaceRefRefs ifaceRefRefs; - for (AstPin* pinp = nodep->pinsp(); pinp; pinp=VN_CAST(pinp->nextp(), Pin)) { + for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { AstVar* modvarp = pinp->modVarp(); if (modvarp->isIfaceRef()) { AstIfaceRefDType* portIrefp = VN_CAST(modvarp->subDTypep(), IfaceRefDType); if (!portIrefp && VN_IS(modvarp->subDTypep(), UnpackArrayDType)) { - portIrefp = VN_CAST(VN_CAST(modvarp->subDTypep(), UnpackArrayDType)->subDTypep(), IfaceRefDType); + portIrefp + = VN_CAST(VN_CAST(modvarp->subDTypep(), UnpackArrayDType)->subDTypep(), + IfaceRefDType); } AstIfaceRefDType* pinIrefp = NULL; AstNode* exprp = pinp->exprp(); - if (exprp - && VN_IS(exprp, VarRef) - && VN_CAST(exprp, VarRef)->varp() + if (exprp && VN_IS(exprp, VarRef) && VN_CAST(exprp, VarRef)->varp() && VN_CAST(exprp, VarRef)->varp()->subDTypep() && VN_IS(VN_CAST(exprp, VarRef)->varp()->subDTypep(), IfaceRefDType)) { pinIrefp = VN_CAST(VN_CAST(exprp, VarRef)->varp()->subDTypep(), IfaceRefDType); - } else if (exprp - && exprp->op1p() - && VN_IS(exprp->op1p(), VarRef) + } else if (exprp && exprp->op1p() && VN_IS(exprp->op1p(), VarRef) && VN_CAST(exprp->op1p(), VarRef)->varp() && VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep() - && VN_CAST(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep(), UnpackArrayDType) - && VN_CAST(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep(), UnpackArrayDType)->subDTypep() - && VN_CAST(VN_CAST(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep(), UnpackArrayDType)->subDTypep(), IfaceRefDType)) { - pinIrefp = VN_CAST(VN_CAST(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep(), UnpackArrayDType)->subDTypep(), IfaceRefDType); - } else if (exprp - && VN_IS(exprp, VarRef) - && VN_CAST(exprp, VarRef)->varp() + && VN_CAST(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep(), + UnpackArrayDType) + && VN_CAST(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep(), + UnpackArrayDType) + ->subDTypep() + && VN_CAST(VN_CAST(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep(), + UnpackArrayDType) + ->subDTypep(), + IfaceRefDType)) { + pinIrefp = VN_CAST(VN_CAST(VN_CAST(exprp->op1p(), VarRef)->varp()->subDTypep(), + UnpackArrayDType) + ->subDTypep(), + IfaceRefDType); + } else if (exprp && VN_IS(exprp, VarRef) && VN_CAST(exprp, VarRef)->varp() && VN_CAST(exprp, VarRef)->varp()->subDTypep() - && VN_CAST(VN_CAST(exprp, VarRef)->varp()->subDTypep(), UnpackArrayDType) - && VN_CAST(VN_CAST(exprp, VarRef)->varp()->subDTypep(), UnpackArrayDType)->subDTypep() - && VN_CAST(VN_CAST(VN_CAST(exprp, VarRef)->varp()->subDTypep(), UnpackArrayDType)->subDTypep(), IfaceRefDType)) { - pinIrefp = VN_CAST(VN_CAST(VN_CAST(exprp, VarRef)->varp()->subDTypep(), UnpackArrayDType)->subDTypep(), IfaceRefDType); + && VN_CAST(VN_CAST(exprp, VarRef)->varp()->subDTypep(), + UnpackArrayDType) + && VN_CAST(VN_CAST(exprp, VarRef)->varp()->subDTypep(), + UnpackArrayDType) + ->subDTypep() + && VN_CAST(VN_CAST(VN_CAST(exprp, VarRef)->varp()->subDTypep(), + UnpackArrayDType) + ->subDTypep(), + IfaceRefDType)) { + pinIrefp = VN_CAST( + VN_CAST(VN_CAST(exprp, VarRef)->varp()->subDTypep(), UnpackArrayDType) + ->subDTypep(), + IfaceRefDType); } - UINFO(9," portIfaceRef "<v3error("Interface port "<prettyNameQ() - <<" is not an interface " << modvarp); + pinp->v3error("Interface port " << modvarp->prettyNameQ() + << " is not an interface " << modvarp); } else if (!pinIrefp) { - pinp->v3error("Interface port "<prettyNameQ() - <<" is not connected to interface/modport pin expression"); + pinp->v3error("Interface port " + << modvarp->prettyNameQ() + << " is not connected to interface/modport pin expression"); } else { - UINFO(9," pinIfaceRef "<ifaceViaCellp() != pinIrefp->ifaceViaCellp()) { - UINFO(9," IfaceRefDType needs reconnect "<modVarp()) + paramValueNumber(pinIrefp)); any_overrides = true; @@ -704,11 +714,11 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { if (portIrefp->ifacep() != pinIrefp->ifacep() // Might be different only due to param cloning, so check names too && portIrefp->ifaceName() != pinIrefp->ifaceName()) { - pinp->v3error("Port "<prettyNameQ()<<" expects " - <ifaceName()) - <<" interface but pin connects " - <ifaceName()) - <<" interface"); + pinp->v3error("Port " << pinp->prettyNameQ() << " expects " + << AstNode::prettyNameQ(portIrefp->ifaceName()) + << " interface but pin connects " + << AstNode::prettyNameQ(pinIrefp->ifaceName()) + << " interface"); } } } @@ -716,23 +726,24 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { } if (!any_overrides) { - UINFO(8,"Cell parameters all match original values, skipping expansion.\n"); + UINFO(8, "Cell parameters all match original values, skipping expansion.\n"); } else { // If the name is very long, we don't want to overwhelm the filename limit // We don't do this always, as it aids debugability to have intuitive naming. // TODO can use new V3Name hash replacement instead of this string newname = longname; - if (longname.length()>30) { + if (longname.length() > 30) { LongMap::iterator iter = m_longMap.find(longname); if (iter != m_longMap.end()) { newname = iter->second; } else { newname = srcModp->name(); - newname += "__pi"+cvtToStr(++m_longId); // We use all upper case above, so lower here can't conflict + // We use all upper case above, so lower here can't conflict + newname += "__pi" + cvtToStr(++m_longId); m_longMap.insert(make_pair(longname, newname)); } } - UINFO(4,"Name: "<name()<<"->"<"<name() << "->" << longname << "->" << newname << endl); // // Already made this flavor? @@ -750,11 +761,11 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { cellmodp->recursiveClone(false); nodep->recursive(false); // Recursion may need level cleanups - if (cellmodp->level() <= m_modp->level()) cellmodp->level(m_modp->level()+1); + if (cellmodp->level() <= m_modp->level()) cellmodp->level(m_modp->level() + 1); if ((cellmodp->level() - srcModp->level()) >= (v3Global.opt.moduleRecursionDepth() - 2)) { nodep->v3error("Exceeded maximum --module-recursion-depth of " - <name(), ModInfo(cellmodp))); iter = m_modNameMap.find(newname); CloneMap* clonemapp = &(iter->second.m_cloneMap); - UINFO(4," De-parameterize to new: "<paramsp()); // Fix any interface references - for (IfaceRefRefs::iterator it=ifaceRefRefs.begin(); - it!=ifaceRefRefs.end(); ++it) { + for (IfaceRefRefs::iterator it = ifaceRefRefs.begin(); it != ifaceRefRefs.end(); + ++it) { AstIfaceRefDType* portIrefp = it->first; AstIfaceRefDType* pinIrefp = it->second; AstIfaceRefDType* cloneIrefp = portIrefp->clonep(); - UINFO(8," IfaceOld "<ifacep(pinIrefp->ifaceViaCellp()); - UINFO(8," IfaceNew "<paramsp(); pinp; pinp=VN_CAST(pinp->nextp(), Pin)) { + for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { if (pinp->exprp()) { if (AstVar* modvarp = pinp->modVarp()) { AstNode* newp = pinp->exprp(); // Const or InitArray @@ -801,8 +812,7 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { if (modvarp->valuep()) modvarp->valuep()->unlinkFrBack()->deleteTree(); // Set this parameter to value requested by cell modvarp->valuep(newp->cloneTree(false)); - } - else if (AstParamTypeDType* modptp = pinp->modPTypep()) { + } else if (AstParamTypeDType* modptp = pinp->modPTypep()) { AstNodeDType* dtypep = VN_CAST(pinp->exprp(), NodeDType); UASSERT_OBJ(dtypep, pinp, "unlinked param dtype"); if (modptp->childDTypep()) { @@ -817,7 +827,7 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { } } else { - UINFO(4," De-parameterize to old: "<second.m_cloneMap); relinkPins(clonemapp, nodep->pinsp()); - UINFO(8," Done with "<recursive(false); // Delete the parameters from the cell; they're not relevant any longer. if (nodep->paramsp()) nodep->paramsp()->unlinkFrBackWithNext()->deleteTree(); - UINFO(8," Done with "<=10) v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("param-out.tree")); + UINFO(8, " Done with " << nodep << endl); + // if (debug() >= 10) + // v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("param-out.tree")); } // Now remember to process the child module at the end of the module @@ -846,9 +857,7 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { // Param class functions void V3Param::param(AstNetlist* rootp) { - UINFO(2,__FUNCTION__<<": "<= 6); } diff --git a/src/V3ParseGrammar.cpp b/src/V3ParseGrammar.cpp index a0426103a..805b10974 100644 --- a/src/V3ParseGrammar.cpp +++ b/src/V3ParseGrammar.cpp @@ -14,7 +14,6 @@ // //************************************************************************* - #include "V3Ast.h" // This must be before V3ParseBison.cpp, as we don't want #defines to conflict //====================================================================== @@ -27,7 +26,7 @@ int V3ParseImp::bisonParse() { // Use --debugi-bison 9 to enable this - if (PARSEP->debugBison()>=9) yydebug = 1; + if (PARSEP->debugBison() >= 9) yydebug = 1; return yyparse(); } @@ -36,8 +35,8 @@ const char* V3ParseImp::tokenName(int token) { static const char** nameTablep = NULL; if (!nameTablep) { int size; - for (size = 0; yytname[size]; ++size) ; - nameTablep = new const char* [size]; + for (size = 0; yytname[size]; ++size) {} + nameTablep = new const char*[size]; // Workaround bug in bison's which have '!' in yytname but not token values int iout = 0; for (int i = 0; yytname[i]; ++i) { @@ -46,9 +45,11 @@ const char* V3ParseImp::tokenName(int token) { } } if (token >= 255) { - return nameTablep[token-255]; + return nameTablep[token - 255]; } else { - static char ch[2]; ch[0] = token; ch[1] = '\0'; + static char ch[2]; + ch[0] = token; + ch[1] = '\0'; return ch; } #else @@ -76,18 +77,20 @@ void V3ParseGrammar::argWrapList(AstNodeFTaskRef* nodep) { } AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, const string& name, int value) { - return new AstAssignW(fileline, new AstVarRef(fileline, name, true), - new AstConst(fileline, AstConst::StringToParse(), - (value ? "'1" : "'0"))); + return new AstAssignW( + fileline, new AstVarRef(fileline, name, true), + new AstConst(fileline, AstConst::StringToParse(), (value ? "'1" : "'0"))); } AstRange* V3ParseGrammar::scrubRange(AstNodeRange* nrangep) { // Remove any UnsizedRange's from list - for (AstNodeRange* nodep = nrangep, *nextp; nodep; nodep = nextp) { + for (AstNodeRange *nodep = nrangep, *nextp; nodep; nodep = nextp) { nextp = VN_CAST(nodep->nextp(), NodeRange); if (!VN_IS(nodep, Range)) { - nodep->v3error("Unsupported or syntax error: Unsized range in cell or other declaration"); - nodep->unlinkFrBack(); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->v3error( + "Unsupported or syntax error: Unsized range in cell or other declaration"); + nodep->unlinkFrBack(); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } } if (nrangep && nrangep->nextp()) { @@ -98,8 +101,8 @@ AstRange* V3ParseGrammar::scrubRange(AstNodeRange* nrangep) { return VN_CAST(nrangep, Range); } -AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep, - AstNodeRange* nrangep, bool isPacked) { +AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep, AstNodeRange* nrangep, + bool isPacked) { // Split RANGE0-RANGE1-RANGE2 // into ARRAYDTYPE0(ARRAYDTYPE1(ARRAYDTYPE2(BASICTYPE3), RANGE), RANGE) AstNodeDType* arrayp = basep; @@ -110,26 +113,26 @@ AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep, if (prevp) nrangep->unlinkFrBack(); AstRange* rangep = VN_CAST(nrangep, Range); if (rangep && isPacked) { - arrayp = new AstPackArrayDType - (rangep->fileline(), VFlagChildDType(), arrayp, rangep); + arrayp + = new AstPackArrayDType(rangep->fileline(), VFlagChildDType(), arrayp, rangep); } else if (VN_IS(nrangep, QueueRange)) { - arrayp = new AstQueueDType - (nrangep->fileline(), VFlagChildDType(), arrayp, NULL); - } else if (rangep && (VN_IS(rangep->leftp(), Unbounded) - || VN_IS(rangep->rightp(), Unbounded))) { + arrayp = new AstQueueDType(nrangep->fileline(), VFlagChildDType(), arrayp, NULL); + } else if (rangep + && (VN_IS(rangep->leftp(), Unbounded) + || VN_IS(rangep->rightp(), Unbounded))) { arrayp = new AstQueueDType(nrangep->fileline(), VFlagChildDType(), arrayp, rangep->rightp()->cloneTree(true)); } else if (rangep) { - arrayp = new AstUnpackArrayDType - (rangep->fileline(), VFlagChildDType(), arrayp, rangep); + arrayp = new AstUnpackArrayDType(rangep->fileline(), VFlagChildDType(), arrayp, + rangep); } else if (VN_IS(nrangep, UnsizedRange)) { - arrayp = new AstUnsizedArrayDType - (nrangep->fileline(), VFlagChildDType(), arrayp); + arrayp = new AstUnsizedArrayDType(nrangep->fileline(), VFlagChildDType(), arrayp); } else if (VN_IS(nrangep, AssocRange)) { AstAssocRange* arangep = VN_CAST(nrangep, AssocRange); - AstNodeDType* keyp = arangep->keyDTypep(); keyp->unlinkFrBack(); - arrayp = new AstAssocArrayDType - (nrangep->fileline(), VFlagChildDType(), arrayp, keyp); + AstNodeDType* keyp = arangep->keyDTypep(); + keyp->unlinkFrBack(); + arrayp + = new AstAssocArrayDType(nrangep->fileline(), VFlagChildDType(), arrayp, keyp); } else { UASSERT_OBJ(0, nrangep, "Expected range or unsized range"); } @@ -142,10 +145,9 @@ AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep, AstVar* V3ParseGrammar::createVariable(FileLine* fileline, const string& name, AstNodeRange* arrayp, AstNode* attrsp) { AstNodeDType* dtypep = GRAMMARP->m_varDTypep; - UINFO(5," creVar "<m_varIO == VDirection::NONE - && GRAMMARP->m_varDecl == AstVarType::PORT) { + UINFO(5, " creVar " << name << " decl=" << GRAMMARP->m_varDecl << " io=" + << GRAMMARP->m_varIO << " dt=" << (dtypep ? "set" : "") << endl); + if (GRAMMARP->m_varIO == VDirection::NONE && GRAMMARP->m_varDecl == AstVarType::PORT) { // Just a port list with variable name (not v2k format); AstPort already created if (dtypep) fileline->v3error("Unsupported: Ranges ignored in port-lists"); return NULL; @@ -159,7 +161,8 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, const string& name, } else { // May make new variables with same type, so clone dtypep = dtypep->cloneTree(false); } - //UINFO(0,"CREVAR "<ascii()<<" decl="<m_varDecl.ascii()<<" io="<m_varIO.ascii()<ascii()<<" decl="<m_varDecl.ascii()<<" + // io="<m_varIO.ascii()<m_varDecl; if (type == AstVarType::UNKNOWN) { if (GRAMMARP->m_varIO.isAny()) { @@ -169,7 +172,7 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, const string& name, } } if (type == AstVarType::GENVAR) { - if (arrayp) fileline->v3error("Genvars may not be arrayed: "<v3error("Genvars may not be arrayed: " << name); } // Split RANGE0-RANGE1-RANGE2 into @@ -202,9 +205,13 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, const string& name, // We need to autosize parameters and integers separately // // Propagate from current module tracing state - if (nodep->isGenVar()) nodep->trace(false); - else if (nodep->isParam() && !v3Global.opt.traceParams()) nodep->trace(false); - else nodep->trace(allTracingOn(nodep->fileline())); + if (nodep->isGenVar()) { + nodep->trace(false); + } else if (nodep->isParam() && !v3Global.opt.traceParams()) { + nodep->trace(false); + } else { + nodep->trace(allTracingOn(nodep->fileline())); + } // Remember the last variable created, so we can attach attributes to it in later parsing GRAMMARP->m_varAttrp = nodep; @@ -222,7 +229,7 @@ string V3ParseGrammar::deQuote(FileLine* fileline, string text) { for (string::const_iterator cp = text.begin(); cp != text.end(); ++cp) { if (quoted) { if (isdigit(*cp)) { - octal_val = octal_val*8 + (*cp-'0'); + octal_val = octal_val * 8 + (*cp - '0'); if (++octal_digits == 3) { octal_digits = 0; quoted = false; @@ -238,29 +245,33 @@ string V3ParseGrammar::deQuote(FileLine* fileline, string text) { continue; } quoted = false; - if (*cp == 'n') newtext += '\n'; - else if (*cp == 'a') newtext += '\a'; // SystemVerilog 3.1 - else if (*cp == 'f') newtext += '\f'; // SystemVerilog 3.1 - else if (*cp == 'r') newtext += '\r'; - else if (*cp == 't') newtext += '\t'; - else if (*cp == 'v') newtext += '\v'; // SystemVerilog 3.1 - else if (*cp == 'x' && isxdigit(cp[1]) && isxdigit(cp[2])) { // SystemVerilog 3.1 -#define vl_decodexdigit(c) ((isdigit(c)?((c)-'0'):(tolower((c))-'a'+10))) - newtext += (char)(16*vl_decodexdigit(cp[1]) + vl_decodexdigit(cp[2])); + if (*cp == 'n') { + newtext += '\n'; + } else if (*cp == 'a') { + newtext += '\a'; // SystemVerilog 3.1 + } else if (*cp == 'f') { + newtext += '\f'; // SystemVerilog 3.1 + } else if (*cp == 'r') { + newtext += '\r'; + } else if (*cp == 't') { + newtext += '\t'; + } else if (*cp == 'v') { + newtext += '\v'; // SystemVerilog 3.1 + } else if (*cp == 'x' && isxdigit(cp[1]) + && isxdigit(cp[2])) { // SystemVerilog 3.1 +#define vl_decodexdigit(c) ((isdigit(c) ? ((c) - '0') : (tolower((c)) - 'a' + 10))) + newtext += (char)(16 * vl_decodexdigit(cp[1]) + vl_decodexdigit(cp[2])); cp += 2; - } - else if (isalnum(*cp)) { - fileline->v3error("Unknown escape sequence: \\"<<*cp); + } else if (isalnum(*cp)) { + fileline->v3error("Unknown escape sequence: \\" << *cp); break; - } - else newtext += *cp; + } else + newtext += *cp; } - } - else if (*cp == '\\') { + } else if (*cp == '\\') { quoted = true; octal_digits = 0; - } - else if (*cp != '"') { + } else if (*cp != '"') { newtext += *cp; } } diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp index ca502f9b3..2294d08f4 100644 --- a/src/V3ParseImp.cpp +++ b/src/V3ParseImp.cpp @@ -41,9 +41,9 @@ //====================================================================== // Globals -V3ParseImp* V3ParseImp::s_parsep = NULL; +V3ParseImp* V3ParseImp::s_parsep = NULL; -int V3ParseSym::s_anonNum = 0; +int V3ParseSym::s_anonNum = 0; extern void yyerror(const char*); extern void yyerrorf(const char* format, ...); @@ -63,7 +63,10 @@ V3ParseImp::~V3ParseImp() { lexDestroy(); parserClear(); - if (debug()>=9) { UINFO(0,"~V3ParseImp\n"); symp()->dump(cout, "-vpi: "); } + if (debug() >= 9) { + UINFO(0, "~V3ParseImp\n"); + symp()->dump(cout, "-vpi: "); + } } //###################################################################### @@ -73,7 +76,7 @@ void V3ParseImp::ppline(const char* textp) { // Handle `line directive FileLine* prevFl = copyOrSameFileLine(); int enterExit; - fileline()->lineDirective(textp, enterExit/*ref*/); + fileline()->lineDirective(textp, enterExit /*ref*/); if (enterExit == 1) { // Enter fileline()->parent(prevFl); } else if (enterExit == 2) { // Exit @@ -83,9 +86,7 @@ void V3ParseImp::ppline(const char* textp) { } } -void V3ParseImp::verilatorCmtLintSave() { - m_lintState.push_back(*parsep()->fileline()); -} +void V3ParseImp::verilatorCmtLintSave() { m_lintState.push_back(*parsep()->fileline()); } void V3ParseImp::verilatorCmtLintRestore() { if (m_lintState.empty()) { @@ -117,16 +118,10 @@ void V3ParseImp::verilatorCmtBad(const char* textp) { if (cmtparse.substr(0, strlen("/*verilator")) == "/*verilator") { cmtparse.replace(0, strlen("/*verilator"), ""); } - while (isspace(cmtparse[0])) { - cmtparse.replace(0, 1, ""); - } + while (isspace(cmtparse[0])) cmtparse.replace(0, 1, ""); string cmtname; - for (int i = 0; isalnum(cmtparse[i]); i++) { - cmtname += cmtparse[i]; - } - if (!parsep()->optFuture(cmtname)) { - yyerrorf("Unknown verilator comment: %s", textp); - } + for (int i = 0; isalnum(cmtparse[i]); i++) { cmtname += cmtparse[i]; } + if (!parsep()->optFuture(cmtname)) yyerrorf("Unknown verilator comment: %s", textp); } void V3ParseImp::errorPreprocDirective(const char* textp) { @@ -140,8 +135,9 @@ void V3ParseImp::errorPreprocDirective(const char* textp) { } V3PreShell::candidateDefines(&speller); string suggest = speller.bestCandidateMsg(textp); - fileline()->v3error("Define or directive not defined: '"<warnMore()+suggest)); + fileline()->v3error("Define or directive not defined: '" + << textp << "'\n" + << (suggest.empty() ? "" : fileline()->warnMore() + suggest)); } void V3ParseImp::tag(const char* text) { @@ -154,19 +150,22 @@ void V3ParseImp::tag(const char* text) { } double V3ParseImp::parseDouble(const char* textp, size_t length, bool* successp) { - char* strgp = new char[length+1]; + char* strgp = new char[length + 1]; char* dp = strgp; if (successp) *successp = true; - for (const char* sp = textp; sp < (textp+length); ++sp) { + for (const char* sp = textp; sp < (textp + length); ++sp) { if (*sp != '_') *dp++ = *sp; } *dp++ = '\0'; char* endp = strgp; double d = strtod(strgp, &endp); - size_t parsed_len = endp-strgp; + size_t parsed_len = endp - strgp; if (parsed_len != strlen(strgp)) { - if (successp) *successp = false; - else yyerrorf("Syntax error parsing real: %s", strgp); + if (successp) { + *successp = false; + } else { + yyerrorf("Syntax error parsing real: %s", strgp); + } } VL_DO_DANGLING(delete[] strgp, strgp); return d; @@ -179,20 +178,21 @@ size_t V3ParseImp::ppInputToLex(char* buf, size_t max_size) { size_t got = 0; while (got < max_size // Haven't got enough && !m_ppBuffers.empty()) { // And something buffered - string front = m_ppBuffers.front(); m_ppBuffers.pop_front(); + string front = m_ppBuffers.front(); + m_ppBuffers.pop_front(); size_t len = front.length(); - if (len > (max_size-got)) { // Front string too big - string remainder = front.substr(max_size-got); - front = front.substr(0, max_size-got); + if (len > (max_size - got)) { // Front string too big + string remainder = front.substr(max_size - got); + front = front.substr(0, max_size - got); m_ppBuffers.push_front(remainder); // Put back remainder for next time - len = (max_size-got); + len = (max_size - got); } - memcpy(buf+got, front.c_str(), len); + memcpy(buf + got, front.c_str(), len); got += len; } - if (debug()>=9) { + if (debug() >= 9) { string out = string(buf, got); - cout<<" inputToLex got="<::iterator it = m_ppBuffers.begin(); it!=m_ppBuffers.end(); ++it) { + for (std::deque::iterator it = m_ppBuffers.begin(); it != m_ppBuffers.end(); + ++it) { if (noblanks) { bool blank = true; for (string::iterator its = it->begin(); its != it->end(); ++its) { - if (!isspace(*its) && *its!='\n') { blank = false; break; } + if (!isspace(*its) && *its != '\n') { + blank = false; + break; + } } if (blank) continue; } @@ -220,7 +224,7 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i const string& errmsg) { // "" for no error, make fake node string modname = V3Os::filenameNonExt(modfilename); - UINFO(2,__FUNCTION__<<": "<newContent(); m_inLibrary = inLibrary; @@ -237,7 +241,8 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i if (v3Global.opt.preprocOnly() || v3Global.opt.keepTempFiles()) { // Create output file with all the preprocessor output we buffered up - string vppfilename = v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"_"+modname+".vpp"; + string vppfilename + = v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "_" + modname + ".vpp"; std::ofstream* ofp = NULL; std::ostream* osp; if (v3Global.opt.preprocOnly()) { @@ -246,7 +251,7 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i osp = ofp = V3File::new_ofstream(vppfilename); } if (osp->fail()) { - fileline->v3error("Cannot write preprocessor output: "+vppfilename); + fileline->v3error("Cannot write preprocessor output: " + vppfilename); return; } else { preprocDumps(*osp); @@ -267,7 +272,7 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i void V3ParseImp::lexFile(const string& modname) { // Prepare for lexing - UINFO(3,"Lexing "<warnResetDefault(); // Reenable warnings on each file lexDestroy(); // Restart from clean slate. @@ -283,7 +288,7 @@ void V3ParseImp::lexFile(const string& modname) { V3Parse::V3Parse(AstNetlist* rootp, VInFilter* filterp, V3ParseSym* symp) { m_impp = new V3ParseImp(rootp, filterp, symp); } -V3Parse::~V3Parse() { +V3Parse::~V3Parse() { // VL_DO_CLEAR(delete m_impp, m_impp = NULL); } void V3Parse::parseFile(FileLine* fileline, const string& modname, bool inLibrary, diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index 7c2076f4e..cc75b3ca8 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -45,49 +45,49 @@ typedef enum { iprop_NONE, iprop_CONTEXT, iprop_PURE } V3ImportProperty; // We can't use bison's %union as we want to pass the fileline with all tokens struct V3ParseBisonYYSType { - FileLine* fl; - AstNode* scp; // Symbol table scope for future lookups - int token; // Read token, aka tok + FileLine* fl; + AstNode* scp; // Symbol table scope for future lookups + int token; // Read token, aka tok union { - V3Number* nump; - string* strp; - int cint; - double cdouble; - bool cbool; - V3UniqState uniqstate; - VSignedState signstate; + V3Number* nump; + string* strp; + int cint; + double cdouble; + bool cbool; + V3UniqState uniqstate; + VSignedState signstate; V3ImportProperty iprop; V3ErrorCode::en errcodeen; AstAttrType::en attrtypeen; - AstNode* nodep; + AstNode* nodep; - AstBasicDType* bdtypep; - AstBegin* beginp; - AstCase* casep; - AstCaseItem* caseitemp; - AstCell* cellp; - AstClass* classp; - AstConst* constp; + AstBasicDType* bdtypep; + AstBegin* beginp; + AstCase* casep; + AstCaseItem* caseitemp; + AstCell* cellp; + AstClass* classp; + AstConst* constp; AstMemberDType* memberp; - AstNodeModule* modulep; + AstNodeModule* modulep; AstNodeUOrStructDType* uorstructp; - AstNodeDType* dtypep; - AstNodeFTask* ftaskp; + AstNodeDType* dtypep; + AstNodeFTask* ftaskp; AstNodeFTaskRef* ftaskrefp; - AstNodeRange* rangep; + AstNodeRange* rangep; AstNodeSenItem* senitemp; - AstNodeVarRef* varnodep; - AstPackage* packagep; - AstPackageRef* packagerefp; - AstParseRef* parserefp; - AstPatMember* patmemberp; - AstPattern* patternp; - AstPin* pinp; - AstRefDType* refdtypep; - AstSenTree* sentreep; - AstVar* varp; - AstVarRef* varrefp; + AstNodeVarRef* varnodep; + AstPackage* packagep; + AstPackageRef* packagerefp; + AstParseRef* parserefp; + AstPatMember* patmemberp; + AstPattern* patternp; + AstPin* pinp; + AstRefDType* refdtypep; + AstSenTree* sentreep; + AstVar* varp; + AstVarRef* varrefp; }; }; @@ -97,33 +97,33 @@ struct V3ParseBisonYYSType { class V3ParseImp { // MEMBERS - AstNetlist* m_rootp; // Root of the design - VInFilter* m_filterp; // Reading filter - V3ParseSym* m_symp; // Symbol table + AstNetlist* m_rootp; // Root of the design + VInFilter* m_filterp; // Reading filter + V3ParseSym* m_symp; // Symbol table - V3Lexer* m_lexerp; // Current FlexLexer - static V3ParseImp* s_parsep; // Current THIS, bison() isn't class based - FileLine* m_fileline; // Filename/linenumber currently active + V3Lexer* m_lexerp; // Current FlexLexer + static V3ParseImp* s_parsep; // Current THIS, bison() isn't class based + FileLine* m_fileline; // Filename/linenumber currently active - bool m_inCellDefine; // Inside a `celldefine - bool m_inLibrary; // Currently reading a library vs. regular file - int m_inBeginKwd; // Inside a `begin_keywords - int m_lastVerilogState; // Last LEX state in `begin_keywords + bool m_inCellDefine; // Inside a `celldefine + bool m_inLibrary; // Currently reading a library vs. regular file + int m_inBeginKwd; // Inside a `begin_keywords + int m_lastVerilogState; // Last LEX state in `begin_keywords VOptionBool m_unconnectedDrive; // Last unconnected drive - int m_prevLexToken; // previous parsed token (for lexer) - bool m_ahead; // aheadval is valid - V3ParseBisonYYSType m_aheadVal; // ahead token value + int m_prevLexToken; // previous parsed token (for lexer) + bool m_ahead; // aheadval is valid + V3ParseBisonYYSType m_aheadVal; // ahead token value V3ParseBisonYYSType m_curBisonVal; // current token for error reporting - V3ParseBisonYYSType m_prevBisonVal; // previous token for error reporting + V3ParseBisonYYSType m_prevBisonVal; // previous token for error reporting - std::deque m_stringps; // Created strings for later cleanup - std::deque m_numberps; // Created numbers for later cleanup - std::deque m_lintState; // Current lint state for save/restore - std::deque m_ppBuffers; // Preprocessor->lex buffer of characters to process + std::deque m_stringps; // Created strings for later cleanup + std::deque m_numberps; // Created numbers for later cleanup + std::deque m_lintState; // Current lint state for save/restore + std::deque m_ppBuffers; // Preprocessor->lex buffer of characters to process - string m_tag; // Contents (if any) of current verilator tag - AstNode* m_tagNodep; // Points to the node to set to m_tag or NULL to not set. + string m_tag; // Contents (if any) of current verilator tag + AstNode* m_tagNodep; // Points to the node to set to m_tag or NULL to not set. public: // Note these are an exception to using the filename as the debug type static int debugBison() { @@ -151,12 +151,21 @@ public: void errorPreprocDirective(const char* textp); void tag(const char* text); void tagNodep(AstNode* nodep) { m_tagNodep = nodep; } - AstNode* tagNodep() const { return m_tagNodep;} + AstNode* tagNodep() const { return m_tagNodep; } static double parseDouble(const char* text, size_t length, bool* successp = NULL); - void pushBeginKeywords(int state) { m_inBeginKwd++; m_lastVerilogState = state; } + void pushBeginKeywords(int state) { + m_inBeginKwd++; + m_lastVerilogState = state; + } bool popBeginKeywords() { - if (m_inBeginKwd) { m_inBeginKwd--; return true; } else return false; } + if (m_inBeginKwd) { + m_inBeginKwd--; + return true; + } else { + return false; + } + } int lastVerilogState() const { return m_lastVerilogState; } static const char* tokenName(int tok); @@ -204,7 +213,7 @@ public: void unconnectedDrive(const VOptionBool flag) { m_unconnectedDrive = flag; } // Interactions with parser - int bisonParse(); + int bisonParse(); // Interactions with lexer void lexNew(); @@ -222,7 +231,9 @@ public: public: // CONSTRUCTORS V3ParseImp(AstNetlist* rootp, VInFilter* filterp, V3ParseSym* parserSymp) - : m_rootp(rootp), m_filterp(filterp), m_symp(parserSymp) { + : m_rootp(rootp) + , m_filterp(filterp) + , m_symp(parserSymp) { m_fileline = NULL; m_lexerp = NULL; m_inCellDefine = false; diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp index 04a063f31..fda0bf411 100644 --- a/src/V3Partition.cpp +++ b/src/V3Partition.cpp @@ -54,7 +54,6 @@ class MergeCandidate; // handle huge nodes gracefully. Maybe not! But it still can, given // appropriate tuning. - // PART_SIBLING_EDGE_LIMIT (integer) // // Arbitrarily limit the number of edges on a single vertex that will be @@ -76,7 +75,6 @@ class MergeCandidate; // vertices, leave this as is. #define PART_SIBLING_EDGE_LIMIT 25 - // PART_STEPPED_COST (boolean) // // When computing critical path costs, use a step function on the actual @@ -109,7 +107,6 @@ class MergeCandidate; // behavior. #define PART_STEPPED_COST true - // PART_STEPPED_RESCORE_LIMIT (boolean) // // If false, we always try to merge the absolute lowest (best) scoring @@ -132,7 +129,6 @@ class MergeCandidate; // is fixed) leave it set false for the most aggressive partition. #define PART_STEPPED_RESCORE_LIMIT false - // Don't produce more than a certain maximum number of MTasks. This helps // the TSP variable sort not to blow up (a concern for some of the tests) // and we probably don't want a huge number of mtasks in practice anyway @@ -158,8 +154,7 @@ static void partCheckCachedScoreVsActual(uint32_t cached, uint32_t actual) { // won't propagate that new CP to children as it hasn't grown. So, // children may continue to think that the CP coming through this path // is a little higher than it really is; permit that. - UASSERT((((cached * 10) <= (actual * 11)) - && (cached * 11) >= (actual * 10)), + UASSERT((((cached * 10) <= (actual * 11)) && (cached * 11) >= (actual * 10)), "Calculation error in scoring (approximate, may need tweak)"); #else UASSERT(cached == actual, "Calculation error in scoring"); @@ -199,8 +194,7 @@ private: public: // CONSTRUCTORS - PartPropagateCp(V3Graph* graphp, GraphWay way, T_CostAccessor* accessp, - bool slowAsserts, + PartPropagateCp(V3Graph* graphp, GraphWay way, T_CostAccessor* accessp, bool slowAsserts, V3EdgeFuncP edgeFuncp = &V3GraphEdge::followAlwaysTrue) : GraphAlg<>(graphp, edgeFuncp) , m_way(way) @@ -213,8 +207,7 @@ public: // For *vxp, whose CP-inclusive has just increased to // newInclusiveCp, iterate to all wayward nodes, update the edges // of each, and add each to m_pending if its overall CP has grown. - for (V3GraphEdge* edgep = vxp->beginp(m_way); - edgep; edgep = edgep->nextp(m_way)) { + for (V3GraphEdge* edgep = vxp->beginp(m_way); edgep; edgep = edgep->nextp(m_way)) { if (!m_edgeFuncp(edgep)) continue; V3GraphVertex* relativep = edgep->furtherp(m_way); m_accessp->notifyEdgeCp(relativep, m_way, vxp, newInclusiveCp); @@ -222,8 +215,8 @@ public: if (m_accessp->critPathCost(relativep, m_way) < newInclusiveCp) { // relativep's critPathCost() is out of step with its // longest !wayward edge. Schedule that to be resolved. - uint32_t newPendingVal = - newInclusiveCp - m_accessp->critPathCost(relativep, m_way); + uint32_t newPendingVal + = newInclusiveCp - m_accessp->critPathCost(relativep, m_way); if (m_pending.has(relativep)) { if (newPendingVal > m_pending.at(relativep)) { m_pending.set(relativep, newPendingVal); @@ -262,9 +255,7 @@ public: // to its edges, update the critPathCost. uint32_t startCp = m_accessp->critPathCost(updateMep, m_way); uint32_t newCp = startCp + cpGrowBy; - if (m_slowAsserts) { - m_accessp->checkNewCpVersusEdges(updateMep, m_way, newCp); - } + if (m_slowAsserts) m_accessp->checkNewCpVersusEdges(updateMep, m_way, newCp); m_accessp->setCritPathCost(updateMep, m_way, newCp); cpHasIncreased(updateMep, newCp + m_accessp->cost(updateMep)); @@ -292,19 +283,18 @@ private: // METHODS protected: friend class PartPropagateCp; - void notifyEdgeCp(V3GraphVertex* vxp, GraphWay way, - V3GraphVertex* throughp, uint32_t cp) const { + void notifyEdgeCp(V3GraphVertex* vxp, GraphWay way, V3GraphVertex* throughp, + uint32_t cp) const { uint32_t throughCost = critPathCost(throughp, way); UASSERT_SELFTEST(uint32_t, cp, (1 + throughCost)); } + private: - void checkNewCpVersusEdges(V3GraphVertex* vxp, - GraphWay way, uint32_t cp) const { + void checkNewCpVersusEdges(V3GraphVertex* vxp, GraphWay way, uint32_t cp) const { // Don't need to check this in the self test; it supports an assert // that runs in production code. } - void setCritPathCost(V3GraphVertex* vxp, - GraphWay way, uint32_t cost) { + void setCritPathCost(V3GraphVertex* vxp, GraphWay way, uint32_t cost) { m_cp[vxp] = cost; // Confirm that we only set each node's CP once. That's an // important property of PartPropagateCp which allows it to be far @@ -327,15 +317,12 @@ private: while (const V3GraphVertex* cvxp = order.nextp()) { V3GraphVertex* vxp = const_cast(cvxp); uint32_t cpCost = 0; - for (V3GraphEdge* edgep = vxp->inBeginp(); - edgep; edgep = edgep->inNextp()) { + for (V3GraphEdge* edgep = vxp->inBeginp(); edgep; edgep = edgep->inNextp()) { V3GraphVertex* parentp = edgep->fromp(); - cpCost = std::max(cpCost, - critPathCost(parentp, GraphWay::FORWARD) + 1); + cpCost = std::max(cpCost, critPathCost(parentp, GraphWay::FORWARD) + 1); } if (checkOnly) { - UASSERT_SELFTEST(uint32_t, cpCost, - critPathCost(vxp, GraphWay::FORWARD)); + UASSERT_SELFTEST(uint32_t, cpCost, critPathCost(vxp, GraphWay::FORWARD)); } else { setCritPathCost(vxp, GraphWay::FORWARD, cpCost); } @@ -345,9 +332,7 @@ private: // Generate a pseudo-random graph vluint64_t rngState[2] = {VL_ULL(0x12345678), VL_ULL(0x9abcdef0)}; // Create 50 vertices - for (unsigned i = 0; i < 50; ++i) { - m_vx[i] = new V3GraphVertex(&m_graph); - } + for (unsigned i = 0; i < 50; ++i) m_vx[i] = new V3GraphVertex(&m_graph); // Create 250 edges at random. Edges must go from // lower-to-higher index vertices, so we get a DAG. for (unsigned i = 0; i < 250; ++i) { @@ -363,8 +348,7 @@ private: partInitCriticalPaths(false); // This SelfTest class is also the T_CostAccessor - PartPropagateCp - prop(&m_graph, GraphWay::FORWARD, this, true); + PartPropagateCp prop(&m_graph, GraphWay::FORWARD, this, true); // Seed the propagator with every input node; // This should result in the complete graph getting all CP's assigned. @@ -384,10 +368,9 @@ private: // Finally, confirm that the entire graph appears to have correct CPs. partInitCriticalPaths(true); } + public: - static void selfTest() { - PartPropagateCpSelfTest().go(); - } + static void selfTest() { PartPropagateCpSelfTest().go(); } }; //###################################################################### @@ -399,7 +382,7 @@ public: typedef std::list VxList; struct CmpLogicMTask { - bool operator() (const LogicMTask* ap, const LogicMTask* bp) const { + bool operator()(const LogicMTask* ap, const LogicMTask* bp) const { return ap->id() < bp->id(); } }; @@ -424,16 +407,15 @@ public: return mtaskp->critPathCost(way); } // Store a new CP to this node - void setCritPathCost(V3GraphVertex* vxp, - GraphWay way, uint32_t cost) const { + void setCritPathCost(V3GraphVertex* vxp, GraphWay way, uint32_t cost) const { LogicMTask* mtaskp = dynamic_cast(vxp); mtaskp->setCritPathCost(way, cost); } // Notify vxp that the wayward CP at the throughp-->vxp edge // has increased to 'cp'. (vxp is wayward from throughp.) // This is our cue to update vxp's m_edges[!way][throughp]. - void notifyEdgeCp(V3GraphVertex* vxp, GraphWay way, - V3GraphVertex* throuvhVxp, uint32_t cp) const { + void notifyEdgeCp(V3GraphVertex* vxp, GraphWay way, V3GraphVertex* throuvhVxp, + uint32_t cp) const { LogicMTask* updateVxp = dynamic_cast(vxp); LogicMTask* lthrouvhVxp = dynamic_cast(throuvhVxp); EdgeSet& edges = updateVxp->m_edges[way.invert()]; @@ -441,8 +423,7 @@ public: if (cp > edgeCp) edges.set(lthrouvhVxp, cp); } // Check that CP matches that of the longest edge wayward of vxp. - void checkNewCpVersusEdges(V3GraphVertex* vxp, - GraphWay way, uint32_t cp) const { + void checkNewCpVersusEdges(V3GraphVertex* vxp, GraphWay way, uint32_t cp) const { LogicMTask* mtaskp = dynamic_cast(vxp); EdgeSet& edges = mtaskp->m_edges[way.invert()]; // This is mtaskp's relative with longest !wayward inclusive CP: @@ -450,6 +431,7 @@ public: uint32_t edgeCp = (*edgeIt).value(); UASSERT_OBJ(edgeCp == cp, vxp, "CP doesn't match longest wayward edge"); } + private: VL_UNCOPYABLE(CpCostAccessor); }; @@ -495,7 +477,7 @@ public: : AbstractLogicMTask(graphp) , m_cost(0) , m_generation(0) { - for (int i=0; ilogicp()) { @@ -514,9 +496,7 @@ public: m_vertices.splice(m_vertices.end(), otherp->m_vertices); m_cost += otherp->m_cost; } - virtual const VxList* vertexListp() const { - return &m_vertices; - } + virtual const VxList* vertexListp() const { return &m_vertices; } static vluint64_t incGeneration() { static vluint64_t s_generation = 0; ++s_generation; @@ -560,9 +540,7 @@ public: EdgeSet& edges = m_edges[way]; UASSERT(!edges.has(relativep), "Adding existing edge"); // value is !way cp to this edge - edges.set(relativep, - relativep->stepCost() - + relativep->critPathCost(way.invert())); + edges.set(relativep, relativep->stepCost() + relativep->critPathCost(way.invert())); } void removeRelative(GraphWay way, LogicMTask* relativep) { EdgeSet& edges = m_edges[way]; @@ -574,13 +552,11 @@ public: } void checkRelativesCp(GraphWay way) const { const EdgeSet& edges = m_edges[way]; - for (EdgeSet::const_reverse_iterator it = edges.rbegin(); - it != edges.rend(); ++it) { + for (EdgeSet::const_reverse_iterator it = edges.rbegin(); it != edges.rend(); ++it) { LogicMTask* relativep = (*it).key(); uint32_t cachedCp = (*it).value(); - partCheckCachedScoreVsActual - (cachedCp, - relativep->critPathCost(way.invert()) + relativep->stepCost()); + partCheckCachedScoreVsActual(cachedCp, relativep->critPathCost(way.invert()) + + relativep->stepCost()); } } @@ -588,29 +564,24 @@ public: // Display forward and reverse critical path costs. This gives a quick // read on whether graph partitioning looks reasonable or bad. std::ostringstream out; - out <<"mt"<furtherp(way), - "In critPathCostWithout(), edge 'withoutp' must " - "further to 'this'"); + UASSERT(this == withoutp->furtherp(way), "In critPathCostWithout(), edge 'withoutp' must " + "further to 'this'"); // Iterate through edges until we get a relative other than // wayEdgeEndp(way, withoutp). This should take 2 iterations max. const EdgeSet& edges = m_edges[way.invert()]; uint32_t result = 0; - for (EdgeSet::const_reverse_iterator it = edges.rbegin(); - it != edges.rend(); ++it) { + for (EdgeSet::const_reverse_iterator it = edges.rbegin(); it != edges.rend(); ++it) { if ((*it).key() != withoutp->furtherp(way.invert())) { // Use the cached cost. It could be a small overestimate // due to stepping. This is consistent with critPathCost() @@ -623,10 +594,8 @@ public: } private: - static bool pathExistsFromInternal(LogicMTask* fromp, - LogicMTask* top, - const V3GraphEdge* excludedEdgep, - vluint64_t generation) { + static bool pathExistsFromInternal(LogicMTask* fromp, LogicMTask* top, + const V3GraphEdge* excludedEdgep, vluint64_t generation) { // Q) Why does this take LogicMTask instead of generic V3GraphVertex? // A) We'll use the critical paths known to LogicMTask to prune the // recursion for speed. Also store 'generation' in @@ -647,17 +616,20 @@ private: // Base case: fromp is too late, cannot possibly be a prereq for top. if (fromp->critPathCost(GraphWay::REVERSE) - < (top->critPathCost(GraphWay::REVERSE) + top->stepCost())) return false; + < (top->critPathCost(GraphWay::REVERSE) + top->stepCost())) { + return false; + } if ((fromp->critPathCost(GraphWay::FORWARD) + fromp->stepCost()) - > top->critPathCost(GraphWay::FORWARD)) return false; + > top->critPathCost(GraphWay::FORWARD)) { + return false; + } // Recursively look for a path - for (const V3GraphEdge* followp = fromp->outBeginp(); - followp; followp = followp->outNextp()) { + for (const V3GraphEdge* followp = fromp->outBeginp(); followp; + followp = followp->outNextp()) { if (followp == excludedEdgep) continue; LogicMTask* nextp = dynamic_cast(followp->top()); - if (pathExistsFromInternal(nextp, top, NULL, generation)) - return true; + if (pathExistsFromInternal(nextp, top, NULL, generation)) return true; } return false; } @@ -671,25 +643,22 @@ private: // TODO: consider changing this API to the 'isTransitiveEdge' API // used by GraphPathChecker public: - static bool pathExistsFrom(LogicMTask* fromp, - LogicMTask* top, + static bool pathExistsFrom(LogicMTask* fromp, LogicMTask* top, const V3GraphEdge* excludedEdgep) { - return pathExistsFromInternal(fromp, top, excludedEdgep, - incGeneration()); + return pathExistsFromInternal(fromp, top, excludedEdgep, incGeneration()); } - static void dumpCpFilePrefixed(const V3Graph* graphp, - const string& nameComment) { - string filename = v3Global.debugFilename(nameComment)+".txt"; - UINFO(1,"Writing "< ofp(V3File::new_ofstream(filename)); std::ostream* osp = &(*ofp); // &* needed to deref unique_ptr - if (osp->fail()) v3fatalStatic("Can't write "<fail()) v3fatalStatic("Can't write " << filename); // Find start vertex with longest CP const LogicMTask* startp = NULL; - for (const V3GraphVertex* vxp = graphp->verticesBeginp(); - vxp; vxp = vxp->verticesNextp()) { + for (const V3GraphVertex* vxp = graphp->verticesBeginp(); vxp; + vxp = vxp->verticesNextp()) { const LogicMTask* mtaskp = dynamic_cast(vxp); if (!startp) { startp = mtaskp; @@ -710,25 +679,28 @@ public: const EdgeSet& children = nextp->m_edges[GraphWay::FORWARD]; EdgeSet::const_reverse_iterator it = children.rbegin(); - if (it == children.rend()) nextp = NULL; - else nextp = (*it).key(); + if (it == children.rend()) { + nextp = NULL; + } else { + nextp = (*it).key(); + } } - *osp<<"totalCost = "<::iterator it = path.begin(); - it != path.end(); ++it) { + for (std::vector::iterator it = path.begin(); it != path.end(); ++it) { const LogicMTask* mtaskp = *it; - *osp<<"begin mtask with cost "<cost()<cost() << endl; for (VxList::const_iterator lit = mtaskp->vertexListp()->begin(); lit != mtaskp->vertexListp()->end(); ++lit) { const OrderLogicVertex* logicp = (*lit)->logicp(); if (!logicp) continue; if (false) { // Show nodes only - *osp<<"> "; logicp->nodep()->dumpTree(*osp); + *osp << "> "; + logicp->nodep()->dumpTree(*osp); } else { // Show nodes with hierarchical costs V3InstrCount::count(logicp->nodep(), false, osp); @@ -751,8 +723,7 @@ class MTaskIdLessThan { public: MTaskIdLessThan() {} virtual ~MTaskIdLessThan() {} - virtual bool operator() (const AbstractMTask* lhsp, - const AbstractMTask* rhsp) const { + virtual bool operator()(const AbstractMTask* lhsp, const AbstractMTask* rhsp) const { return lhsp->id() < rhsp->id(); } }; @@ -764,7 +735,8 @@ private: vluint64_t m_id; // Serial number for ordering public: // CONSTRUCTORS - MergeCandidate() : m_removedFromSb(false) { + MergeCandidate() + : m_removedFromSb(false) { static vluint64_t serial = 0; ++serial; m_id = serial; @@ -773,9 +745,7 @@ public: // METHODS bool removedFromSb() const { return m_removedFromSb; } void removedFromSb(bool removed) { m_removedFromSb = removed; } - bool operator<(const MergeCandidate& other) const { - return m_id < other.m_id; - } + bool operator<(const MergeCandidate& other) const { return m_id < other.m_id; } }; // A pair of associated LogicMTask's that are merge candidates for sibling @@ -786,6 +756,7 @@ private: LogicMTask* m_bp; // CONSTRUCTORS SiblingMC() VL_EQ_DELETE; + public: SiblingMC(LogicMTask* ap, LogicMTask* bp) { // Assign 'ap' and 'bp' in a canonical order, so we can more easily @@ -830,12 +801,8 @@ public: LogicMTask* furtherMTaskp(GraphWay way) const { return dynamic_cast(this->furtherp(way)); } - LogicMTask* fromMTaskp() const { - return dynamic_cast(fromp()); - } - LogicMTask* toMTaskp() const { - return dynamic_cast(top()); - } + LogicMTask* fromMTaskp() const { return dynamic_cast(fromp()); } + LogicMTask* toMTaskp() const { return dynamic_cast(top()); } virtual bool mergeWouldCreateCycle() const { return LogicMTask::pathExistsFrom(fromMTaskp(), toMTaskp(), this); } @@ -856,6 +823,7 @@ public: fromp->addRelative(GraphWay::FORWARD, top); top->addRelative(GraphWay::REVERSE, fromp); } + private: VL_UNCOPYABLE(MTaskEdge); }; @@ -865,9 +833,9 @@ private: class OrderByPtrId { PartPtrIdMap m_ids; + public: - virtual bool operator() (const OrderVarStdVertex* lhsp, - const OrderVarStdVertex* rhsp) const { + virtual bool operator()(const OrderVarStdVertex* lhsp, const OrderVarStdVertex* rhsp) const { vluint64_t l_id = m_ids.findId(lhsp); vluint64_t r_id = m_ids.findId(rhsp); return l_id < r_id; @@ -897,11 +865,11 @@ class PartParallelismEst { public: // CONSTRUCTORS explicit PartParallelismEst(const V3Graph* graphp) - : m_graphp(graphp), - m_totalGraphCost(0), - m_longestCpCost(0), - m_vertexCount(0), - m_edgeCount(0) {} + : m_graphp(graphp) + , m_totalGraphCost(0) + , m_longestCpCost(0) + , m_vertexCount(0) + , m_edgeCount(0) {} // METHODS uint32_t totalGraphCost() const { return m_totalGraphCost; } @@ -916,12 +884,10 @@ public: // of the graph through the end of the node. vl_unordered_map critPaths; GraphStreamUnordered serialize(m_graphp); - for (const V3GraphVertex* vertexp; - (vertexp = serialize.nextp());) { + for (const V3GraphVertex* vertexp; (vertexp = serialize.nextp());) { m_vertexCount++; uint32_t cpCostToHere = 0; - for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; - edgep = edgep->inNextp()) { + for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { ++m_edgeCount; // For each upstream item, add its critical path cost to // the cost of this edge, to form a new candidate critical @@ -940,23 +906,18 @@ public: } } void statsReport(const string& stage) { - V3Stats::addStat("MTask graph, "+stage+", critical path cost", - m_longestCpCost); - V3Stats::addStat("MTask graph, "+stage+", total graph cost", - m_totalGraphCost); - V3Stats::addStat("MTask graph, "+stage+", mtask count", - m_vertexCount); - V3Stats::addStat("MTask graph, "+stage+", edge count", - m_edgeCount); - V3Stats::addStat("MTask graph, "+stage+", parallelism factor", - parallelismFactor()); + V3Stats::addStat("MTask graph, " + stage + ", critical path cost", m_longestCpCost); + V3Stats::addStat("MTask graph, " + stage + ", total graph cost", m_totalGraphCost); + V3Stats::addStat("MTask graph, " + stage + ", mtask count", m_vertexCount); + V3Stats::addStat("MTask graph, " + stage + ", edge count", m_edgeCount); + V3Stats::addStat("MTask graph, " + stage + ", parallelism factor", parallelismFactor()); } void debugReport() { - UINFO(0, " Critical path cost = "<weight() != 0, mtaskp, "Should be no cut edges in mtasks graph"); UASSERT_OBJ(relatives.find(edgep->furtherp(rev)) == relatives.end(), mtaskp, "Should be no redundant edges in mtasks graph"); relatives.insert(edgep->furtherp(rev)); - LogicMTask* relativep - = dynamic_cast(edgep->furtherp(rev)); - cpCost = std::max(cpCost, - (relativep->critPathCost(way) - + static_cast(relativep->stepCost()))); + LogicMTask* relativep = dynamic_cast(edgep->furtherp(rev)); + cpCost = std::max(cpCost, (relativep->critPathCost(way) + + static_cast(relativep->stepCost()))); } if (checkOnly) { partCheckCachedScoreVsActual(mtaskp->critPathCost(way), cpCost); @@ -1011,10 +967,8 @@ static void partInitCriticalPaths(V3Graph* mtasksp) { // Reset all MTaskEdges so that 'm_edges' will show correct CP numbers. // They would have been all zeroes on initial creation of the MTaskEdges. - for (V3GraphVertex* vxp = mtasksp->verticesBeginp(); - vxp; vxp = vxp->verticesNextp()) { - for (V3GraphEdge* edgep = vxp->outBeginp(); - edgep; edgep = edgep->outNextp()) { + for (V3GraphVertex* vxp = mtasksp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) { + for (V3GraphEdge* edgep = vxp->outBeginp(); edgep; edgep = edgep->outNextp()) { MTaskEdge* mtedgep = dynamic_cast(edgep); mtedgep->resetCriticalPaths(); } @@ -1026,8 +980,7 @@ static void partInitCriticalPaths(V3Graph* mtasksp) { static void partCheckCriticalPaths(V3Graph* mtasksp) { partInitHalfCriticalPaths(GraphWay::FORWARD, mtasksp, true); partInitHalfCriticalPaths(GraphWay::REVERSE, mtasksp, true); - for (V3GraphVertex* vxp = mtasksp->verticesBeginp(); - vxp; vxp = vxp->verticesNextp()) { + for (V3GraphVertex* vxp = mtasksp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) { LogicMTask* mtaskp = dynamic_cast(vxp); mtaskp->checkRelativesCp(GraphWay::FORWARD); mtaskp->checkRelativesCp(GraphWay::REVERSE); @@ -1074,22 +1027,18 @@ static V3GraphEdge* partBlastEdgep(GraphWay way, V3GraphEdge* edgep) { // // Another way of stating this: this code ensures that scores of // non-transitive edges only ever increase. -static void partMergeEdgesFrom(V3Graph* mtasksp, LogicMTask* recipientp, - LogicMTask* donorp, +static void partMergeEdgesFrom(V3Graph* mtasksp, LogicMTask* recipientp, LogicMTask* donorp, V3Scoreboard* sbp) { for (unsigned wi = 0; wi < 2; ++wi) { GraphWay way = wi ? GraphWay::REVERSE : GraphWay::FORWARD; - for (V3GraphEdge* edgep = donorp->beginp(way); - edgep; edgep = partBlastEdgep(way, edgep)) { + for (V3GraphEdge* edgep = donorp->beginp(way); edgep; edgep = partBlastEdgep(way, edgep)) { MTaskEdge* tedgep = MTaskEdge::cast(edgep); - if (sbp && !tedgep->removedFromSb()) - sbp->removeElem(tedgep); + if (sbp && !tedgep->removedFromSb()) sbp->removeElem(tedgep); // Existing edge; mark it in need of a rescore if (recipientp->hasRelative(way, tedgep->furtherMTaskp(way))) { if (sbp) { - MTaskEdge* existMTaskEdgep = - MTaskEdge::cast(recipientp->findConnectingEdgep - (way, tedgep->furtherMTaskp(way))); + MTaskEdge* existMTaskEdgep = MTaskEdge::cast( + recipientp->findConnectingEdgep(way, tedgep->furtherMTaskp(way))); UASSERT(existMTaskEdgep, "findConnectingEdge didn't find edge"); if (!existMTaskEdgep->removedFromSb()) { sbp->hintScoreChanged(existMTaskEdgep); @@ -1099,11 +1048,9 @@ static void partMergeEdgesFrom(V3Graph* mtasksp, LogicMTask* recipientp, // No existing edge into *this, make one. MTaskEdge* newEdgep; if (way == GraphWay::REVERSE) { - newEdgep = new MTaskEdge(mtasksp, tedgep->fromMTaskp(), - recipientp, 1); + newEdgep = new MTaskEdge(mtasksp, tedgep->fromMTaskp(), recipientp, 1); } else { - newEdgep = new MTaskEdge(mtasksp, recipientp, - tedgep->toMTaskp(), 1); + newEdgep = new MTaskEdge(mtasksp, recipientp, tedgep->toMTaskp(), 1); } if (sbp) sbp->addElem(newEdgep); } @@ -1151,15 +1098,14 @@ public: , m_scoreLimitBeforeRescore(0xffffffff) , m_mergesSinceRescore(0) , m_slowAsserts(slowAsserts) - , m_sb(&mergeCandidateScore, slowAsserts) { } + , m_sb(&mergeCandidateScore, slowAsserts) {} // METHODS void go() { unsigned maxMTasks = v3Global.opt.threadsMaxMTasks(); if (maxMTasks == 0) { // Unspecified so estimate if (v3Global.opt.threads() > 1) { - maxMTasks = (PART_DEFAULT_MAX_MTASKS_PER_THREAD - * v3Global.opt.threads()); + maxMTasks = (PART_DEFAULT_MAX_MTASKS_PER_THREAD * v3Global.opt.threads()); } else { // Running PartContraction with --threads <= 1 means self-test maxMTasks = 500; @@ -1175,11 +1121,9 @@ public: // - Merge the best pair. // - Incrementally recompute critical paths near the merged mtask. - for (V3GraphVertex* itp = m_mtasksp->verticesBeginp(); itp; - itp = itp->verticesNextp()) { + for (V3GraphVertex* itp = m_mtasksp->verticesBeginp(); itp; itp = itp->verticesNextp()) { vl_unordered_set neighbors; - for (V3GraphEdge* edgep = itp->outBeginp(); edgep; - edgep=edgep->outNextp()) { + for (V3GraphEdge* edgep = itp->outBeginp(); edgep; edgep = edgep->outNextp()) { m_sb.addElem(MTaskEdge::cast(edgep)); UASSERT_OBJ(neighbors.find(edgep->top()) == neighbors.end(), itp, "Redundant edge found in input to PartContraction()"); @@ -1234,17 +1178,18 @@ public: // Except, if we have too many mtasks, raise the score // limit and keep going... unsigned mtaskCount = 0; - for (V3GraphVertex* vxp = m_mtasksp->verticesBeginp(); - vxp; vxp = vxp->verticesNextp()) { + for (V3GraphVertex* vxp = m_mtasksp->verticesBeginp(); vxp; + vxp = vxp->verticesNextp()) { ++mtaskCount; } if (mtaskCount > maxMTasks) { uint32_t oldLimit = m_scoreLimit; m_scoreLimit = (m_scoreLimit * 120) / 100; v3Global.rootp()->fileline()->v3warn( - UNOPTTHREADS, "Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads."); - UINFO(1,"Critical path limit was="<critPathCost(way), mtaskp->critPathCost(way)); } - uint32_t origRelativesCp - = mtaskp->critPathCost(way) + mtaskp->stepCost(); - uint32_t newRelativesCp - = newCp + LogicMTask::stepCost(mtaskp->cost() + otherp->cost()); + uint32_t origRelativesCp = mtaskp->critPathCost(way) + mtaskp->stepCost(); + uint32_t newRelativesCp = newCp + LogicMTask::stepCost(mtaskp->cost() + otherp->cost()); NewCp result; result.cp = newCp; @@ -1336,14 +1277,11 @@ private: } void removeSiblingMCsWith(LogicMTask* mtaskp) { - for (SibpSet::iterator it = m_mtask2sibs[mtaskp].begin(); - it != m_mtask2sibs[mtaskp].end(); ++it) { + for (SibpSet::iterator it = m_mtask2sibs[mtaskp].begin(); it != m_mtask2sibs[mtaskp].end(); + ++it) { const SiblingMC* pairp = *it; - if (!pairp->removedFromSb()) { - m_sb.removeElem(pairp); - } - LogicMTask* otherp = (pairp->bp() == mtaskp) ? - pairp->ap() : pairp->bp(); + if (!pairp->removedFromSb()) { m_sb.removeElem(pairp); } + LogicMTask* otherp = (pairp->bp() == mtaskp) ? pairp->ap() : pairp->bp(); size_t erased = m_mtask2sibs[otherp].erase(pairp); UASSERT_OBJ(erased > 0, otherp, "Expected existing mtask"); erased = m_pairs.erase(*pairp); @@ -1354,8 +1292,8 @@ private: } void contract(MergeCandidate* mergeCanp) { - LogicMTask *top = NULL; - LogicMTask *fromp = NULL; + LogicMTask* top = NULL; + LogicMTask* fromp = NULL; MTaskEdge* mergeEdgep = dynamic_cast(mergeCanp); SiblingMC* mergeSibsp = NULL; if (mergeEdgep) { @@ -1363,8 +1301,7 @@ private: fromp = dynamic_cast(mergeEdgep->fromp()); } else { mergeSibsp = dynamic_cast(mergeCanp); - UASSERT(mergeSibsp, - "Failed to cast mergeCanp to either MTaskEdge or SiblingMC"); + UASSERT(mergeSibsp, "Failed to cast mergeCanp to either MTaskEdge or SiblingMC"); top = mergeSibsp->ap(); fromp = mergeSibsp->bp(); } @@ -1384,7 +1321,8 @@ private: donorp = fromp; recipientp = top; } - VL_DANGLING(fromp); VL_DANGLING(top); // Use donorp and recipientp now instead + VL_DANGLING(fromp); + VL_DANGLING(top); // Use donorp and recipientp now instead // Recursively update forward and reverse CP numbers. // @@ -1394,51 +1332,41 @@ private: // // These 'NewCp' objects carry a bit indicating whether we must // propagate CP for each of the four cases: - NewCp recipientNewCpFwd - = newCp(GraphWay::FORWARD, recipientp, donorp, mergeEdgep); - NewCp donorNewCpFwd - = newCp(GraphWay::FORWARD, donorp, recipientp, mergeEdgep); - NewCp recipientNewCpRev - = newCp(GraphWay::REVERSE, recipientp, donorp, mergeEdgep); - NewCp donorNewCpRev - = newCp(GraphWay::REVERSE, donorp, recipientp, mergeEdgep); + NewCp recipientNewCpFwd = newCp(GraphWay::FORWARD, recipientp, donorp, mergeEdgep); + NewCp donorNewCpFwd = newCp(GraphWay::FORWARD, donorp, recipientp, mergeEdgep); + NewCp recipientNewCpRev = newCp(GraphWay::REVERSE, recipientp, donorp, mergeEdgep); + NewCp donorNewCpRev = newCp(GraphWay::REVERSE, donorp, recipientp, mergeEdgep); if (mergeEdgep) { // Remove and free the connecting edge. Must do this before // propagating CP's below. m_sb.removeElem(mergeCanp); - VL_DO_CLEAR(mergeEdgep->unlinkDelete(), mergeEdgep=NULL); + VL_DO_CLEAR(mergeEdgep->unlinkDelete(), mergeEdgep = NULL); } // This also updates cost and stepCost on recipientp recipientp->moveAllVerticesFrom(donorp); - UINFO(9, "recipient = "<id() - << ", donor = "<id() - << ", mergeEdgep = "< - forwardPropagator(m_mtasksp, GraphWay::FORWARD, &cpAccess, m_slowAsserts); - PartPropagateCp - reversePropagator(m_mtasksp, GraphWay::REVERSE, &cpAccess, m_slowAsserts); + PartPropagateCp forwardPropagator(m_mtasksp, GraphWay::FORWARD, + &cpAccess, m_slowAsserts); + PartPropagateCp reversePropagator(m_mtasksp, GraphWay::REVERSE, + &cpAccess, m_slowAsserts); - recipientp->setCritPathCost(GraphWay::FORWARD, - recipientNewCpFwd.cp); + recipientp->setCritPathCost(GraphWay::FORWARD, recipientNewCpFwd.cp); if (recipientNewCpFwd.propagate) { forwardPropagator.cpHasIncreased(recipientp, recipientNewCpFwd.propagateCp); } - recipientp->setCritPathCost(GraphWay::REVERSE, - recipientNewCpRev.cp); + recipientp->setCritPathCost(GraphWay::REVERSE, recipientNewCpRev.cp); if (recipientNewCpRev.propagate) { reversePropagator.cpHasIncreased(recipientp, recipientNewCpRev.propagateCp); } @@ -1479,16 +1407,14 @@ private: siblingPairFromRelatives(GraphWay::REVERSE, recipientp, true); siblingPairFromRelatives(GraphWay::FORWARD, recipientp, true); unsigned edges = 0; - for (V3GraphEdge* edgep = recipientp->outBeginp(); - edgep; edgep = edgep->outNextp()) { + for (V3GraphEdge* edgep = recipientp->outBeginp(); edgep; edgep = edgep->outNextp()) { LogicMTask* postreqp = dynamic_cast(edgep->top()); siblingPairFromRelatives(GraphWay::REVERSE, postreqp, false); edges++; if (edges > PART_SIBLING_EDGE_LIMIT) break; } edges = 0; - for (V3GraphEdge* edgep = recipientp->inBeginp(); - edgep; edgep = edgep->inNextp()) { + for (V3GraphEdge* edgep = recipientp->inBeginp(); edgep; edgep = edgep->inNextp()) { LogicMTask* prereqp = dynamic_cast(edgep->fromp()); siblingPairFromRelatives(GraphWay::FORWARD, prereqp, false); edges++; @@ -1503,8 +1429,7 @@ private: // behave identically without the caching (just slower) m_sb.rescore(); - UINFO(6, "Did rescore. Merges since previous = " - << m_mergesSinceRescore << endl); + UINFO(6, "Did rescore. Merges since previous = " << m_mergesSinceRescore << endl); m_mergesSinceRescore = 0; m_scoreLimitBeforeRescore = 0xffffffff; @@ -1519,9 +1444,7 @@ private: return 1 + edgeScore(edgep); } const SiblingMC* sibsp = dynamic_cast(pairp); - if (sibsp) { - return siblingScore(sibsp); - } + if (sibsp) { return siblingScore(sibsp); } v3fatalSrc("Failed to cast pairp to either MTaskEdge or SiblingMC in mergeCandidateScore"); return 0; } @@ -1529,12 +1452,11 @@ private: static uint32_t siblingScore(const SiblingMC* sibsp) { LogicMTask* ap = sibsp->ap(); LogicMTask* bp = sibsp->bp(); - uint32_t mergedCpCostFwd = std::max(ap->critPathCost(GraphWay::FORWARD), - bp->critPathCost(GraphWay::FORWARD)); - uint32_t mergedCpCostRev = std::max(ap->critPathCost(GraphWay::REVERSE), - bp->critPathCost(GraphWay::REVERSE)); - return mergedCpCostRev + mergedCpCostFwd - + LogicMTask::stepCost(ap->cost() + bp->cost()); + uint32_t mergedCpCostFwd + = std::max(ap->critPathCost(GraphWay::FORWARD), bp->critPathCost(GraphWay::FORWARD)); + uint32_t mergedCpCostRev + = std::max(ap->critPathCost(GraphWay::REVERSE), bp->critPathCost(GraphWay::REVERSE)); + return mergedCpCostRev + mergedCpCostFwd + LogicMTask::stepCost(ap->cost() + bp->cost()); } static uint32_t edgeScore(const V3GraphEdge* edgep) { @@ -1543,17 +1465,15 @@ private: // critical path running through the merged node.) LogicMTask* top = dynamic_cast(edgep->top()); LogicMTask* fromp = dynamic_cast(edgep->fromp()); - uint32_t mergedCpCostFwd = std::max - (fromp->critPathCost(GraphWay::FORWARD), - top->critPathCostWithout(GraphWay::FORWARD, edgep)); - uint32_t mergedCpCostRev = std::max - (fromp->critPathCostWithout(GraphWay::REVERSE, edgep), - top->critPathCost(GraphWay::REVERSE)); + uint32_t mergedCpCostFwd = std::max(fromp->critPathCost(GraphWay::FORWARD), + top->critPathCostWithout(GraphWay::FORWARD, edgep)); + uint32_t mergedCpCostRev = std::max(fromp->critPathCostWithout(GraphWay::REVERSE, edgep), + top->critPathCost(GraphWay::REVERSE)); return mergedCpCostRev + mergedCpCostFwd - + LogicMTask::stepCost(fromp->cost() + top->cost()); + + LogicMTask::stepCost(fromp->cost() + top->cost()); } - void makeSiblingMC(LogicMTask* ap, LogicMTask *bp) { + void makeSiblingMC(LogicMTask* ap, LogicMTask* bp) { SiblingMC newSibs(ap, bp); std::pair insertResult = m_pairs.insert(newSibs); if (insertResult.second) { @@ -1564,17 +1484,15 @@ private: } else if (m_slowAsserts) { // It's fine if we already have this SiblingMC, we may have // created it earlier. Just confirm that we have associated data. - UASSERT_OBJ(m_mtask2sibs.find(ap) != m_mtask2sibs.end(), ap, - "Sibling not found"); - UASSERT_OBJ(m_mtask2sibs.find(bp) != m_mtask2sibs.end(), bp, - "Sibling not found"); + UASSERT_OBJ(m_mtask2sibs.find(ap) != m_mtask2sibs.end(), ap, "Sibling not found"); + UASSERT_OBJ(m_mtask2sibs.find(bp) != m_mtask2sibs.end(), bp, "Sibling not found"); bool found = false; - for (SibpSet::iterator it = m_mtask2sibs[ap].begin(); - it != m_mtask2sibs[ap].end(); ++it) { + for (SibpSet::iterator it = m_mtask2sibs[ap].begin(); it != m_mtask2sibs[ap].end(); + ++it) { const SiblingMC* sibsp = *it; UASSERT_OBJ(!(!sibsp->removedFromSb() && !m_sb.contains(sibsp)), ap, "One sibling must be the one we collided with"); - if ( (sibsp->ap() == ap && sibsp->bp() == bp) + if ((sibsp->ap() == ap && sibsp->bp() == bp) || (sibsp->bp() == ap && sibsp->ap() == bp)) found = true; } @@ -1585,8 +1503,8 @@ private: static const GraphWay* s_shortestWaywardCpInclusiveWay; static int shortestWaywardCpInclusive(const void* vap, const void* vbp) { const GraphWay* wp = s_shortestWaywardCpInclusiveWay; - const LogicMTask* ap = *reinterpret_cast(vap); - const LogicMTask* bp = *reinterpret_cast(vbp); + const LogicMTask* ap = *reinterpret_cast(vap); + const LogicMTask* bp = *reinterpret_cast(vbp); uint32_t aCp = ap->critPathCost(*wp) + ap->stepCost(); uint32_t bCp = bp->critPathCost(*wp) + bp->stepCost(); if (aCp < bCp) { return -1; } @@ -1596,12 +1514,10 @@ private: return 0; } - void siblingPairFromRelatives(GraphWay way, V3GraphVertex* mtaskp, - bool exhaustive) { + void siblingPairFromRelatives(GraphWay way, V3GraphVertex* mtaskp, bool exhaustive) { std::vector shortestPrereqs; - for (V3GraphEdge* edgep = mtaskp->beginp(way); - edgep; edgep = edgep->nextp(way)) { + for (V3GraphEdge* edgep = mtaskp->beginp(way); edgep; edgep = edgep->nextp(way)) { LogicMTask* prereqp = dynamic_cast(edgep->furtherp(way)); shortestPrereqs.push_back(prereqp); // Prevent nodes with huge numbers of edges from massively @@ -1613,8 +1529,8 @@ private: // qsort_r would be nice here, but it isn't portable s_shortestWaywardCpInclusiveWay = &way; - qsort(&shortestPrereqs[0], shortestPrereqs.size(), - sizeof(LogicMTask*), &shortestWaywardCpInclusive); + qsort(&shortestPrereqs[0], shortestPrereqs.size(), sizeof(LogicMTask*), + &shortestWaywardCpInclusive); // Don't make all NxN/2 possible pairs of prereqs, that's a lot // to cart around. Just make a few pairs. @@ -1642,7 +1558,7 @@ private: // or worse which would suggest N^2 scaling or worse. UASSERT(usecsLarge < (usecsSmall * 1500), "selfTestChain() took longer than expected. Small input runtime = " - <setCost(1); unsigned i; - for (i=0; i<50; ++i) { + for (i = 0; i < 50; ++i) { LogicMTask* mtp = new LogicMTask(&mtasks, NULL); mtp->setCost(1); // Edge from every input -> center new MTaskEdge(&mtasks, mtp, center, 1); } - for (i=0; i<50; ++i) { + for (i = 0; i < 50; ++i) { LogicMTask* mtp = new LogicMTask(&mtasks, NULL); mtp->setCost(1); // Edge from center -> every output @@ -1728,7 +1641,7 @@ private: // Checking exact values here is maybe overly precise. What we're // mostly looking for is a healthy reduction in the number of // mtasks. - if (debug()>=5) { + if (debug() >= 5) { UINFO(0, "X self test stats:\n"); check.debugReport(); } @@ -1737,6 +1650,7 @@ private: UASSERT_SELFTEST(uint32_t, check.vertexCount(), 14); UASSERT_SELFTEST(uint32_t, check.edgeCount(), 13); } + public: static void selfTest() { selfTestX(); @@ -1767,7 +1681,7 @@ private: m_tracingCall = false; if (nodep->dpiImportWrapper()) { if (nodep->pure() ? !v3Global.opt.threadsDpiPure() - : !v3Global.opt.threadsDpiUnpure()) { + : !v3Global.opt.threadsDpiUnpure()) { m_hasDpiHazard = true; } } @@ -1883,7 +1797,7 @@ class PartFixDataHazards { private: // TYPES typedef std::set LogicMTaskSet; - typedef std::map TasksByRank; + typedef std::map TasksByRank; typedef std::set OvvSet; typedef vl_unordered_map Olv2MTaskMap; @@ -1894,46 +1808,41 @@ private: public: // CONSTRUCTORs explicit PartFixDataHazards(V3Graph* mtasksp) - : m_mtasksp(mtasksp), m_mergesDone(0) {} + : m_mtasksp(mtasksp) + , m_mergesDone(0) {} // METHODS private: void findAdjacentTasks(OvvSet::iterator ovvIt, TasksByRank* tasksByRankp) { // Find all writer tasks for this variable, group by rank. - for (V3GraphEdge* edgep = (*ovvIt)->inBeginp(); - edgep; edgep = edgep->inNextp()) { + for (V3GraphEdge* edgep = (*ovvIt)->inBeginp(); edgep; edgep = edgep->inNextp()) { OrderLogicVertex* logicp = dynamic_cast(edgep->fromp()); if (!logicp) continue; - if (logicp->domainp()->hasInitial() - || logicp->domainp()->hasSettle()) continue; + if (logicp->domainp()->hasInitial() || logicp->domainp()->hasSettle()) continue; LogicMTask* writerMtaskp = m_olv2mtask.at(logicp); (*tasksByRankp)[writerMtaskp->rank()].insert(writerMtaskp); } // Find all reader tasks for this variable, group by rank. - for (V3GraphEdge* edgep = (*ovvIt)->outBeginp(); - edgep; edgep = edgep->outNextp()) { + for (V3GraphEdge* edgep = (*ovvIt)->outBeginp(); edgep; edgep = edgep->outNextp()) { OrderLogicVertex* logicp = dynamic_cast(edgep->fromp()); if (!logicp) continue; - if (logicp->domainp()->hasInitial() - || logicp->domainp()->hasSettle()) continue; + if (logicp->domainp()->hasInitial() || logicp->domainp()->hasSettle()) continue; LogicMTask* readerMtaskp = m_olv2mtask.at(logicp); (*tasksByRankp)[readerMtaskp->rank()].insert(readerMtaskp); } } void mergeSameRankTasks(TasksByRank* tasksByRankp) { LogicMTask* lastMergedp = NULL; - for (TasksByRank::iterator rankIt = tasksByRankp->begin(); - rankIt != tasksByRankp->end(); ++rankIt) { + for (TasksByRank::iterator rankIt = tasksByRankp->begin(); rankIt != tasksByRankp->end(); + ++rankIt) { // Find the largest node at this rank, merge into it. (If we // happen to find a huge node, this saves time in // partMergeEdgesFrom() versus merging into an arbitrary node.) LogicMTask* mergedp = NULL; - for (LogicMTaskSet::iterator it = rankIt->second.begin(); - it != rankIt->second.end(); ++it) { + for (LogicMTaskSet::iterator it = rankIt->second.begin(); it != rankIt->second.end(); + ++it) { LogicMTask* mtaskp = *it; if (mergedp) { - if (mergedp->cost() < mtaskp->cost()) { - mergedp = mtaskp; - } + if (mergedp->cost() < mtaskp->cost()) { mergedp = mtaskp; } } else { mergedp = mtaskp; } @@ -1947,8 +1856,7 @@ private: rankIt->second.erase(begin); // Merge donorp into mergedp. // Fix up the map, so donor's OLVs map to mergedp - for (LogicMTask::VxList::const_iterator tmvit = - donorp->vertexListp()->begin(); + for (LogicMTask::VxList::const_iterator tmvit = donorp->vertexListp()->begin(); tmvit != donorp->vertexListp()->end(); ++tmvit) { MTaskMoveVertex* tmvp = *tmvit; OrderLogicVertex* logicp = tmvp->logicp(); @@ -1986,12 +1894,13 @@ private: // Find all calls to DPI-imported functions, we can put those // into a serial order at least. That should solve the most // likely DPI-related data hazards. - if (DpiImportCallVisitor(nodep).hasDpiHazard()) { + if (DpiImportCallVisitor(nodep).hasDpiHazard()) { // return true; } } return false; } + public: void go() { vluint64_t startUsecs = 0; @@ -2003,24 +1912,21 @@ public: // OVV's which wrap systemC vars will be handled slightly specially OvvSet ovvSetSystemC(ovvOrder); - for (V3GraphVertex* vxp = m_mtasksp->verticesBeginp(); - vxp; vxp = vxp->verticesNextp()) { + for (V3GraphVertex* vxp = m_mtasksp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) { LogicMTask* mtaskp = dynamic_cast(vxp); // Should be only one MTaskMoveVertex in each mtask at this // stage, but whatever, write it as a loop: - for (LogicMTask::VxList::const_iterator it - = mtaskp->vertexListp()->begin(); + for (LogicMTask::VxList::const_iterator it = mtaskp->vertexListp()->begin(); it != mtaskp->vertexListp()->end(); ++it) { MTaskMoveVertex* tmvp = *it; if (OrderLogicVertex* logicp = tmvp->logicp()) { m_olv2mtask[logicp] = mtaskp; // Look at downstream vars. - for (V3GraphEdge *edgep = logicp->outBeginp(); - edgep; edgep = edgep->outNextp()) { + for (V3GraphEdge* edgep = logicp->outBeginp(); edgep; + edgep = edgep->outNextp()) { // Only consider OrderVarStdVertex which reflects // an actual lvalue assignment; the others do not. - OrderVarStdVertex* ovvp - = dynamic_cast(edgep->top()); + OrderVarStdVertex* ovvp = dynamic_cast(edgep->top()); if (!ovvp) continue; if (ovvp->varScp()->varp()->isSc()) { ovvSetSystemC.insert(ovvp); @@ -2042,8 +1948,7 @@ public: const V3GraphVertex* vertexp; while ((vertexp = serialize.nextp())) { uint32_t rank = 0; - for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; - edgep = edgep->inNextp()) { + for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { rank = std::max(edgep->fromp()->rank() + 1, rank); } const_cast(vertexp)->rank(rank); @@ -2063,8 +1968,7 @@ public: // NOTE: we don't update the CP's stored in the LogicMTasks to // reflect the changes we make to the graph. That's OK, as we // haven't yet initialized CPs when we call this routine. - for (OvvSet::iterator ovvit = ovvSet.begin(); - ovvit != ovvSet.end(); ++ovvit) { + for (OvvSet::iterator ovvit = ovvSet.begin(); ovvit != ovvSet.end(); ++ovvit) { // Build a set of mtasks, per rank, which access this var. // Within a rank, sort by MTaskID to avoid nondeterminism. TasksByRank tasksByRank; @@ -2104,8 +2008,8 @@ public: // Hopefully we only have a few SC vars -- top level ports, probably. { TasksByRank tasksByRank; - for (OvvSet::iterator ovvit = ovvSetSystemC.begin(); - ovvit != ovvSetSystemC.end(); ++ovvit) { + for (OvvSet::iterator ovvit = ovvSetSystemC.begin(); ovvit != ovvSetSystemC.end(); + ++ovvit) { findAdjacentTasks(ovvit, &tasksByRank); } mergeSameRankTasks(&tasksByRank); @@ -2116,19 +2020,17 @@ public: // Same basic strategy as above to serialize access to SC vars. if (!v3Global.opt.threadsDpiPure() || !v3Global.opt.threadsDpiUnpure()) { TasksByRank tasksByRank; - for (V3GraphVertex* vxp = m_mtasksp->verticesBeginp(); - vxp; vxp = vxp->verticesNextp()) { + for (V3GraphVertex* vxp = m_mtasksp->verticesBeginp(); vxp; + vxp = vxp->verticesNextp()) { LogicMTask* mtaskp = dynamic_cast(vxp); - if (hasDpiHazard(mtaskp)) { - tasksByRank[vxp->rank()].insert(mtaskp); - } + if (hasDpiHazard(mtaskp)) { tasksByRank[vxp->rank()].insert(mtaskp); } } mergeSameRankTasks(&tasksByRank); } - UINFO(4, "PartFixDataHazards() merged "<id() < bp->id(); - } + bool operator()(const ExecMTask* ap, ExecMTask* bp) const { return ap->id() < bp->id(); } }; // MEMBERS @@ -2187,10 +2086,8 @@ private: public: // CONSTRUCTORS - explicit PartPackMTasks(V3Graph* mtasksp, - uint32_t nThreads = v3Global.opt.threads(), - unsigned sandbagNumerator = 30, - unsigned sandbagDenom = 100) + explicit PartPackMTasks(V3Graph* mtasksp, uint32_t nThreads = v3Global.opt.threads(), + unsigned sandbagNumerator = 30, unsigned sandbagDenom = 100) : m_mtasksp(mtasksp) , m_nThreads(nThreads) , m_sandbagNumerator(sandbagNumerator) @@ -2209,24 +2106,22 @@ public: // Add some padding to the estimated runtime when looking from // another thread - uint32_t sandbaggedEndTime = state.completionTime - + (m_sandbagNumerator * mtaskp->cost()) / m_sandbagDenom; + uint32_t sandbaggedEndTime + = state.completionTime + (m_sandbagNumerator * mtaskp->cost()) / m_sandbagDenom; // If task B is packed after task A on thread 0, don't let thread 1 // think that A finishes later than thread 0 thinks that B // finishes, otherwise we get priority inversions and fail the self // test. if (mtaskp->packNextp()) { - uint32_t successorEndTime - = completionTime(mtaskp->packNextp(), mtaskp->thread()); - if ((sandbaggedEndTime >= successorEndTime) - && (successorEndTime > 1)) { + uint32_t successorEndTime = completionTime(mtaskp->packNextp(), mtaskp->thread()); + if ((sandbaggedEndTime >= successorEndTime) && (successorEndTime > 1)) { sandbaggedEndTime = successorEndTime - 1; } } - UINFO(6, "Sandbagged end time for "<name() - <<" on th "<name() << " on th " << thread << " = " + << sandbaggedEndTime << endl); return sandbaggedEndTime; } @@ -2237,8 +2132,7 @@ public: void go() { // Build initial ready list - for (V3GraphVertex* vxp = m_mtasksp->verticesBeginp(); - vxp; vxp = vxp->verticesNextp()) { + for (V3GraphVertex* vxp = m_mtasksp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) { ExecMTask* mtaskp = dynamic_cast(vxp); if (vxp->inEmpty()) m_ready.insert(mtaskp); } @@ -2255,28 +2149,23 @@ public: uint32_t bestTh = 0; ExecMTask* bestMtaskp = NULL; for (uint32_t th = 0; th < m_nThreads; ++th) { - for (ReadyMTasks::iterator taskIt = m_ready.begin(); - taskIt != m_ready.end(); ++taskIt) { + for (ReadyMTasks::iterator taskIt = m_ready.begin(); taskIt != m_ready.end(); + ++taskIt) { uint32_t timeBegin = m_busyUntil[th]; if (timeBegin > bestTime) { - UINFO(6, "th "<inBeginp(); - edgep; edgep = edgep->inNextp()) { - ExecMTask* priorp - = dynamic_cast(edgep->fromp()); + for (V3GraphEdge* edgep = taskp->inBeginp(); edgep; edgep = edgep->inNextp()) { + ExecMTask* priorp = dynamic_cast(edgep->fromp()); uint32_t priorEndTime = completionTime(priorp, th); - if (priorEndTime > timeBegin) { - timeBegin = priorEndTime; - } + if (priorEndTime > timeBegin) timeBegin = priorEndTime; } - UINFO(6, "Task "<name() - <<" start at "<name() << " start at " << timeBegin << " on thread " + << th << endl); if ((timeBegin < bestTime) || ((timeBegin == bestTime) && bestMtaskp // Redundant, but appeases static analysis tools @@ -2289,16 +2178,15 @@ public: } if (!bestMtaskp) v3fatalSrc("Should have found some task"); - UINFO(6, "Will schedule "<name() - <<" onto thread "<name() << " onto thread " << bestTh << endl); uint32_t bestEndTime = bestTime + bestMtaskp->cost(); setCompletionTime(bestMtaskp, bestEndTime); // Update the ready list size_t erased = m_ready.erase(bestMtaskp); UASSERT_OBJ(erased > 0, bestMtaskp, "Should have erased something?"); - for (V3GraphEdge* edgeOutp = bestMtaskp->outBeginp(); - edgeOutp; edgeOutp = edgeOutp->outNextp()) { + for (V3GraphEdge* edgeOutp = bestMtaskp->outBeginp(); edgeOutp; + edgeOutp = edgeOutp->outNextp()) { ExecMTask* nextp = dynamic_cast(edgeOutp->top()); UASSERT(nextp->thread() == 0xffffffff, @@ -2308,8 +2196,8 @@ public: UASSERT_OBJ(m_ready.find(nextp) == m_ready.end(), nextp, "Tasks after one being assigned should not be ready"); bool isReady = true; - for (V3GraphEdge* edgeInp = nextp->inBeginp(); - edgeInp; edgeInp = edgeInp->inNextp()) { + for (V3GraphEdge* edgeInp = nextp->inBeginp(); edgeInp; + edgeInp = edgeInp->inNextp()) { ExecMTask* priorp = dynamic_cast(edgeInp->fromp()); if (priorp == bestMtaskp) continue; if (priorp->thread() == 0xffffffff) { @@ -2319,17 +2207,17 @@ public: } if (isReady) { m_ready.insert(nextp); - UINFO(6, "Inserted "<name()<<" into ready\n"); + UINFO(6, "Inserted " << nextp->name() << " into ready\n"); } } // Update the ExecMTask itself if (m_prevMTask[bestTh]) { m_prevMTask[bestTh]->packNextp(bestMtaskp); - UINFO(6, "Packing "<name() - <<" after "<name()<name() << " after " + << m_prevMTask[bestTh]->name() << endl); } else { - UINFO(6, "Marking "<name()<<" as thread root\n"); + UINFO(6, "Marking " << bestMtaskp->name() << " as thread root\n"); bestMtaskp->threadRoot(true); } bestMtaskp->thread(bestTh); @@ -2402,10 +2290,11 @@ void V3Partition::debugMTaskGraphStats(const V3Graph* graphp, const string& stag if (!debug()) return; UINFO(4, "\n"); - UINFO(4, " Stats for "<verticesBeginp(); mtaskp; mtaskp = mtaskp->verticesNextp()) { @@ -2418,19 +2307,17 @@ void V3Partition::debugMTaskGraphStats(const V3Graph* graphp, const string& stag UASSERT(log2Cost < 32, "log2Cost overflow in debugMTaskGraphStats"); ++mtaskCostHist[log2Cost]; } - UINFO(4, " Total mtask cost = "< 0) ? cvtToStr(totalCost / mtaskCount) : "INF!") << "\n"); UINFO(4, " Histogram of mtask costs:\n"); for (unsigned i = 0; i < 32; ++i) { if (mtaskCostHist[i]) { - UINFO(4, " 2^"<=4) { + if (debug() >= 4) { UINFO(0, "\n"); UINFO(0, " Parallelism estimate for based on mtask costs:\n"); vertexParEst.debugReport(); @@ -2462,27 +2349,22 @@ void V3Partition::hashGraphDebug(const V3Graph* graphp, const char* debugName) { vl_unordered_map vx2Id; unsigned id = 0; - for (const V3GraphVertex* vxp = graphp->verticesBeginp(); - vxp; vxp = vxp->verticesNextp()) { + for (const V3GraphVertex* vxp = graphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) { vx2Id[vxp] = id++; } unsigned hash = 0; - for (const V3GraphVertex* vxp = graphp->verticesBeginp(); - vxp; vxp = vxp->verticesNextp()) { - for (const V3GraphEdge* edgep = vxp->outBeginp(); - edgep; edgep= edgep->outNextp()) { + for (const V3GraphVertex* vxp = graphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) { + for (const V3GraphEdge* edgep = vxp->outBeginp(); edgep; edgep = edgep->outNextp()) { const V3GraphVertex* top = edgep->top(); hash = vx2Id[top] + 31u * hash; // The K&R hash function } } - UINFO(0, "Hash of shape (not contents) of "<(outp->top()); + const MTaskMoveVertex* top = dynamic_cast(outp->top()); UASSERT(top, "MoveVertex not associated to mtask"); Vx2MTaskMap::const_iterator it = vx2mtaskp->find(top); UASSERT(it != vx2mtaskp->end(), "MTask map can't find id"); @@ -2503,7 +2383,7 @@ void V3Partition::setupMTaskDeps(V3Graph* mtasksp, const Vx2MTaskMap* vx2mtaskp) UASSERT_OBJ(otherMTaskp != mtaskp, mtaskp, "Would create a cycle edge"); // Don't create redundant edges. - if (mtaskp->hasRelative(GraphWay::FORWARD, otherMTaskp)) { + if (mtaskp->hasRelative(GraphWay::FORWARD, otherMTaskp)) { // continue; } new MTaskEdge(mtasksp, mtaskp, otherMTaskp, 1); @@ -2526,8 +2406,8 @@ void V3Partition::go(V3Graph* mtasksp) { // node, to assert that we never count any node twice. AstUser5InUse inUser5; Vx2MTaskMap vx2mtask; - for (V3GraphVertex* vxp = m_fineDepsGraphp->verticesBeginp(); - vxp; vxp = vxp->verticesNextp()) { + for (V3GraphVertex* vxp = m_fineDepsGraphp->verticesBeginp(); vxp; + vxp = vxp->verticesNextp()) { MTaskMoveVertex* mtmvVxp = dynamic_cast(vxp); UASSERT_OBJ(mtmvVxp, vxp, "Every vertex here should be an MTaskMoveVertex"); @@ -2575,9 +2455,7 @@ void V3Partition::go(V3Graph* mtasksp) { mtasksp->orderPreRanked(); int targetParFactor = v3Global.opt.threads(); - if (targetParFactor < 2) { - v3fatalSrc("We should not reach V3Partition when --threads <= 1"); - } + if (targetParFactor < 2) { v3fatalSrc("We should not reach V3Partition when --threads <= 1"); } // Set cpLimit to roughly totalGraphCost / nThreads // @@ -2586,9 +2464,8 @@ void V3Partition::go(V3Graph* mtasksp) { // when scheduling them. unsigned fudgeNumerator = 3; unsigned fudgeDenominator = 5; - uint32_t cpLimit = ((totalGraphCost * fudgeNumerator) - / (targetParFactor * fudgeDenominator)); - UINFO(4, "V3Partition set cpLimit = "< SortedMTaskSet; SortedMTaskSet sorted; - for (V3GraphVertex* itp = mtasksp->verticesBeginp(); itp; - itp = itp->verticesNextp()) { + for (V3GraphVertex* itp = mtasksp->verticesBeginp(); itp; itp = itp->verticesNextp()) { LogicMTask* mtaskp = dynamic_cast(itp); sorted.insert(mtaskp); } uint32_t nextId = 1; - for (SortedMTaskSet::iterator it = sorted.begin(); - it != sorted.end(); ++it) { + for (SortedMTaskSet::iterator it = sorted.begin(); it != sorted.end(); ++it) { // We shouldn't perturb the sort order of the set, despite // changing the IDs, they should all just remain in the same // relative order. Confirm that: UASSERT(nextId <= (*it)->id(), "Should only shrink MTaskIDs here"); - UINFO(4, "Reassigning MTask id " << (*it)->id() - << " to id " << nextId << "\n"); + UINFO(4, "Reassigning MTask id " << (*it)->id() << " to id " << nextId << "\n"); (*it)->id(nextId); nextId++; } } // Set color to indicate an mtaskId on every underlying MTaskMoveVertex. - for (V3GraphVertex* itp = mtasksp->verticesBeginp(); itp; - itp = itp->verticesNextp()) { + for (V3GraphVertex* itp = mtasksp->verticesBeginp(); itp; itp = itp->verticesNextp()) { LogicMTask* mtaskp = dynamic_cast(itp); - for (LogicMTask::VxList::const_iterator it - = mtaskp->vertexListp()->begin(); + for (LogicMTask::VxList::const_iterator it = mtaskp->vertexListp()->begin(); it != mtaskp->vertexListp()->end(); ++it) { MTaskMoveVertex* mvertexp = *it; mvertexp->color(mtaskp->id()); @@ -2661,8 +2534,7 @@ void V3Partition::finalizeCosts(V3Graph* execMTaskGraphp) { // choice among several ready mtasks, we'll want to start the // highest priority one first, so we're always working on the "long // pole" - for (V3GraphEdge* edgep = mtp->outBeginp(); - edgep; edgep = edgep->outNextp()) { + for (V3GraphEdge* edgep = mtp->outBeginp(); edgep; edgep = edgep->outNextp()) { ExecMTask* followp = dynamic_cast(edgep->top()); if ((followp->priority() + mtp->cost()) > mtp->priority()) { mtp->priority(followp->priority() + mtp->cost()); @@ -2673,7 +2545,7 @@ void V3Partition::finalizeCosts(V3Graph* execMTaskGraphp) { // Some MTasks may now have zero cost, eliminate those. // (It's common for tasks to shrink to nothing when V3LifePost // removes dly assignments.) - for (V3GraphVertex* vxp = execMTaskGraphp->verticesBeginp(); vxp; ) { + for (V3GraphVertex* vxp = execMTaskGraphp->verticesBeginp(); vxp;) { ExecMTask* mtp = dynamic_cast(vxp); vxp = vxp->verticesNextp(); // Advance before delete @@ -2682,13 +2554,10 @@ void V3Partition::finalizeCosts(V3Graph* execMTaskGraphp) { // the MTaskBody to see if it's empty. That's the source of truth. AstMTaskBody* bodyp = mtp->bodyp(); if (!bodyp->stmtsp()) { // Kill this empty mtask - UINFO(6, "Removing zero-cost "<name()<inBeginp(); - inp; inp = inp->inNextp()) { - for (V3GraphEdge* outp = mtp->outBeginp(); - outp; outp = outp->outNextp()) { - new V3GraphEdge(execMTaskGraphp, inp->fromp(), - outp->top(), 1); + UINFO(6, "Removing zero-cost " << mtp->name() << endl); + for (V3GraphEdge* inp = mtp->inBeginp(); inp; inp = inp->inNextp()) { + for (V3GraphEdge* outp = mtp->outBeginp(); outp; outp = outp->outNextp()) { + new V3GraphEdge(execMTaskGraphp, inp->fromp(), outp->top(), 1); } } VL_DO_DANGLING(mtp->unlinkDelete(execMTaskGraphp), mtp); @@ -2703,8 +2572,7 @@ void V3Partition::finalizeCosts(V3Graph* execMTaskGraphp) { // tasks, which could be transitive. Prune out all transitive edges. { execMTaskGraphp->removeTransitiveEdges(); - V3Partition::debugMTaskGraphStats(execMTaskGraphp, - "transitive2"); + V3Partition::debugMTaskGraphStats(execMTaskGraphp, "transitive2"); } // Record summary stats for final m_tasks graph. @@ -2713,7 +2581,7 @@ void V3Partition::finalizeCosts(V3Graph* execMTaskGraphp) { parEst.traverse(); parEst.statsReport("final"); if (debug() >= 3) { - UINFO(0," Final mtask parallelism report:\n"); + UINFO(0, " Final mtask parallelism report:\n"); parEst.debugReport(); } } diff --git a/src/V3PreLex.l b/src/V3PreLex.l index c75bf8844..443a199f7 100644 --- a/src/V3PreLex.l +++ b/src/V3PreLex.l @@ -353,7 +353,7 @@ size_t V3PreLex::inputToLex(char* buf, size_t max_size) { // become a stale invalid pointer. // VPreStream* streamp = curStreamp(); - if (debug()>=10) { + if (debug() >= 10) { cout<<"- pp:inputToLex ITL s="<= 10) { cout<<"- pp::inputToLex got="< m_args; // List of define arguments public: @@ -78,7 +81,9 @@ public: void parenLevel(int value) { m_parenLevel = value; } std::vector& args() { return m_args; } VDefineRef(const string& name, const string& params) - : m_name(name), m_params(params), m_parenLevel(0) {} + : m_name(name) + , m_params(params) + , m_parenLevel(0) {} ~VDefineRef() {} }; @@ -87,13 +92,14 @@ public: class VPreIfEntry { // One for each pending ifdef/ifndef - bool m_on; // Current parse for this ifdef level is "on" - bool m_everOn; // Some if term in elsif tree has been on + bool m_on; // Current parse for this ifdef level is "on" + bool m_everOn; // Some if term in elsif tree has been on public: bool on() const { return m_on; } bool everOn() const { return m_everOn; } VPreIfEntry(bool on, bool everOn) - : m_on(on), m_everOn(everOn || on) {} // Note everOn includes new state + : m_on(on) + , m_everOn(everOn || on) {} // Note everOn includes new state ~VPreIfEntry() {} }; @@ -103,7 +109,7 @@ public: class V3PreProcImp : public V3PreProc { public: // TYPES - typedef std::map DefinesMap; + typedef std::map DefinesMap; typedef VInFilter::StrList StrList; // debug() -> see V3PreShellImp::debug; use --debugi-V3PreShell @@ -118,58 +124,67 @@ public: int m_lastLineno; // Last line number (stall detection) int m_tokensOnLine; // Number of tokens on line (stall detection) - enum ProcState { ps_TOP, - ps_DEFNAME_UNDEF, ps_DEFNAME_DEFINE, - ps_DEFNAME_IFDEF, ps_DEFNAME_IFNDEF, ps_DEFNAME_ELSIF, - ps_DEFFORM, ps_DEFVALUE, ps_DEFPAREN, ps_DEFARG, - ps_INCNAME, ps_ERRORNAME, ps_JOIN, ps_STRIFY }; + enum ProcState { + ps_TOP, + ps_DEFNAME_UNDEF, + ps_DEFNAME_DEFINE, + ps_DEFNAME_IFDEF, + ps_DEFNAME_IFNDEF, + ps_DEFNAME_ELSIF, + ps_DEFFORM, + ps_DEFVALUE, + ps_DEFPAREN, + ps_DEFARG, + ps_INCNAME, + ps_ERRORNAME, + ps_JOIN, + ps_STRIFY + }; static const char* procStateName(ProcState s) { static const char* states[] - = {"ps_TOP", - "ps_DEFNAME_UNDEF", "ps_DEFNAME_DEFINE", + = {"ps_TOP", "ps_DEFNAME_UNDEF", "ps_DEFNAME_DEFINE", "ps_DEFNAME_IFDEF", "ps_DEFNAME_IFNDEF", "ps_DEFNAME_ELSIF", - "ps_DEFFORM", "ps_DEFVALUE", "ps_DEFPAREN", "ps_DEFARG", - "ps_INCNAME", "ps_ERRORNAME", "ps_JOIN", "ps_STRIFY"}; + "ps_DEFFORM", "ps_DEFVALUE", "ps_DEFPAREN", + "ps_DEFARG", "ps_INCNAME", "ps_ERRORNAME", + "ps_JOIN", "ps_STRIFY"}; return states[s]; } std::stack m_states; ///< Current state of parser - int m_off; ///< If non-zero, ifdef level is turned off, don't dump text - bool m_incError; ///< Include error found - string m_lastSym; ///< Last symbol name found. - string m_formals; ///< Last formals found + int m_off; ///< If non-zero, ifdef level is turned off, don't dump text + bool m_incError; ///< Include error found + string m_lastSym; ///< Last symbol name found. + string m_formals; ///< Last formals found // For getRawToken/ `line insertion - string m_lineCmt; ///< Line comment(s) to be returned - bool m_lineCmtNl; ///< Newline needed before inserting lineCmt - int m_lineAdd; ///< Empty lines to return to maintain line count - bool m_rawAtBol; ///< Last rawToken left us at beginning of line + string m_lineCmt; ///< Line comment(s) to be returned + bool m_lineCmtNl; ///< Newline needed before inserting lineCmt + int m_lineAdd; ///< Empty lines to return to maintain line count + bool m_rawAtBol; ///< Last rawToken left us at beginning of line // For getFinalToken - bool m_finAhead; ///< Have read a token ahead - int m_finToken; ///< Last token read - string m_finBuf; ///< Last yytext read - bool m_finAtBol; ///< Last getFinalToken left us at beginning of line - FileLine* m_finFilelinep; ///< Location of last returned token (internal only) + bool m_finAhead; ///< Have read a token ahead + int m_finToken; ///< Last token read + string m_finBuf; ///< Last yytext read + bool m_finAtBol; ///< Last getFinalToken left us at beginning of line + FileLine* m_finFilelinep; ///< Location of last returned token (internal only) // For stringification - string m_strify; ///< Text to be stringified + string m_strify; ///< Text to be stringified // For defines std::stack m_defRefs; ///< Pending define substitution - std::stack m_ifdefStack; ///< Stack of true/false emitting evaluations - unsigned m_defDepth; ///< How many `defines deep - bool m_defPutJoin; ///< Insert `` after substitution + std::stack m_ifdefStack; ///< Stack of true/false emitting evaluations + unsigned m_defDepth; ///< How many `defines deep + bool m_defPutJoin; ///< Insert `` after substitution // For `` join std::stack m_joinStack; ///< Text on lhs of join // For getline() - string m_lineChars; ///< Characters left for next line + string m_lineChars; ///< Characters left for next line - void v3errorEnd(std::ostringstream& str) { - fileline()->v3errorEnd(str); - } + void v3errorEnd(std::ostringstream& str) { fileline()->v3errorEnd(str); } static const char* tokenName(int tok); void debugToken(int tok, const char* cmtp); @@ -194,7 +209,7 @@ private: void parsingOn() { m_off--; - if (m_off<0) fatalSrc("Underflow of parsing cmds"); + if (m_off < 0) fatalSrc("Underflow of parsing cmds"); // addLineComment no longer needed; getFinalToken will correct. } void parsingOff() { m_off++; } @@ -205,15 +220,11 @@ private: ProcState state() const { return m_states.top(); } bool stateIsDefname() const { - return state()==ps_DEFNAME_UNDEF - || state()==ps_DEFNAME_DEFINE - || state()==ps_DEFNAME_IFDEF - || state()==ps_DEFNAME_IFNDEF - || state()==ps_DEFNAME_ELSIF; - } - void statePush(ProcState state) { - m_states.push(state); + return state() == ps_DEFNAME_UNDEF || state() == ps_DEFNAME_DEFINE + || state() == ps_DEFNAME_IFDEF || state() == ps_DEFNAME_IFNDEF + || state() == ps_DEFNAME_ELSIF; } + void statePush(ProcState state) { m_states.push(state); } void statePop() { m_states.pop(); if (VL_UNCOVERABLE(m_states.empty())) { @@ -222,7 +233,8 @@ private: } } void stateChange(ProcState state) { - statePop(); statePush(state); + statePop(); + statePush(state); } public: @@ -278,7 +290,7 @@ public: m_lexp->m_keepComments = m_preprocp->keepComments(); m_lexp->m_keepWhitespace = m_preprocp->keepWhitespace(); m_lexp->m_pedantic = m_preprocp->pedantic(); - m_lexp->debug(debug()>=5 ? debug() : 0); // See also V3PreProc::debug() method + m_lexp->debug(debug() >= 5 ? debug() : 0); // See also V3PreProc::debug() method } ~V3PreProcImp() { if (m_lexp) VL_DO_CLEAR(delete m_lexp, m_lexp = NULL); @@ -297,12 +309,11 @@ V3PreProc* V3PreProc::createPreProc(FileLine* fl) { //************************************************************************* // Defines -void V3PreProcImp::undef(const string& name) { - m_defines.erase(name); -} +void V3PreProcImp::undef(const string& name) { m_defines.erase(name); } void V3PreProcImp::undefineall() { - for (DefinesMap::iterator nextit, it = m_defines.begin(); it != m_defines.end(); it=nextit) { - nextit = it; ++nextit; + for (DefinesMap::iterator nextit, it = m_defines.begin(); it != m_defines.end(); it = nextit) { + nextit = it; + ++nextit; if (!it->second.cmdline()) m_defines.erase(it); } } @@ -313,7 +324,7 @@ bool V3PreProcImp::defExists(const string& name) { string V3PreProcImp::defValue(const string& name) { DefinesMap::iterator iter = m_defines.find(name); if (iter == m_defines.end()) { - fileline()->v3error("Define or directive not defined: `"+name); + fileline()->v3error("Define or directive not defined: `" + name); return ""; } return iter->second.value(); @@ -321,7 +332,7 @@ string V3PreProcImp::defValue(const string& name) { string V3PreProcImp::defParams(const string& name) { DefinesMap::iterator iter = m_defines.find(name); if (iter == m_defines.end()) { - fileline()->v3error("Define or directive not defined: `"+name); + fileline()->v3error("Define or directive not defined: `" + name); return ""; } return iter->second.params(); @@ -333,20 +344,21 @@ FileLine* V3PreProcImp::defFileline(const string& name) { } void V3PreProcImp::define(FileLine* fl, const string& name, const string& value, const string& params, bool cmdline) { - UINFO(4,"DEFINE '"<v3error("Attempting to define built-in directive: '`" - << name << "' (IEEE 1800-2017 22.5.1)"); + fl->v3error("Attempting to define built-in directive: '`" << name + << "' (IEEE 1800-2017 22.5.1)"); } else { if (defExists(name)) { if (!(defValue(name) == value && defParams(name) == params)) { // Duplicate defs are OK - fl->v3warn(REDEFMACRO, "Redefining existing define: '"<v3warn(REDEFMACRO, "Redefining existing define: '" + << name << "', with different value: " << value + << (params == "" ? "" : " ") << params); defFileline(name)->v3warn(REDEFMACRO, "Previous definition is here, with value: " - << defValue(name) - << (defParams(name).empty() ? "" : " ") - << defParams(name)); + << defValue(name) + << (defParams(name).empty() ? "" : " ") + << defParams(name)); } undef(name); } @@ -357,14 +369,19 @@ void V3PreProcImp::define(FileLine* fl, const string& name, const string& value, string V3PreProcImp::removeDefines(const string& text) { string val; string rtnsym = text; - for (int loopprevent=0; loopprevent<100; loopprevent++) { + for (int loopprevent = 0; loopprevent < 100; loopprevent++) { string xsym = rtnsym; - if (xsym.substr(0, 1)=="`") xsym.replace(0, 1, ""); + if (xsym.substr(0, 1) == "`") xsym.replace(0, 1, ""); if (defExists(xsym)) { val = defValue(xsym); - if (val != rtnsym) rtnsym = val; // Prevent infinite loop if have `define X X - else break; - } else break; + if (val != rtnsym) { + rtnsym = val; // Prevent infinite loop if have `define X X + } else { + break; + } + } else { + break; + } } return rtnsym; // NA } @@ -387,14 +404,13 @@ string V3PreProcImp::commentCleanup(const string& text) { while ((pos = cmd.find('\"')) != string::npos) cmd.replace(pos, 1, " "); while ((pos = cmd.find('\t')) != string::npos) cmd.replace(pos, 1, " "); while ((pos = cmd.find(" ")) != string::npos) cmd.replace(pos, 2, " "); - while (!cmd.empty() && isspace(cmd[cmd.size()-1])) cmd.erase(cmd.size()-1); + while (!cmd.empty() && isspace(cmd[cmd.size() - 1])) cmd.erase(cmd.size() - 1); return cmd; } bool V3PreProcImp::commentTokenMatch(string& cmdr, const char* strg) { int len = strlen(strg); - if (0==strncmp(cmdr.c_str(), strg, len) - && (cmdr[len]=='\0' || isspace(cmdr[len]))) { + if (0 == strncmp(cmdr.c_str(), strg, len) && (cmdr[len] == '\0' || isspace(cmdr[len]))) { if (isspace(cmdr[len])) len++; cmdr = cmdr.substr(len); return true; @@ -412,32 +428,35 @@ void V3PreProcImp::comment(const string& text) { } const char* cp = text.c_str(); - if (cp[0]=='/' && (cp[1]=='/' || cp[1]=='*')) { + if (cp[0] == '/' && (cp[1] == '/' || cp[1] == '*')) { cp += 2; - } else return; + } else { + return; + } while (isspace(*cp)) cp++; bool synth = false; bool vlcomment = false; - if ((cp[0]=='v' || cp[0]=='V') - && 0==(strncmp(cp+1, "erilator", 8))) { + if ((cp[0] == 'v' || cp[0] == 'V') && 0 == (strncmp(cp + 1, "erilator", 8))) { cp += strlen("verilator"); - if (*cp == '_') fileline()->v3error("Extra underscore in meta-comment;" - " use /*verilator {...}*/ not /*verilator_{...}*/"); + if (*cp == '_') + fileline()->v3error("Extra underscore in meta-comment;" + " use /*verilator {...}*/ not /*verilator_{...}*/"); vlcomment = true; - } else if (0==(strncmp(cp, "synopsys", strlen("synopsys")))) { + } else if (0 == (strncmp(cp, "synopsys", strlen("synopsys")))) { cp += strlen("synopsys"); synth = true; - if (*cp == '_') fileline()->v3error("Extra underscore in meta-comment;" - " use /*synopsys {...}*/ not /*synopsys_{...}*/"); - } else if (0==(strncmp(cp, "cadence", strlen("cadence")))) { + if (*cp == '_') + fileline()->v3error("Extra underscore in meta-comment;" + " use /*synopsys {...}*/ not /*synopsys_{...}*/"); + } else if (0 == (strncmp(cp, "cadence", strlen("cadence")))) { cp += strlen("cadence"); synth = true; - } else if (0==(strncmp(cp, "pragma", strlen("pragma")))) { + } else if (0 == (strncmp(cp, "pragma", strlen("pragma")))) { cp += strlen("pragma"); synth = true; - } else if (0==(strncmp(cp, "ambit synthesis", strlen("ambit synthesis")))) { + } else if (0 == (strncmp(cp, "ambit synthesis", strlen("ambit synthesis")))) { cp += strlen("ambit synthesis"); synth = true; } else { @@ -453,16 +472,16 @@ void V3PreProcImp::comment(const string& text) { if (synth) { if (v3Global.opt.assertOn()) { // one_hot, one_cold, (full_case, parallel_case) - if (commentTokenMatch(cmd/*ref*/, "full_case")) { + if (commentTokenMatch(cmd /*ref*/, "full_case")) { if (!printed) insertUnreadback("/*verilator full_case*/"); } - if (commentTokenMatch(cmd/*ref*/, "parallel_case")) { + if (commentTokenMatch(cmd /*ref*/, "parallel_case")) { if (!printed) insertUnreadback("/*verilator parallel_case*/"); } - //if (commentTokenMatch(cmd/*ref*/, "one_hot")) { + // if (commentTokenMatch(cmd/*ref*/, "one_hot")) { // insertUnreadback ("/*verilator one_hot*/ "+cmd+";"); //} - //if (commentTokenMatch(cmd/*ref*/, "one_cold")) { + // if (commentTokenMatch(cmd/*ref*/, "one_cold")) { // insertUnreadback ("/*verilator one_cold*/ "+cmd+";"); //} // else ignore the comment we don't recognize @@ -471,11 +490,11 @@ void V3PreProcImp::comment(const string& text) { string::size_type pos; if ((pos = cmd.find("public_flat_rw")) != string::npos) { // "/*verilator public_flat_rw @(foo) */" -> "/*verilator public_flat_rw*/ @(foo)" - cmd = cmd.substr(pos+strlen("public_flat_rw")); + cmd = cmd.substr(pos + strlen("public_flat_rw")); while (isspace(cmd[0])) cmd = cmd.substr(1); - if (!printed) insertUnreadback("/*verilator public_flat_rw*/ "+cmd+" /**/"); + if (!printed) insertUnreadback("/*verilator public_flat_rw*/ " + cmd + " /**/"); } else { - if (!printed) insertUnreadback("/*verilator "+cmd+"*/"); + if (!printed) insertUnreadback("/*verilator " + cmd + "*/"); } } } @@ -493,34 +512,34 @@ FileLine* V3PreProc::fileline() { const char* V3PreProcImp::tokenName(int tok) { switch (tok) { - case VP_BACKQUOTE : return("BACKQUOTE"); - case VP_COMMENT : return("COMMENT"); - case VP_DEFARG : return("DEFARG"); - case VP_DEFFORM : return("DEFFORM"); - case VP_DEFINE : return("DEFINE"); - case VP_DEFREF : return("DEFREF"); - case VP_DEFREF_JOIN : return("DEFREF_JOIN"); - case VP_DEFVALUE : return("DEFVALUE"); - case VP_ELSE : return("ELSE"); - case VP_ELSIF : return("ELSIF"); - case VP_ENDIF : return("ENDIF"); - case VP_EOF : return("EOF"); - case VP_EOF_ERROR : return("EOF_ERROR"); - case VP_ERROR : return("ERROR"); - case VP_IFDEF : return("IFDEF"); - case VP_IFNDEF : return("IFNDEF"); - case VP_JOIN : return("JOIN"); - case VP_INCLUDE : return("INCLUDE"); - case VP_LINE : return("LINE"); - case VP_STRIFY : return("STRIFY"); - case VP_STRING : return("STRING"); - case VP_SYMBOL : return("SYMBOL"); - case VP_SYMBOL_JOIN : return("SYMBOL_JOIN"); - case VP_TEXT : return("TEXT"); - case VP_UNDEF : return("UNDEF"); - case VP_UNDEFINEALL : return("UNDEFINEALL"); - case VP_WHITE : return("WHITE"); - default: return("?"); + case VP_BACKQUOTE: return ("BACKQUOTE"); + case VP_COMMENT: return ("COMMENT"); + case VP_DEFARG: return ("DEFARG"); + case VP_DEFFORM: return ("DEFFORM"); + case VP_DEFINE: return ("DEFINE"); + case VP_DEFREF: return ("DEFREF"); + case VP_DEFREF_JOIN: return ("DEFREF_JOIN"); + case VP_DEFVALUE: return ("DEFVALUE"); + case VP_ELSE: return ("ELSE"); + case VP_ELSIF: return ("ELSIF"); + case VP_ENDIF: return ("ENDIF"); + case VP_EOF: return ("EOF"); + case VP_EOF_ERROR: return ("EOF_ERROR"); + case VP_ERROR: return ("ERROR"); + case VP_IFDEF: return ("IFDEF"); + case VP_IFNDEF: return ("IFNDEF"); + case VP_JOIN: return ("JOIN"); + case VP_INCLUDE: return ("INCLUDE"); + case VP_LINE: return ("LINE"); + case VP_STRIFY: return ("STRIFY"); + case VP_STRING: return ("STRING"); + case VP_SYMBOL: return ("SYMBOL"); + case VP_SYMBOL_JOIN: return ("SYMBOL_JOIN"); + case VP_TEXT: return ("TEXT"); + case VP_UNDEF: return ("UNDEF"); + case VP_UNDEFINEALL: return ("UNDEFINEALL"); + case VP_WHITE: return ("WHITE"); + default: return ("?"); } } @@ -530,7 +549,7 @@ void V3PreProcImp::unputString(const string& strg) { // However this can lead to "flex scanner push-back overflow" // so instead we scan from a temporary buffer, then on EOF return. // This is also faster than the old scheme, amazingly. - if (m_lexp->m_bufferState!=m_lexp->currentBuffer()) { + if (m_lexp->m_bufferState != m_lexp->currentBuffer()) { fatalSrc("bufferStack missing current buffer; will return incorrectly"); // Hard to debug lost text as won't know till much later } @@ -539,31 +558,31 @@ void V3PreProcImp::unputString(const string& strg) { void V3PreProcImp::unputDefrefString(const string& strg) { int multiline = 0; - for (size_t i=0; icurStreamp()->m_ignNewlines += multiline; // Must be after unput - applies to new stream + // Must be after unput - applies to new stream + m_lexp->curStreamp()->m_ignNewlines += multiline; } string V3PreProcImp::trimWhitespace(const string& strg, bool trailing) { // Remove leading whitespace string out = strg; string::size_type leadspace = 0; - while (out.length() > leadspace - && isspace(out[leadspace])) leadspace++; + while (out.length() > leadspace && isspace(out[leadspace])) leadspace++; if (leadspace) out.erase(0, leadspace); // Remove trailing whitespace if (trailing) { string::size_type trailspace = 0; - while (out.length() > trailspace - && isspace(out[out.length()-1-trailspace])) trailspace++; + while (out.length() > trailspace && isspace(out[out.length() - 1 - trailspace])) + trailspace++; // Don't remove \{space_or_newline} - if (trailspace && out.length() > trailspace && out[out.length()-1-trailspace]=='\\') + if (trailspace && out.length() > trailspace && out[out.length() - 1 - trailspace] == '\\') trailspace--; - if (trailspace) out.erase(out.length()-trailspace, trailspace); + if (trailspace) out.erase(out.length() - trailspace, trailspace); } return out; } @@ -577,16 +596,16 @@ string V3PreProcImp::defineSubst(VDefineRef* refp) { // Note we parse the definition parameters and value here. If a // parameterized define is used many, many times, we could cache the // parsed result. - UINFO(4,"defineSubstIn `"<name()<<" "<params()<args().size(); i++) { - UINFO(4,"defineArg["<args()[i]<<"'"<name() << " " << refp->params() << endl); + for (unsigned i = 0; i < refp->args().size(); i++) { + UINFO(4, "defineArg[" << i << "] = '" << refp->args()[i] << "'" << endl); } // Grab value string value = defValue(refp->name()); - UINFO(4,"defineValue '"< argValueByName; - { // Parse argument list into map + std::map argValueByName; + { // Parse argument list into map unsigned numArgs = 0; string argName; int paren = 1; // (), {} and [] can use same counter, as must be matched pair per spec @@ -598,16 +617,21 @@ string V3PreProcImp::defineSubst(VDefineRef* refp) { const char* cp = params.c_str(); if (*cp == '(') cp++; for (; *cp; cp++) { - //UINFO(4," Parse Paren="<args().size() > numArgs) { // A call `def( a ) must be equivalent to `def(a ), so trimWhitespace // At one point we didn't trim trailing @@ -615,8 +639,9 @@ string V3PreProcImp::defineSubst(VDefineRef* refp) { string arg = trimWhitespace(refp->args()[numArgs], true); if (arg != "") valueDef = arg; } else if (!haveDefault) { - error("Define missing argument '"+argName+"' for: "+refp->name()+"\n"); - return " `"+refp->name()+" "; + error("Define missing argument '" + argName + "' for: " + refp->name() + + "\n"); + return " `" + refp->name() + " "; } numArgs++; } @@ -626,64 +651,69 @@ string V3PreProcImp::defineSubst(VDefineRef* refp) { token = ""; haveDefault = false; continue; - } - else if (*cp=='=') { + } else if (*cp == '=') { haveDefault = true; argName = token; token = ""; continue; } } - if (cp[0]=='\\' && cp[1]) { + if (cp[0] == '\\' && cp[1]) { token += cp[0]; // \{any} Put out literal next character token += cp[1]; cp++; continue; } if (!quote) { - if (*cp=='(' || *cp=='{' || *cp=='[') paren++; - else if (*cp==')' || *cp=='}' || *cp==']') paren--; + if (*cp == '(' || *cp == '{' || *cp == '[') { + paren++; + } else if (*cp == ')' || *cp == '}' || *cp == ']') { + paren--; + } } - if (*cp=='"') quote=!quote; + if (*cp == '"') quote = !quote; if (*cp) token += *cp; } if (refp->args().size() > numArgs // `define X() is ok to call with nothing - && !(refp->args().size()==1 && numArgs==0 - && trimWhitespace(refp->args()[0], false)=="")) { - error("Define passed too many arguments: "+refp->name()+"\n"); - return " `"+refp->name()+" "; + && !(refp->args().size() == 1 && numArgs == 0 + && trimWhitespace(refp->args()[0], false) == "")) { + error("Define passed too many arguments: " + refp->name() + "\n"); + return " `" + refp->name() + " "; } } string out; - { // Parse substitution define using arguments + { // Parse substitution define using arguments string argName; bool quote = false; bool backslashesc = false; // In \.....{space} block // Note we go through the loop once more at the NULL end-of-string - for (const char* cp=value.c_str(); (*cp) || argName!=""; cp=(*cp?cp+1:cp)) { - //UINFO(4, "CH "<<*cp<<" an "<::iterator iter = argValueByName.find(argName); + std::map::iterator iter = argValueByName.find(argName); if (iter != argValueByName.end()) { // Substitute string subst = iter->second; if (subst == "") { // Normally `` is removed later, but with no token after, we're otherwise // stuck, so remove proceeding `` - if (out.size()>=2 && out.substr(out.size()-2) == "``") { - out = out.substr(0, out.size()-2); + if (out.size() >= 2 && out.substr(out.size() - 2) == "``") { + out = out.substr(0, out.size() - 2); } } else { out += subst; @@ -695,36 +725,33 @@ string V3PreProcImp::defineSubst(VDefineRef* refp) { } if (!quote) { // Check for `` only after we've detected end-of-argname - if (cp[0]=='`' && cp[1]=='`') { + if (cp[0] == '`' && cp[1] == '`') { if (backslashesc) { // Don't put out the ``, we're forming an escape // which will not expand further later } else { - out += "``"; // `` must get removed later, as `FOO```BAR must pre-expand FOO and BAR + out += "``"; // `` must get removed later, as `FOO```BAR must pre-expand + // FOO and BAR // See also removal in empty substitutes above } cp++; continue; - } - else if (cp[0]=='`' && cp[1]=='"') { + } else if (cp[0] == '`' && cp[1] == '"') { out += "`\""; // `" means to put out a " without enabling quote mode (sort of) // however we must expand any macro calls inside it first. // So keep it `", so we don't enter quote mode. cp++; continue; - } - else if (cp[0]=='`' && cp[1]=='\\' && cp[2]=='`' && cp[3]=='"') { - out += "`\\`\""; // `\`" means to put out a backslash quote + } else if (cp[0] == '`' && cp[1] == '\\' && cp[2] == '`' && cp[3] == '"') { + out += "`\\`\""; // `\`" means to put out a backslash quote // Leave it literal until we parse the VP_STRIFY string cp += 3; continue; - } - else if (cp[0]=='`' && cp[1]=='\\') { + } else if (cp[0] == '`' && cp[1] == '\\') { out += '\\'; // `\ means to put out a backslash cp++; continue; - } - else if (cp[0]=='\\' && cp[1]=='\n') { + } else if (cp[0] == '\\' && cp[1] == '\n') { // We kept the \\n when we lexed because we don't want whitespace // trimming to mis-drop the final \\n // At replacement time we need the standard newline. @@ -733,24 +760,23 @@ string V3PreProcImp::defineSubst(VDefineRef* refp) { continue; } } - if (cp[0]=='\\' && cp[1]=='\"') { + if (cp[0] == '\\' && cp[1] == '\"') { out += cp[0]; // \{any} Put out literal next character out += cp[1]; cp++; continue; - } - else if (cp[0]=='\\') { + } else if (cp[0] == '\\') { // Normally \{any} would put out literal next character // Instead we allow "`define A(nm) \nm" to expand, per proposed mantis1537 out += cp[0]; continue; } - if (*cp=='"') quote=!quote; + if (*cp == '"') quote = !quote; if (*cp) out += *cp; } } - UINFO(4,"defineSubstOut '"< with the whole file. StrList wholefile; - bool ok = filterp->readWholefile(filename, wholefile/*ref*/); + bool ok = filterp->readWholefile(filename, wholefile /*ref*/); if (!ok) { - error("File not found: "+filename+"\n"); + error("File not found: " + filename + "\n"); return; } @@ -774,7 +800,7 @@ void V3PreProcImp::openFile(FileLine* fl, VInFilter* filterp, const string& file // We allow the same include file twice, because occasionally it pops // up, with guards preventing a real recursion. if (m_lexp->m_streampStack.size() > V3PreProc::INCLUDE_DEPTH_MAX) { - error("Recursive inclusion of file: "+filename); + error("Recursive inclusion of file: " + filename); // Include might be a tree of includes that is O(n^2) or worse. // Once hit this error then, ignore all further includes so can unwind. m_incError = true; @@ -788,7 +814,7 @@ void V3PreProcImp::openFile(FileLine* fl, VInFilter* filterp, const string& file FileLine* flsp = new FileLine(filename); flsp->lineno(1); flsp->newContent(); - for (StrList::iterator it=wholefile.begin(); it!=wholefile.end(); ++it) { + for (StrList::iterator it = wholefile.begin(); it != wholefile.end(); ++it) { flsp->contentp()->pushText(*it); } @@ -799,23 +825,23 @@ void V3PreProcImp::openFile(FileLine* fl, VInFilter* filterp, const string& file // Filter all DOS CR's en-mass. This avoids bugs with lexing CRs in the wrong places. // This will also strip them from strings, but strings aren't supposed // to be multi-line without a "\" - for (StrList::iterator it=wholefile.begin(); it!=wholefile.end(); ++it) { + for (StrList::iterator it = wholefile.begin(); it != wholefile.end(); ++it) { // We don't end-loop at \0 as we allow and strip mid-string '\0's (for now). bool strip = false; const char* sp = it->data(); const char* ep = sp + it->length(); // Only process if needed, as saves extra string allocations - for (const char* cp=sp; cplength()); - for (const char* cp=sp; cplength()); + for (const char* cp = sp; cp < ep; cp++) { + if (!(*cp == '\r' || *cp == '\0')) out += *cp; } *it = out; } @@ -830,8 +856,9 @@ void V3PreProcImp::openFile(FileLine* fl, VInFilter* filterp, const string& file void V3PreProcImp::insertUnreadbackAtBol(const string& text) { // Insert insuring we're at the beginning of line, for `line // We don't always add a leading newline, as it may result in extra unreadback(newlines). - if (m_lineCmt == "") { m_lineCmtNl = true; } - else if (m_lineCmt[m_lineCmt.length()-1]!='\n') { + if (m_lineCmt == "") { + m_lineCmtNl = true; + } else if (m_lineCmt[m_lineCmt.length() - 1] != '\n') { insertUnreadback("\n"); } insertUnreadback(text); @@ -845,11 +872,11 @@ void V3PreProcImp::addLineComment(int enterExit) { void V3PreProcImp::dumpDefines(std::ostream& os) { for (DefinesMap::const_iterator it = m_defines.begin(); it != m_defines.end(); ++it) { - os<<"`define "<first; + os << "`define " << it->first; // No need to print "()" below as already part of params() - if (!it->second.params().empty()) os<second.params(); - if (!it->second.value().empty()) os<<" "<second.value(); - os<second.params().empty()) os << it->second.params(); + if (!it->second.value().empty()) os << " " << it->second.value(); + os << endl; } } @@ -862,15 +889,15 @@ void V3PreProcImp::candidateDefines(VSpellCheck* spellerp) { int V3PreProcImp::getRawToken() { // Get a token from the file, whatever it may be. while (true) { - next_tok: + next_tok: if (m_lineAdd) { m_lineAdd--; m_rawAtBol = true; yyourtext("\n", 1); - if (debug()>=5) debugToken(VP_WHITE, "LNA"); + if (debug() >= 5) debugToken(VP_WHITE, "LNA"); return VP_WHITE; } - if (m_lineCmt!="") { + if (m_lineCmt != "") { // We have some `line directive or other processed data to return to the user. static string rtncmt; // Keep the c string till next call rtncmt = m_lineCmt; @@ -880,12 +907,12 @@ int V3PreProcImp::getRawToken() { } yyourtext(rtncmt.c_str(), rtncmt.length()); m_lineCmt = ""; - if (yyourleng()) m_rawAtBol = (yyourtext()[yyourleng()-1]=='\n'); - if (state()==ps_DEFVALUE) { + if (yyourleng()) m_rawAtBol = (yyourtext()[yyourleng() - 1] == '\n'); + if (state() == ps_DEFVALUE) { V3PreLex::s_currentLexp->appendDefValue(yyourtext(), yyourleng()); goto next_tok; } else { - if (debug()>=5) debugToken(VP_TEXT, "LCM"); + if (debug() >= 5) debugToken(VP_TEXT, "LCM"); return VP_TEXT; } } @@ -894,25 +921,25 @@ int V3PreProcImp::getRawToken() { // Snarf next token from the file m_lexp->curFilelinep()->startToken(); int tok = m_lexp->lex(); - if (debug()>=5) debugToken(tok, "RAW"); + if (debug() >= 5) debugToken(tok, "RAW"); if (m_lastLineno != m_lexp->m_tokFilelinep->lineno()) { m_lastLineno = m_lexp->m_tokFilelinep->lineno(); m_tokensOnLine = 0; } else if (++m_tokensOnLine > LINE_TOKEN_MAX) { - error("Too many preprocessor tokens on a line (>"+cvtToStr(LINE_TOKEN_MAX) - +"); perhaps recursive `define"); + error("Too many preprocessor tokens on a line (>" + cvtToStr(LINE_TOKEN_MAX) + + "); perhaps recursive `define"); tok = VP_EOF_ERROR; } - if (tok==VP_EOF || tok==VP_EOF_ERROR) { + if (tok == VP_EOF || tok == VP_EOF_ERROR) { // An error might be in an unexpected point, so stop parsing - if (tok==VP_EOF_ERROR) forceEof(); + if (tok == VP_EOF_ERROR) forceEof(); // A EOF on an include, stream will find the EOF, after adding needed `lines goto next_tok; } - if (yyourleng()) m_rawAtBol = (yyourtext()[yyourleng()-1]=='\n'); + if (yyourleng()) m_rawAtBol = (yyourtext()[yyourleng() - 1] == '\n'); return tok; } } @@ -925,14 +952,12 @@ void V3PreProcImp::debugToken(int tok, const char* cmtp) { while ((pos = buf.find('\n')) != string::npos) { buf.replace(pos, 1, "\\n"); } while ((pos = buf.find('\r')) != string::npos) { buf.replace(pos, 1, "\\r"); } string flcol = m_lexp->m_tokFilelinep->asciiLineCol(); - fprintf(stderr, "%s: %s %s %s(%d) dr%d: <%d>%-10s: %s\n", - flcol.c_str(), - cmtp, (m_off ? "of" : "on"), - procStateName(state()), static_cast(m_states.size()), - static_cast(m_defRefs.size()), - m_lexp->currentStartState(), tokenName(tok), buf.c_str()); + fprintf(stderr, "%s: %s %s %s(%d) dr%d: <%d>%-10s: %s\n", flcol.c_str(), cmtp, + (m_off ? "of" : "on"), procStateName(state()), static_cast(m_states.size()), + static_cast(m_defRefs.size()), m_lexp->currentStartState(), tokenName(tok), + buf.c_str()); if (s_debugFileline >= 9) { - std::cerr<m_tokFilelinep->warnContextSecondary()<m_tokFilelinep->warnContextSecondary() << endl; } } } @@ -943,17 +968,18 @@ void V3PreProcImp::debugToken(int tok, const char* cmtp) { int V3PreProcImp::getStateToken() { // Return the next state-determined token while (true) { - next_tok: + next_tok: if (isEof()) return VP_EOF; int tok = getRawToken(); // Most states emit white space and comments between tokens. (Unless collecting a string) - if (tok==VP_WHITE && state() !=ps_STRIFY) return tok; - if (tok==VP_BACKQUOTE && state() !=ps_STRIFY) { tok = VP_TEXT; } - if (tok==VP_COMMENT) { + if (tok == VP_WHITE && state() != ps_STRIFY) return tok; + if (tok == VP_BACKQUOTE && state() != ps_STRIFY) { tok = VP_TEXT; } + if (tok == VP_COMMENT) { if (!m_off) { if (m_lexp->m_keepComments == KEEPCMT_SUB) { - string rtn; rtn.assign(yyourtext(), yyourleng()); + string rtn; + rtn.assign(yyourtext(), yyourleng()); comment(rtn); // Need to ensure "foo/**/bar" becomes two tokens insertUnreadback(" "); @@ -967,17 +993,17 @@ int V3PreProcImp::getStateToken() { // We're off or processed the comment specially. If there are newlines // in it, we also return the newlines as TEXT so that the linenumber // count is maintained for downstream tools - for (size_t len=0; len(yyourleng()); len++) { - if (yyourtext()[len]=='\n') m_lineAdd++; + for (size_t len = 0; len < static_cast(yyourleng()); len++) { + if (yyourtext()[len] == '\n') m_lineAdd++; } goto next_tok; } - if (tok==VP_LINE) { + if (tok == VP_LINE) { addLineComment(m_lexp->m_enterExit); goto next_tok; } - if (tok==VP_DEFREF_JOIN) { + if (tok == VP_DEFREF_JOIN) { // Here's something fun and unspecified as yet: // The existence of non-existance of a base define changes `` expansion // `define QA_b zzz @@ -989,23 +1015,24 @@ int V3PreProcImp::getStateToken() { // `define Q1 `QA()``_b // -> a_b // This may be a side effect of how `UNDEFINED remains as `UNDEFINED, // but it screws up our method here. So hardcode it. - string name (yyourtext()+1, yyourleng()-1); + string name(yyourtext() + 1, yyourleng() - 1); if (defExists(name)) { // JOIN(DEFREF) // Put back the `` and process the defref - UINFO(5,"```: define "< string doesn't include the ``, so can just grab next and continue - string out (yyourtext(), yyourleng()); - UINFO(5,"`` LHS:"<pushStateDefForm(); goto next_tok; + } else { + fatalSrc("Bad case\n"); } - else fatalSrc("Bad case\n"); goto next_tok; - } - else if (tok==VP_TEXT) { + } else if (tok == VP_TEXT) { // IE, something like comment between define and symbol - if (!m_off) return tok; - else goto next_tok; - } - else if (tok==VP_DEFREF) { + if (!m_off) { + return tok; + } else { + goto next_tok; + } + } else if (tok == VP_DEFREF) { // IE, `ifdef `MACRO(x): Substitute and come back here when state pops. break; - } - else { - error(string("Expecting define name. Found: ")+tokenName(tok)+"\n"); + } else { + error(string("Expecting define name. Found: ") + tokenName(tok) + "\n"); goto next_tok; } } case ps_DEFFORM: { - if (tok==VP_DEFFORM) { + if (tok == VP_DEFFORM) { m_formals = m_lexp->m_defValue; - if (debug()>=5) cout<<"DefFormals='"<= 5) { + cout << "DefFormals='" << V3PreLex::cleanDbgStrg(m_formals) << "'\n"; + } stateChange(ps_DEFVALUE); m_lexp->pushStateDefValue(); goto next_tok; - } else if (tok==VP_TEXT) { + } else if (tok == VP_TEXT) { // IE, something like comment in formals - if (!m_off) return tok; - else goto next_tok; + if (!m_off) { + return tok; + } else { + goto next_tok; + } } else { - error(string("Expecting define formal arguments. Found: ")+tokenName(tok)+"\n"); + error(string("Expecting define formal arguments. Found: ") + tokenName(tok) + + "\n"); goto next_tok; } } @@ -1101,8 +1132,10 @@ int V3PreProcImp::getStateToken() { static string newlines; newlines = "\n"; // Always start with trailing return if (tok == VP_DEFVALUE) { - if (debug()>=5) cout<<"DefValue='"<m_defValue) - <<"' formals='"<= 5) { + cout << "DefValue='" << V3PreLex::cleanDbgStrg(m_lexp->m_defValue) + << "' formals='" << V3PreLex::cleanDbgStrg(m_formals) << "'\n"; + } // Add any formals string formals = m_formals; string value = m_lexp->m_defValue; @@ -1112,42 +1145,39 @@ int V3PreProcImp::getStateToken() { // 2. Substituting in " .... " with embedded returns requires \ escape. // This is very difficult in the presence of `", so we // keep the \ before the newline. - for (size_t i=0; iname()+"\n"); + error(string("Expecting ( to begin argument list for define reference `") + + refp->name() + "\n"); statePop(); goto next_tok; } @@ -1155,128 +1185,130 @@ int V3PreProcImp::getStateToken() { case ps_DEFARG: { if (m_defRefs.empty()) fatalSrc("Shouldn't be in DEFARG w/o active defref"); VDefineRef* refp = &(m_defRefs.top()); - refp->nextarg(refp->nextarg()+m_lexp->m_defValue); m_lexp->m_defValue = ""; - UINFO(4,"defarg++ "<nextarg()<nextarg(refp->nextarg() + m_lexp->m_defValue); + m_lexp->m_defValue = ""; + UINFO(4, "defarg++ " << refp->nextarg() << endl); + if (tok == VP_DEFARG && yyourleng() == 1 && yyourtext()[0] == ',') { refp->args().push_back(refp->nextarg()); stateChange(ps_DEFARG); m_lexp->pushStateDefArg(1); refp->nextarg(""); goto next_tok; - } else if (tok==VP_DEFARG && yyourleng()==1 && yyourtext()[0]==')') { + } else if (tok == VP_DEFARG && yyourleng() == 1 && yyourtext()[0] == ')') { // Substitute in and prepare for next action // Similar code in non-parenthesized define (Search for END_OF_DEFARG) refp->args().push_back(refp->nextarg()); string out; if (!m_off) { out = defineSubst(refp); - //NOP: out = m_preprocp->defSubstitute(out); + // NOP: out = m_preprocp->defSubstitute(out); } VL_DO_DANGLING(m_defRefs.pop(), refp); if (m_defRefs.empty()) { statePop(); - if (state() == ps_JOIN) { // Handle {left}```FOO(ARG) where `FOO(ARG) might be empty + if (state() + == ps_JOIN) { // Handle {left}```FOO(ARG) where `FOO(ARG) might be empty if (m_joinStack.empty()) fatalSrc("`` join stack empty, but in a ``"); - string lhs = m_joinStack.top(); m_joinStack.pop(); + string lhs = m_joinStack.top(); + m_joinStack.pop(); out.insert(0, lhs); - UINFO(5,"``-end-defarg Out:"<m_parenLevel = 0; - } - else { // Finished a defref inside a upper defref + } else { // Finished a defref inside a upper defref // Can't subst now, or // `define a(ign) x,y // foo(`a(ign),`b) would break because a contains comma refp = &(m_defRefs.top()); // We popped, so new top - refp->nextarg(refp->nextarg()+m_lexp->m_defValue+out); m_lexp->m_defValue = ""; + refp->nextarg(refp->nextarg() + m_lexp->m_defValue + out); + m_lexp->m_defValue = ""; m_lexp->m_parenLevel = refp->parenLevel(); statePop(); // Will go to ps_DEFARG, as we're under another define } goto next_tok; - } else if (tok==VP_DEFREF) { + } else if (tok == VP_DEFREF) { // Expand it, then state will come back here // Value of building argument is data before the lower defref // we'll append it when we push the argument. break; - } else if (tok==VP_SYMBOL || tok==VP_STRING || tok==VP_TEXT || tok==VP_WHITE) { - string rtn; rtn.assign(yyourtext(), yyourleng()); - refp->nextarg(refp->nextarg()+rtn); + } else if (tok == VP_SYMBOL || tok == VP_STRING || tok == VP_TEXT || tok == VP_WHITE) { + string rtn; + rtn.assign(yyourtext(), yyourleng()); + refp->nextarg(refp->nextarg() + rtn); goto next_tok; - } else if (tok==VP_STRIFY) { + } else if (tok == VP_STRIFY) { // We must expand stringinfication, when done will return to this state statePush(ps_STRIFY); goto next_tok; } else { error(string("Expecting ) or , to end argument list for define reference. Found: ") - +tokenName(tok)); + + tokenName(tok)); statePop(); goto next_tok; } } case ps_INCNAME: { - if (tok==VP_STRING) { + if (tok == VP_STRING) { statePop(); m_lastSym.assign(yyourtext(), yyourleng()); - UINFO(4,"Include "< stateChange(ps_INCNAME); // Still m_lexp->pushStateIncFilename(); goto next_tok; - } - else if (tok==VP_DEFREF - || tok==VP_STRIFY) { + } else if (tok == VP_DEFREF || tok == VP_STRIFY) { // Expand it, then state will come back here break; - } - else { + } else { statePop(); - error(string("Expecting include filename. Found: ")+tokenName(tok)+"\n"); + error(string("Expecting include filename. Found: ") + tokenName(tok) + "\n"); goto next_tok; } } case ps_ERRORNAME: { - if (tok==VP_STRING) { + if (tok == VP_STRING) { if (!m_off) { m_lastSym.assign(yyourtext(), yyourleng()); error(m_lastSym); } statePop(); goto next_tok; - } - else { - error(string("Expecting `error string. Found: ")+tokenName(tok)+"\n"); + } else { + error(string("Expecting `error string. Found: ") + tokenName(tok) + "\n"); statePop(); goto next_tok; } } case ps_JOIN: { - if (tok==VP_SYMBOL || tok==VP_TEXT) { + if (tok == VP_SYMBOL || tok == VP_TEXT) { if (m_joinStack.empty()) fatalSrc("`` join stack empty, but in a ``"); - string lhs = m_joinStack.top(); m_joinStack.pop(); - UINFO(5,"`` LHS:"< V3PreProc::DEFINE_RECURSION_LEVEL_MAX) { - error("Recursive `define substitution: `"+name); + error("Recursive `define substitution: `" + name); goto next_tok; } // Substitute if (!defExists(name)) { // Not found, return original string as-is m_defDepth = 0; - UINFO(4,"Defref `"< not_defined"< not_defined" << endl); if (m_off) { goto next_tok; } else { return VP_TEXT; } - } - else { + } else { string params = defParams(name); - if (params=="0" || params=="") { // Found, as simple substitution + if (params == "0" || params == "") { // Found, as simple substitution string out; if (!m_off) { VDefineRef tempref(name, ""); out = defineSubst(&tempref); } // Similar code in parenthesized define (Search for END_OF_DEFARG) - //NOP: out = m_preprocp->defSubstitute(out); + // NOP: out = m_preprocp->defSubstitute(out); if (m_defRefs.empty()) { // Just output the substitution if (state() == ps_JOIN) { // Handle {left}```FOO where `FOO might be empty if (m_joinStack.empty()) fatalSrc("`` join stack empty, but in a ``"); - string lhs = m_joinStack.top(); m_joinStack.pop(); + string lhs = m_joinStack.top(); + m_joinStack.pop(); out.insert(0, lhs); - UINFO(5,"``-end-defref Out:"<nextarg(refp->nextarg()+m_lexp->m_defValue+out); + refp->nextarg(refp->nextarg() + m_lexp->m_defValue + out); m_lexp->m_defValue = ""; } goto next_tok; - } - else { // Found, with parameters - UINFO(4,"Defref `"< parameterized"< parameterized" << endl); // The CURRENT macro needs the paren saved, it's not a // property of the child macro if (!m_defRefs.empty()) m_defRefs.top().parenLevel(m_lexp->m_parenLevel); @@ -1443,13 +1466,11 @@ int V3PreProcImp::getStateToken() { goto next_tok; } case VP_EOF: - if (!m_ifdefStack.empty()) { - error("`ifdef not terminated at EOF\n"); - } + if (!m_ifdefStack.empty()) error("`ifdef not terminated at EOF\n"); return tok; case VP_UNDEFINEALL: if (!m_off) { - UINFO(4,"Undefineall "<=5) { + if (0 && debug() >= 5) { string bufcln = V3PreLex::cleanDbgStrg(buf); string flcol = m_lexp->m_tokFilelinep->asciiLineCol(); - fprintf(stderr, "%s: FIN: %-10s: %s\n", - flcol.c_str(), - tokenName(tok), bufcln.c_str()); + fprintf(stderr, "%s: FIN: %-10s: %s\n", flcol.c_str(), tokenName(tok), + bufcln.c_str()); } // Track `line const char* bufp = buf.c_str(); while (*bufp == '\n') bufp++; - if ((tok == VP_TEXT || tok == VP_LINE) && 0==strncmp(bufp, "`line ", 6)) { + if ((tok == VP_TEXT || tok == VP_LINE) && 0 == strncmp(bufp, "`line ", 6)) { int enter; - m_finFilelinep->lineDirective(bufp, enter/*ref*/); - } - else { - if (m_finAtBol && !(tok==VP_TEXT && buf=="\n") - && m_preprocp->lineDirectives()) { - if (int outBehind = (m_lexp->m_tokFilelinep->lastLineno() - - m_finFilelinep->lastLineno())) { - if (debug()>=5) { + m_finFilelinep->lineDirective(bufp, enter /*ref*/); + } else { + if (m_finAtBol && !(tok == VP_TEXT && buf == "\n") && m_preprocp->lineDirectives()) { + if (int outBehind + = (m_lexp->m_tokFilelinep->lastLineno() - m_finFilelinep->lastLineno())) { + if (debug() >= 5) { string flcol = m_lexp->m_tokFilelinep->asciiLineCol(); - fprintf(stderr, "%s: FIN: readjust, fin at %d request at %d\n", - flcol.c_str(), - m_finFilelinep->lastLineno(), - m_lexp->m_tokFilelinep->lastLineno()); + fprintf(stderr, "%s: FIN: readjust, fin at %d request at %d\n", flcol.c_str(), + m_finFilelinep->lastLineno(), m_lexp->m_tokFilelinep->lastLineno()); } m_finFilelinep->filename(m_lexp->m_tokFilelinep->filename()); m_finFilelinep->lineno(m_lexp->m_tokFilelinep->lastLineno()); @@ -1521,7 +1540,7 @@ int V3PreProcImp::getFinalToken(string& buf) { // Output stream is behind, send newlines to get back in sync // (Most likely because we're completing a disabled `endif) if (m_preprocp->keepWhitespace()) { - buf = string(outBehind,'\n'); + buf = string(outBehind, '\n'); return VP_TEXT; } } else { @@ -1532,7 +1551,7 @@ int V3PreProcImp::getFinalToken(string& buf) { } } // Track newlines in prep for next token - for (string::iterator cp=buf.begin(); cp!=buf.end(); ++cp) { + for (string::iterator cp = buf.begin(); cp != buf.end(); ++cp) { if (*cp == '\n') { m_finAtBol = true; m_finFilelinep->linenoInc(); @@ -1552,36 +1571,32 @@ string V3PreProcImp::getline() { bool gotEof = false; while (NULL == (rtnp = strchr(m_lineChars.c_str(), '\n')) && !gotEof) { string buf; - int tok = getFinalToken(buf/*ref*/); - if (debug()>=5) { + int tok = getFinalToken(buf /*ref*/); + if (debug() >= 5) { string bufcln = V3PreLex::cleanDbgStrg(buf); string flcol = m_lexp->m_tokFilelinep->asciiLineCol(); - fprintf(stderr, "%s: GETFETC: %-10s: %s\n", - flcol.c_str(), - tokenName(tok), bufcln.c_str()); + fprintf(stderr, "%s: GETFETC: %-10s: %s\n", flcol.c_str(), tokenName(tok), + bufcln.c_str()); } - if (tok==VP_EOF) { + if (tok == VP_EOF) { // Add a final newline, if the user forgot the final \n. - if (m_lineChars != "" && m_lineChars[m_lineChars.length()-1] != '\n') { + if (m_lineChars != "" && m_lineChars[m_lineChars.length() - 1] != '\n') { m_lineChars.append("\n"); } gotEof = true; - } - else { + } else { m_lineChars.append(buf); } } // Make new string with data up to the newline. - int len = rtnp-m_lineChars.c_str()+1; + int len = rtnp - m_lineChars.c_str() + 1; string theLine(m_lineChars, 0, len); m_lineChars = m_lineChars.erase(0, len); // Remove returned characters - if (debug()>=4) { + if (debug() >= 4) { string lncln = V3PreLex::cleanDbgStrg(theLine); string flcol = m_lexp->m_tokFilelinep->asciiLineCol(); - fprintf(stderr, "%s: GETLINE: %s\n", - flcol.c_str(), - lncln.c_str()); + fprintf(stderr, "%s: GETLINE: %s\n", flcol.c_str(), lncln.c_str()); } return theLine; } diff --git a/src/V3Premit.cpp b/src/V3Premit.cpp index ec613e954..e4271defa 100644 --- a/src/V3Premit.cpp +++ b/src/V3Premit.cpp @@ -42,17 +42,17 @@ class PremitAssignVisitor : public AstNVisitor { private: // NODE STATE // AstVar::user4() // bool; occurs on LHS of current assignment - AstUser4InUse m_inuser4; + AstUser4InUse m_inuser4; // STATE - bool m_noopt; // Disable optimization of variables in this block + bool m_noopt; // Disable optimization of variables in this block // METHODS VL_DEBUG_FUNC; // Declare debug() // VISITORS virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { - //AstNode::user4ClearTree(); // Implied by AstUser4InUse + // AstNode::user4ClearTree(); // Implied by AstUser4InUse // LHS first as fewer varrefs iterateAndNextNull(nodep->lhsp()); // Now find vars marked as lhs @@ -64,7 +64,7 @@ private: nodep->varp()->user4(true); } else { if (nodep->varp()->user4()) { - if (!m_noopt) UINFO(4, "Block has LHS+RHS var: "< bool. True if converted to conditional // AstShiftR::user2() -> bool. True if converted to conditional // *::user4() -> See PremitAssignVisitor - AstUser1InUse m_inuser1; - AstUser2InUse m_inuser2; + AstUser1InUse m_inuser1; + AstUser2InUse m_inuser2; // STATE - AstNodeModule* m_modp; // Current module - AstCFunc* m_funcp; // Current block - AstNode* m_stmtp; // Current statement - AstWhile* m_inWhilep; // Inside while loop, special statement additions - AstTraceInc* m_inTracep; // Inside while loop, special statement additions - bool m_assignLhs; // Inside assignment lhs, don't breakup extracts + AstNodeModule* m_modp; // Current module + AstCFunc* m_funcp; // Current block + AstNode* m_stmtp; // Current statement + AstWhile* m_inWhilep; // Inside while loop, special statement additions + AstTraceInc* m_inTracep; // Inside while loop, special statement additions + bool m_assignLhs; // Inside assignment lhs, don't breakup extracts // METHODS VL_DEBUG_FUNC; // Declare debug() bool assignNoTemp(AstNodeAssign* nodep) { - return (VN_IS(nodep->lhsp(), VarRef) - && !AstVar::scVarRecurse(nodep->lhsp()) + return (VN_IS(nodep->lhsp(), VarRef) && !AstVar::scVarRecurse(nodep->lhsp()) && VN_IS(nodep->rhsp(), Const)); } void checkNode(AstNode* nodep) { @@ -119,24 +118,22 @@ private: // ARRAYSEL(*here*, ...) (No wides can be in any argument but first, // so we don't check which arg is wide) // ASSIGN(x, SEL*HERE*(ARRAYSEL()...) (m_assignLhs==true handles this.) - //UINFO(9, " Check: "<user1()) { // Not already done + // UINFO(9, " Check: " << nodep << endl); + // UINFO(9, " Detail stmtp=" << (m_stmtp?"Y":"N") << " U=" << (nodep->user1()?"Y":"N") + // << " IW=" << (nodep->isWide()?"Y":"N") << endl); + if (m_stmtp && !nodep->user1()) { // Not already done if (nodep->isWide()) { if (m_assignLhs) { - } else if (nodep->firstAbovep() - && VN_IS(nodep->firstAbovep(), NodeAssign) + } else if (nodep->firstAbovep() && VN_IS(nodep->firstAbovep(), NodeAssign) && assignNoTemp(VN_CAST(nodep->firstAbovep(), NodeAssign))) { // Not much point if it's just a direct assignment to a constant } else if (VN_IS(nodep->backp(), Sel) && VN_CAST(nodep->backp(), Sel)->widthp() == nodep) { // AstSel::width must remain a constant - } else if (nodep->firstAbovep() - && VN_IS(nodep->firstAbovep(), ArraySel)) { + } else if (nodep->firstAbovep() && VN_IS(nodep->firstAbovep(), ArraySel)) { // ArraySel's are pointer refs, ignore } else { - UINFO(4,"Cre Temp: "<varNumGetInc())); - AstVar* varp = new AstVar(nodep->fileline(), AstVarType::STMTTEMP, newvarname, - nodep->dtypep()); + string newvarname = (string("__Vtemp") + cvtToStr(m_modp->varNumGetInc())); + AstVar* varp + = new AstVar(nodep->fileline(), AstVarType::STMTTEMP, newvarname, nodep->dtypep()); m_funcp->addInitsp(varp); return varp; } @@ -171,7 +168,7 @@ private: } void createDeepTemp(AstNode* nodep, bool noSubst) { - if (debug()>8) nodep->dumpTree(cout, "deepin:"); + if (debug() > 8) nodep->dumpTree(cout, "deepin:"); AstNRelinker linker; nodep->unlinkFrBack(&linker); @@ -183,16 +180,15 @@ private: linker.relink(newp); // Put assignment before the referencing statement AstAssign* assp = new AstAssign(nodep->fileline(), - new AstVarRef(nodep->fileline(), varp, true), - nodep); + new AstVarRef(nodep->fileline(), varp, true), nodep); insertBeforeStmt(assp); - if (debug()>8) assp->dumpTree(cout, "deepou:"); + if (debug() > 8) assp->dumpTree(cout, "deepou:"); nodep->user1(true); // Don't add another assignment } // VISITORS virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { - UINFO(4," MOD "<precondsp()); startStatement(nodep); @@ -229,7 +225,7 @@ private: bool noopt = PremitAssignVisitor(nodep).noOpt(); if (noopt && !nodep->user1()) { // Need to do this even if not wide, as e.g. a select may be on a wide operator - UINFO(4,"Deep temp for LHS/RHS\n"); + UINFO(4, "Deep temp for LHS/RHS\n"); createDeepTemp(nodep->rhsp(), false); } } @@ -244,7 +240,7 @@ private: iterateChildren(nodep); return; } - UINFO(4," STMT "< 32/64 bits in C++ will wrap-around and generate non-0s if (!nodep->user2SetOnce()) { - UINFO(4," ShiftFix "<rhsp(), Const); if (shiftp && shiftp->num().mostSetBitP1() > 32) { - shiftp->v3error("Unsupported: Shifting of by over 32-bit number isn't supported." - <<" (This isn't a shift of 32 bits, but a shift of 2^32, or 4 billion!)\n"); + shiftp->v3error( + "Unsupported: Shifting of by over 32-bit number isn't supported." + << " (This isn't a shift of 32 bits, but a shift of 2^32, or 4 billion!)\n"); } if (nodep->widthMin() <= 64 // Else we'll use large operators which work right - // C operator's width must be < maximum shift which is based on Verilog width - && nodep->width() < (1LL<rhsp()->widthMin())) { + // C operator's width must be < maximum shift which is + // based on Verilog width + && nodep->width() < (1LL << nodep->rhsp()->widthMin())) { AstNRelinker replaceHandle; nodep->unlinkFrBack(&replaceHandle); AstNode* constzerop; - int m1value = nodep->widthMin()-1; // Constant of width-1; not changing dtype width + int m1value + = nodep->widthMin() - 1; // Constant of width-1; not changing dtype width if (nodep->signedFlavor()) { // Then over shifting gives the sign bit, not all zeros // Note *NOT* clean output -- just like normal shift! // Create equivalent of VL_SIGNONES_(node_width) - constzerop = new AstNegate(nodep->fileline(), - new AstShiftR(nodep->fileline(), - nodep->lhsp()->cloneTree(false), - new AstConst(nodep->fileline(), - m1value), - nodep->width())); + constzerop = new AstNegate( + nodep->fileline(), + new AstShiftR(nodep->fileline(), nodep->lhsp()->cloneTree(false), + new AstConst(nodep->fileline(), m1value), nodep->width())); } else { constzerop = new AstConst(nodep->fileline(), AstConst::WidthedValue(), nodep->width(), 0); @@ -291,43 +288,39 @@ private: AstNode* constwidthp = new AstConst(nodep->fileline(), AstConst::WidthedValue(), nodep->rhsp()->widthMin(), m1value); constwidthp->dtypeFrom(nodep->rhsp()); // unsigned - AstCond* newp = - new AstCond(nodep->fileline(), - new AstGte(nodep->fileline(), - constwidthp, - nodep->rhsp()->cloneTree(false)), - nodep, - constzerop); + AstCond* newp = new AstCond( + nodep->fileline(), + new AstGte(nodep->fileline(), constwidthp, nodep->rhsp()->cloneTree(false)), + nodep, constzerop); replaceHandle.relink(newp); } } - iterateChildren(nodep); checkNode(nodep); - } - virtual void visit(AstShiftL* nodep) VL_OVERRIDE { - visitShift(nodep); - } - virtual void visit(AstShiftR* nodep) VL_OVERRIDE { - visitShift(nodep); - } - virtual void visit(AstShiftRS* nodep) VL_OVERRIDE { - visitShift(nodep); + iterateChildren(nodep); + checkNode(nodep); } + virtual void visit(AstShiftL* nodep) VL_OVERRIDE { visitShift(nodep); } + virtual void visit(AstShiftR* nodep) VL_OVERRIDE { visitShift(nodep); } + virtual void visit(AstShiftRS* nodep) VL_OVERRIDE { visitShift(nodep); } // Operators virtual void visit(AstNodeTermop* nodep) VL_OVERRIDE { - iterateChildren(nodep); checkNode(nodep); + iterateChildren(nodep); + checkNode(nodep); } virtual void visit(AstNodeUniop* nodep) VL_OVERRIDE { - iterateChildren(nodep); checkNode(nodep); + iterateChildren(nodep); + checkNode(nodep); } virtual void visit(AstNodeBiop* nodep) VL_OVERRIDE { - iterateChildren(nodep); checkNode(nodep); + iterateChildren(nodep); + checkNode(nodep); } virtual void visit(AstUCFunc* nodep) VL_OVERRIDE { - iterateChildren(nodep); checkNode(nodep); + iterateChildren(nodep); + checkNode(nodep); } virtual void visit(AstSel* nodep) VL_OVERRIDE { iterateAndNextNull(nodep->fromp()); - { // Only the 'from' is part of the assignment LHS + { // Only the 'from' is part of the assignment LHS bool prevAssign = m_assignLhs; m_assignLhs = false; iterateAndNextNull(nodep->lsbp()); @@ -338,7 +331,7 @@ private: } virtual void visit(AstArraySel* nodep) VL_OVERRIDE { iterateAndNextNull(nodep->fromp()); - { // Only the 'from' is part of the assignment LHS + { // Only the 'from' is part of the assignment LHS bool prevAssign = m_assignLhs; m_assignLhs = false; iterateAndNextNull(nodep->bitp()); @@ -348,7 +341,7 @@ private: } virtual void visit(AstAssocSel* nodep) VL_OVERRIDE { iterateAndNextNull(nodep->fromp()); - { // Only the 'from' is part of the assignment LHS + { // Only the 'from' is part of the assignment LHS bool prevAssign = m_assignLhs; m_assignLhs = false; iterateAndNextNull(nodep->bitp()); @@ -362,8 +355,7 @@ private: } virtual void visit(AstNodeCond* nodep) VL_OVERRIDE { iterateChildren(nodep); - if (nodep->expr1p()->isWide() - && !VN_IS(nodep->condp(), Const) + if (nodep->expr1p()->isWide() && !VN_IS(nodep->condp(), Const) && !VN_IS(nodep->condp(), VarRef)) { // We're going to need the expression several times in the expanded code, // so might as well make it a common expression @@ -380,12 +372,11 @@ private: if (v3Global.opt.autoflush()) { AstNode* searchp = nodep->nextp(); while (searchp && VN_IS(searchp, Comment)) searchp = searchp->nextp(); - if (searchp - && VN_IS(searchp, Display) + if (searchp && VN_IS(searchp, Display) && nodep->filep()->sameGateTree(VN_CAST(searchp, Display)->filep())) { // There's another display next; we can just wait to flush } else { - UINFO(4,"Autoflush "<addNextHere(new AstFFlush(nodep->fileline(), AstNode::cloneTreeNull(nodep->filep(), true))); } @@ -395,9 +386,8 @@ private: iterateChildren(nodep); // Any strings sent to a display must be var of string data type, // to avoid passing a pointer to a temporary. - for (AstNode* expp=nodep->exprsp(); expp; expp = expp->nextp()) { - if (expp->dtypep()->basicp() - && expp->dtypep()->basicp()->isString() + for (AstNode* expp = nodep->exprsp(); expp; expp = expp->nextp()) { + if (expp->dtypep()->basicp() && expp->dtypep()->basicp()->isString() && !VN_IS(expp, VarRef)) { createDeepTemp(expp, true); } @@ -430,9 +420,7 @@ public: // Premit class functions void V3Premit::premitAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3ProtectLib.cpp b/src/V3ProtectLib.cpp index 018a1d4f1..49b78d76f 100644 --- a/src/V3ProtectLib.cpp +++ b/src/V3ProtectLib.cpp @@ -26,50 +26,49 @@ #include - //###################################################################### // ProtectLib top-level visitor class ProtectVisitor : public AstNVisitor { - private: - AstVFile* m_vfilep; // DPI-enabled Verilog wrapper - AstCFile* m_cfilep; // C implementation of DPI functions +private: + AstVFile* m_vfilep; // DPI-enabled Verilog wrapper + AstCFile* m_cfilep; // C implementation of DPI functions // Verilog text blocks - AstTextBlock* m_modPortsp; // Module port list - AstTextBlock* m_comboPortsp; // Combo function port list - AstTextBlock* m_seqPortsp; // Sequential function port list + AstTextBlock* m_modPortsp; // Module port list + AstTextBlock* m_comboPortsp; // Combo function port list + AstTextBlock* m_seqPortsp; // Sequential function port list AstTextBlock* m_comboIgnorePortsp; // Combo ignore function port list - AstTextBlock* m_comboDeclsp; // Combo signal declaration list - AstTextBlock* m_seqDeclsp; // Sequential signal declaration list - AstTextBlock* m_tmpDeclsp; // Temporary signal declaration list - AstTextBlock* m_hashValuep; // CPP hash value - AstTextBlock* m_comboParamsp; // Combo function parameter list - AstTextBlock* m_clkSensp; // Clock sensitivity list - AstTextBlock* m_comboIgnoreParamsp; // Combo ignore parameter list - AstTextBlock* m_seqParamsp; // Sequential parameter list - AstTextBlock* m_nbAssignsp; // Non-blocking assignment list - AstTextBlock* m_seqAssignsp; // Sequential assignment list - AstTextBlock* m_comboAssignsp; // Combo assignment list + AstTextBlock* m_comboDeclsp; // Combo signal declaration list + AstTextBlock* m_seqDeclsp; // Sequential signal declaration list + AstTextBlock* m_tmpDeclsp; // Temporary signal declaration list + AstTextBlock* m_hashValuep; // CPP hash value + AstTextBlock* m_comboParamsp; // Combo function parameter list + AstTextBlock* m_clkSensp; // Clock sensitivity list + AstTextBlock* m_comboIgnoreParamsp; // Combo ignore parameter list + AstTextBlock* m_seqParamsp; // Sequential parameter list + AstTextBlock* m_nbAssignsp; // Non-blocking assignment list + AstTextBlock* m_seqAssignsp; // Sequential assignment list + AstTextBlock* m_comboAssignsp; // Combo assignment list // C text blocks - AstTextBlock* m_cHashValuep; // CPP hash value - AstTextBlock* m_cComboParamsp; // Combo function parameter list - AstTextBlock* m_cComboInsp; // Combo input copy list - AstTextBlock* m_cComboOutsp; // Combo output copy list - AstTextBlock* m_cSeqParamsp; // Sequential parameter list - AstTextBlock* m_cSeqClksp; // Sequential clock copy list - AstTextBlock* m_cSeqOutsp; // Sequential output copy list - AstTextBlock* m_cIgnoreParamsp; // Combo ignore parameter list + AstTextBlock* m_cHashValuep; // CPP hash value + AstTextBlock* m_cComboParamsp; // Combo function parameter list + AstTextBlock* m_cComboInsp; // Combo input copy list + AstTextBlock* m_cComboOutsp; // Combo output copy list + AstTextBlock* m_cSeqParamsp; // Sequential parameter list + AstTextBlock* m_cSeqClksp; // Sequential clock copy list + AstTextBlock* m_cSeqOutsp; // Sequential output copy list + AstTextBlock* m_cIgnoreParamsp; // Combo ignore parameter list string m_libName; string m_topName; - bool m_foundTop; // Have seen the top module + bool m_foundTop; // Have seen the top module // VISITORS virtual void visit(AstNetlist* nodep) VL_OVERRIDE { - m_vfilep = new AstVFile(nodep->fileline(), - v3Global.opt.makeDir()+"/"+m_libName+".sv"); + m_vfilep + = new AstVFile(nodep->fileline(), v3Global.opt.makeDir() + "/" + m_libName + ".sv"); nodep->addFilesp(m_vfilep); - m_cfilep = new AstCFile(nodep->fileline(), - v3Global.opt.makeDir()+"/"+m_libName+".cpp"); + m_cfilep + = new AstCFile(nodep->fileline(), v3Global.opt.makeDir() + "/" + m_libName + ".cpp"); nodep->addFilesp(m_cfilep); iterateChildren(nodep); } @@ -87,8 +86,8 @@ class ProtectVisitor : public AstNVisitor { iterateChildren(nodep); V3Hash hash = V3Hashed::uncachedHash(m_cfilep); - m_hashValuep->addText(fl, cvtToStr(hash.fullValue())+";\n"); - m_cHashValuep->addText(fl, cvtToStr(hash.fullValue())+"U;\n"); + m_hashValuep->addText(fl, cvtToStr(hash.fullValue()) + ";\n"); + m_cHashValuep->addText(fl, cvtToStr(hash.fullValue()) + "U;\n"); m_foundTop = true; } @@ -127,47 +126,55 @@ class ProtectVisitor : public AstNVisitor { // Comments AstTextBlock* txtp = new AstTextBlock(fl); addComment(txtp, fl, "Wrapper module for DPI protected library"); - addComment(txtp, fl, "This module requires lib"+m_libName+ - ".a or lib"+m_libName+".so to work"); - addComment(txtp, fl, "See instructions in your simulator for how" + addComment(txtp, fl, + "This module requires lib" + m_libName + ".a or lib" + m_libName + + ".so to work"); + addComment(txtp, fl, + "See instructions in your simulator for how" " to use DPI libraries\n"); // Module declaration - m_modPortsp = new AstTextBlock(fl, "module "+m_libName+" (\n", false, true); + m_modPortsp = new AstTextBlock(fl, "module " + m_libName + " (\n", false, true); txtp->addNodep(m_modPortsp); txtp->addText(fl, ");\n\n"); // DPI declarations hashComment(txtp, fl); - txtp->addText(fl, "import \"DPI-C\" function void "+ - m_libName+"_protectlib_check_hash(int protectlib_hash__V);\n\n"); + txtp->addText(fl, "import \"DPI-C\" function void " + m_libName + + "_protectlib_check_hash(int protectlib_hash__V);\n\n"); initialComment(txtp, fl); - txtp->addText(fl, "import \"DPI-C\" function chandle "+ - m_libName+"_protectlib_create(string scope__V);\n\n"); + txtp->addText(fl, "import \"DPI-C\" function chandle " + m_libName + + "_protectlib_create(string scope__V);\n\n"); comboComment(txtp, fl); - m_comboPortsp = new AstTextBlock(fl, "import \"DPI-C\" function longint "+ - m_libName+"_protectlib_combo_update " - "(\n", false, true); + m_comboPortsp = new AstTextBlock(fl, + "import \"DPI-C\" function longint " + m_libName + + "_protectlib_combo_update " + "(\n", + false, true); m_comboPortsp->addText(fl, "chandle handle__V\n"); txtp->addNodep(m_comboPortsp); txtp->addText(fl, ");\n\n"); seqComment(txtp, fl); - m_seqPortsp = new AstTextBlock(fl, "import \"DPI-C\" function longint "+ - m_libName+"_protectlib_seq_update" - "(\n", false, true); + m_seqPortsp = new AstTextBlock(fl, + "import \"DPI-C\" function longint " + m_libName + + "_protectlib_seq_update" + "(\n", + false, true); m_seqPortsp->addText(fl, "chandle handle__V\n"); txtp->addNodep(m_seqPortsp); txtp->addText(fl, ");\n\n"); comboIgnoreComment(txtp, fl); - m_comboIgnorePortsp = new AstTextBlock(fl, "import \"DPI-C\" function void "+ - m_libName+"_protectlib_combo_ignore" - "(\n", false, true); + m_comboIgnorePortsp = new AstTextBlock(fl, + "import \"DPI-C\" function void " + m_libName + + "_protectlib_combo_ignore" + "(\n", + false, true); m_comboIgnorePortsp->addText(fl, "chandle handle__V\n"); txtp->addNodep(m_comboIgnorePortsp); txtp->addText(fl, ");\n\n"); finalComment(txtp, fl); - txtp->addText(fl, "import \"DPI-C\" function void "+ - m_libName+"_protectlib_final(chandle handle__V);\n\n"); + txtp->addText(fl, "import \"DPI-C\" function void " + m_libName + + "_protectlib_final(chandle handle__V);\n\n"); // Local variables txtp->addText(fl, "chandle handle__V;\n\n"); @@ -189,16 +196,18 @@ class ProtectVisitor : public AstNVisitor { // Initial txtp->addText(fl, "initial begin\n"); - txtp->addText(fl, m_libName+"_protectlib_check_hash(protectlib_hash__V);\n"); - txtp->addText(fl, "handle__V = "+m_libName+"_protectlib_create" - "($sformatf(\"%m\"));\n"); + txtp->addText(fl, m_libName + "_protectlib_check_hash(protectlib_hash__V);\n"); + txtp->addText(fl, "handle__V = " + m_libName + + "_protectlib_create" + "($sformatf(\"%m\"));\n"); txtp->addText(fl, "end\n\n"); // Combinatorial process addComment(txtp, fl, "Combinatorialy evaluate changes to inputs"); - m_comboParamsp = new AstTextBlock(fl, "always @(*) begin\n" - "last_combo_seqnum__V = "+ - m_libName+"_protectlib_combo_update(\n", + m_comboParamsp = new AstTextBlock(fl, + "always @(*) begin\n" + "last_combo_seqnum__V = " + + m_libName + "_protectlib_combo_update(\n", false, true); m_comboParamsp->addText(fl, "handle__V\n"); txtp->addNodep(m_comboParamsp); @@ -210,14 +219,13 @@ class ProtectVisitor : public AstNVisitor { m_clkSensp = new AstTextBlock(fl, "always @(", false, true); txtp->addNodep(m_clkSensp); txtp->addText(fl, ") begin\n"); - m_comboIgnoreParamsp = new AstTextBlock(fl, m_libName+"_protectlib_combo_ignore(\n", - false, true); + m_comboIgnoreParamsp + = new AstTextBlock(fl, m_libName + "_protectlib_combo_ignore(\n", false, true); m_comboIgnoreParamsp->addText(fl, "handle__V\n"); txtp->addNodep(m_comboIgnoreParamsp); txtp->addText(fl, ");\n"); - m_seqParamsp = new AstTextBlock(fl, "last_seq_seqnum__V <= "+m_libName+ - "_protectlib_seq_update(\n", - false, true); + m_seqParamsp = new AstTextBlock( + fl, "last_seq_seqnum__V <= " + m_libName + "_protectlib_seq_update(\n", false, true); m_seqParamsp->addText(fl, "handle__V\n"); txtp->addNodep(m_seqParamsp); txtp->addText(fl, ");\n"); @@ -229,7 +237,7 @@ class ProtectVisitor : public AstNVisitor { addComment(txtp, fl, "Select between combinatorial and sequential results"); txtp->addText(fl, "always @(*) begin\n"); m_seqAssignsp = new AstTextBlock(fl, "if (last_seq_seqnum__V > " - "last_combo_seqnum__V) begin\n"); + "last_combo_seqnum__V) begin\n"); txtp->addNodep(m_seqAssignsp); m_comboAssignsp = new AstTextBlock(fl, "end else begin\n"); txtp->addNodep(m_comboAssignsp); @@ -237,15 +245,17 @@ class ProtectVisitor : public AstNVisitor { txtp->addText(fl, "end\n\n"); // Final - txtp->addText(fl, "final "+m_libName+"_protectlib_final(handle__V);\n\n"); + txtp->addText(fl, "final " + m_libName + "_protectlib_final(handle__V);\n\n"); txtp->addText(fl, "endmodule\n"); m_vfilep->tblockp(txtp); } void castPtr(FileLine* fl, AstTextBlock* txtp) { - txtp->addText(fl, m_topName+"_container* handlep__V = " - "static_cast<"+m_topName+"_container*>(vhandlep__V);\n"); + txtp->addText(fl, m_topName + + "_container* handlep__V = " + "static_cast<" + + m_topName + "_container*>(vhandlep__V);\n"); } void createCppFile(FileLine* fl) { @@ -254,18 +264,18 @@ class ProtectVisitor : public AstNVisitor { addComment(txtp, fl, "Wrapper functions for DPI protected library\n"); // Includes - txtp->addText(fl, "#include \""+m_topName+".h\"\n"); + txtp->addText(fl, "#include \"" + m_topName + ".h\"\n"); txtp->addText(fl, "#include \"verilated_dpi.h\"\n\n"); txtp->addText(fl, "#include \n"); txtp->addText(fl, "#include \n\n"); // Verilated module plus sequence number addComment(txtp, fl, "Container class to house verilated object and sequence number"); - txtp->addText(fl, "class "+m_topName+"_container: public "+m_topName+" {\n"); + txtp->addText(fl, "class " + m_topName + "_container: public " + m_topName + " {\n"); txtp->addText(fl, "public:\n"); txtp->addText(fl, "long long m_seqnum;\n"); - txtp->addText(fl, m_topName+"_container(const char* scopep__V):\n"); - txtp->addText(fl, m_topName+"(scopep__V) {}\n"); + txtp->addText(fl, m_topName + "_container(const char* scopep__V):\n"); + txtp->addText(fl, m_topName + "(scopep__V) {}\n"); txtp->addText(fl, "};\n\n"); // Extern C @@ -273,31 +283,32 @@ class ProtectVisitor : public AstNVisitor { // Hash check hashComment(txtp, fl); - txtp->addText(fl, "void "+m_libName+"_protectlib_check_hash" - "(int protectlib_hash__V) {\n"); + txtp->addText(fl, "void " + m_libName + + "_protectlib_check_hash" + "(int protectlib_hash__V) {\n"); m_cHashValuep = new AstTextBlock(fl, "int expected_hash__V = "); txtp->addNodep(m_cHashValuep); txtp->addText(fl, "if (protectlib_hash__V != expected_hash__V) {\n"); - txtp->addText(fl, "fprintf(stderr, \"%%Error: cannot use "+m_libName+" library, " - "Verliog (%u) and library (%u) hash values do not " - "agree\\n\", protectlib_hash__V, expected_hash__V);\n"); + txtp->addText(fl, "fprintf(stderr, \"%%Error: cannot use " + m_libName + + " library, " + "Verliog (%u) and library (%u) hash values do not " + "agree\\n\", protectlib_hash__V, expected_hash__V);\n"); txtp->addText(fl, "exit(EXIT_FAILURE);\n"); txtp->addText(fl, "}\n"); txtp->addText(fl, "}\n\n"); // Initial initialComment(txtp, fl); - txtp->addText(fl, "void* "+m_libName+"_protectlib_create" - " (const char* scopep__V) {\n"); - txtp->addText(fl, m_topName+"_container* handlep__V = " - "new "+m_topName+"_container(scopep__V);\n"); + txtp->addText(fl, "void* " + m_libName + "_protectlib_create(const char* scopep__V) {\n"); + txtp->addText(fl, m_topName + "_container* handlep__V = new " + m_topName + + "_container(scopep__V);\n"); txtp->addText(fl, "return handlep__V;\n"); txtp->addText(fl, "}\n\n"); // Updates comboComment(txtp, fl); - m_cComboParamsp = new AstTextBlock(fl, "long long "+m_libName+"_protectlib_combo_update(\n", - false, true); + m_cComboParamsp = new AstTextBlock( + fl, "long long " + m_libName + "_protectlib_combo_update(\n", false, true); m_cComboParamsp->addText(fl, "void* vhandlep__V\n"); txtp->addNodep(m_cComboParamsp); txtp->addText(fl, ")\n"); @@ -310,8 +321,8 @@ class ProtectVisitor : public AstNVisitor { txtp->addText(fl, "}\n\n"); seqComment(txtp, fl); - m_cSeqParamsp = new AstTextBlock(fl, "long long "+m_libName+"_protectlib_seq_update(\n", - false, true); + m_cSeqParamsp = new AstTextBlock( + fl, "long long " + m_libName + "_protectlib_seq_update(\n", false, true); m_cSeqParamsp->addText(fl, "void* vhandlep__V\n"); txtp->addNodep(m_cSeqParamsp); txtp->addText(fl, ")\n"); @@ -324,8 +335,8 @@ class ProtectVisitor : public AstNVisitor { txtp->addText(fl, "}\n\n"); comboIgnoreComment(txtp, fl); - m_cIgnoreParamsp = new AstTextBlock(fl, "void "+m_libName+"_protectlib_combo_ignore(\n", - false, true); + m_cIgnoreParamsp = new AstTextBlock( + fl, "void " + m_libName + "_protectlib_combo_ignore(\n", false, true); m_cIgnoreParamsp->addText(fl, "void* vhandlep__V\n"); txtp->addNodep(m_cIgnoreParamsp); txtp->addText(fl, ")\n"); @@ -333,7 +344,7 @@ class ProtectVisitor : public AstNVisitor { // Final finalComment(txtp, fl); - txtp->addText(fl, "void "+m_libName+"_protectlib_final(void* vhandlep__V) {\n"); + txtp->addText(fl, "void " + m_libName + "_protectlib_final(void* vhandlep__V) {\n"); castPtr(fl, txtp); txtp->addText(fl, "handlep__V->final();\n"); txtp->addText(fl, "delete handlep__V;\n"); @@ -346,11 +357,11 @@ class ProtectVisitor : public AstNVisitor { virtual void visit(AstVar* nodep) VL_OVERRIDE { if (!nodep->isIO()) return; if (VN_IS(nodep->dtypep(), UnpackArrayDType)) { - nodep->v3error("Unsupported: unpacked arrays with protect-lib on "<prettyNameQ()); + nodep->v3error("Unsupported: unpacked arrays with protect-lib on " + << nodep->prettyNameQ()); } if (nodep->direction() == VDirection::INPUT) { - if (nodep->isUsedClock() - || nodep->attrClocker() == VVarAttrClocker::CLOCKER_YES) { + if (nodep->isUsedClock() || nodep->attrClocker() == VVarAttrClocker::CLOCKER_YES) { handleClock(nodep); } else { handleDataInput(nodep); @@ -358,8 +369,8 @@ class ProtectVisitor : public AstNVisitor { } else if (nodep->direction() == VDirection::OUTPUT) { handleOutput(nodep); } else { - nodep->v3error("Unsupported: protect-lib port direction: "<< - nodep->direction().ascii()); + nodep->v3error( + "Unsupported: protect-lib port direction: " << nodep->direction().ascii()); } } @@ -369,18 +380,18 @@ class ProtectVisitor : public AstNVisitor { string frstmt; bool useSetWSvlv = V3Task::dpiToInternalFrStmt(varp, varp->name(), frstmt); if (useSetWSvlv) { - return frstmt+" handlep__V->"+varp->name()+", "+varp->name()+");\n"; + return frstmt + " handlep__V->" + varp->name() + ", " + varp->name() + ");\n"; } - return "handlep__V->"+varp->name()+" = "+frstmt+";\n"; + return "handlep__V->" + varp->name() + " = " + frstmt + ";\n"; } void handleClock(AstVar* varp) { FileLine* fl = varp->fileline(); handleInput(varp); m_seqPortsp->addNodep(varp->cloneTree(false)); - m_seqParamsp->addText(fl, varp->name()+"\n"); - m_clkSensp->addText(fl, "edge("+varp->name()+")"); - m_cSeqParamsp->addText(fl, varp->dpiArgType(true, false)+"\n"); + m_seqParamsp->addText(fl, varp->name() + "\n"); + m_clkSensp->addText(fl, "edge(" + varp->name() + ")"); + m_cSeqParamsp->addText(fl, varp->dpiArgType(true, false) + "\n"); m_cSeqClksp->addText(fl, cInputConnection(varp)); } @@ -388,61 +399,76 @@ class ProtectVisitor : public AstNVisitor { FileLine* fl = varp->fileline(); handleInput(varp); m_comboPortsp->addNodep(varp->cloneTree(false)); - m_comboParamsp->addText(fl, varp->name()+"\n"); + m_comboParamsp->addText(fl, varp->name() + "\n"); m_comboIgnorePortsp->addNodep(varp->cloneTree(false)); - m_comboIgnoreParamsp->addText(fl, varp->name()+"\n"); - m_cComboParamsp->addText(fl, varp->dpiArgType(true, false)+"\n"); + m_comboIgnoreParamsp->addText(fl, varp->name() + "\n"); + m_cComboParamsp->addText(fl, varp->dpiArgType(true, false) + "\n"); m_cComboInsp->addText(fl, cInputConnection(varp)); - m_cIgnoreParamsp->addText(fl, varp->dpiArgType(true, false)+"\n"); + m_cIgnoreParamsp->addText(fl, varp->dpiArgType(true, false) + "\n"); } - void handleInput(AstVar* varp) { - m_modPortsp->addNodep(varp->cloneTree(false)); - } + void handleInput(AstVar* varp) { m_modPortsp->addNodep(varp->cloneTree(false)); } void handleOutput(AstVar* varp) { FileLine* fl = varp->fileline(); m_modPortsp->addNodep(varp->cloneTree(false)); m_comboPortsp->addNodep(varp->cloneTree(false)); - m_comboParamsp->addText(fl, varp->name()+"_combo__V\n"); + m_comboParamsp->addText(fl, varp->name() + "_combo__V\n"); m_seqPortsp->addNodep(varp->cloneTree(false)); - m_seqParamsp->addText(fl, varp->name()+"_tmp__V\n"); + m_seqParamsp->addText(fl, varp->name() + "_tmp__V\n"); AstNodeDType* comboDtypep = varp->dtypep()->cloneTree(false); m_comboDeclsp->addNodep(comboDtypep); - m_comboDeclsp->addText(fl, " "+varp->name()+"_combo__V;\n"); + m_comboDeclsp->addText(fl, " " + varp->name() + "_combo__V;\n"); AstNodeDType* seqDtypep = varp->dtypep()->cloneTree(false); m_seqDeclsp->addNodep(seqDtypep); - m_seqDeclsp->addText(fl, " "+varp->name()+"_seq__V;\n"); + m_seqDeclsp->addText(fl, " " + varp->name() + "_seq__V;\n"); AstNodeDType* tmpDtypep = varp->dtypep()->cloneTree(false); m_tmpDeclsp->addNodep(tmpDtypep); - m_tmpDeclsp->addText(fl, " "+varp->name()+"_tmp__V;\n"); + m_tmpDeclsp->addText(fl, " " + varp->name() + "_tmp__V;\n"); - m_nbAssignsp->addText(fl, varp->name()+"_seq__V <= "+varp->name()+"_tmp__V;\n"); - m_seqAssignsp->addText(fl, varp->name()+" = "+varp->name()+"_seq__V;\n"); - m_comboAssignsp->addText(fl, varp->name()+" = "+varp->name()+"_combo__V;\n"); - m_cComboParamsp->addText(fl, varp->dpiArgType(true, false)+"\n"); + m_nbAssignsp->addText(fl, varp->name() + "_seq__V <= " + varp->name() + "_tmp__V;\n"); + m_seqAssignsp->addText(fl, varp->name() + " = " + varp->name() + "_seq__V;\n"); + m_comboAssignsp->addText(fl, varp->name() + " = " + varp->name() + "_combo__V;\n"); + m_cComboParamsp->addText(fl, varp->dpiArgType(true, false) + "\n"); m_cComboOutsp->addText(fl, V3Task::assignInternalToDpi(varp, true, "", "", "handlep__V->")); - m_cSeqParamsp->addText(fl, varp->dpiArgType(true, false)+"\n"); + m_cSeqParamsp->addText(fl, varp->dpiArgType(true, false) + "\n"); m_cSeqOutsp->addText(fl, V3Task::assignInternalToDpi(varp, true, "", "", "handlep__V->")); } - public: - explicit ProtectVisitor(AstNode* nodep): - m_vfilep(NULL), m_cfilep(NULL), m_modPortsp(NULL), - m_comboPortsp(NULL), m_seqPortsp(NULL), m_comboIgnorePortsp(NULL), m_comboDeclsp(NULL), - m_seqDeclsp(NULL), m_tmpDeclsp(NULL), m_hashValuep(NULL), - m_comboParamsp(NULL), - m_clkSensp(NULL), - m_comboIgnoreParamsp(NULL), m_seqParamsp(NULL), m_nbAssignsp(NULL), m_seqAssignsp(NULL), - m_comboAssignsp(NULL), m_cHashValuep(NULL), m_cComboParamsp(NULL), m_cComboInsp(NULL), - m_cComboOutsp(NULL), m_cSeqParamsp(NULL), m_cSeqClksp(NULL), m_cSeqOutsp(NULL), - m_cIgnoreParamsp(NULL), m_libName(v3Global.opt.protectLib()), - m_topName(v3Global.opt.prefix()), m_foundTop(false) - { +public: + explicit ProtectVisitor(AstNode* nodep) + : m_vfilep(NULL) + , m_cfilep(NULL) + , m_modPortsp(NULL) + , m_comboPortsp(NULL) + , m_seqPortsp(NULL) + , m_comboIgnorePortsp(NULL) + , m_comboDeclsp(NULL) + , m_seqDeclsp(NULL) + , m_tmpDeclsp(NULL) + , m_hashValuep(NULL) + , m_comboParamsp(NULL) + , m_clkSensp(NULL) + , m_comboIgnoreParamsp(NULL) + , m_seqParamsp(NULL) + , m_nbAssignsp(NULL) + , m_seqAssignsp(NULL) + , m_comboAssignsp(NULL) + , m_cHashValuep(NULL) + , m_cComboParamsp(NULL) + , m_cComboInsp(NULL) + , m_cComboOutsp(NULL) + , m_cSeqParamsp(NULL) + , m_cSeqClksp(NULL) + , m_cSeqOutsp(NULL) + , m_cIgnoreParamsp(NULL) + , m_libName(v3Global.opt.protectLib()) + , m_topName(v3Global.opt.prefix()) + , m_foundTop(false) { iterate(nodep); } }; diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp index 1243ceb1a..4ce1a1485 100644 --- a/src/V3Scope.cpp +++ b/src/V3Scope.cpp @@ -43,8 +43,8 @@ private: // NODE STATE // AstVar::user1p -> AstVarScope replacement for this variable // AstTask::user2p -> AstTask*. Replacement task - AstUser1InUse m_inuser1; - AstUser2InUse m_inuser2; + AstUser1InUse m_inuser1; + AstUser2InUse m_inuser2; // TYPES typedef vl_unordered_map PackageScopeMap; @@ -53,26 +53,25 @@ private: typedef std::set > VarRefScopeSet; // STATE, inside processing a single module - AstNodeModule* m_modp; // Current module - AstScope* m_scopep; // Current scope we are building + AstNodeModule* m_modp; // Current module + AstScope* m_scopep; // Current scope we are building // STATE, for passing down one level of hierarchy (may need save/restore) - AstCell* m_aboveCellp; // Cell that instantiates this module - AstScope* m_aboveScopep; // Scope that instantiates this scope + AstCell* m_aboveCellp; // Cell that instantiates this module + AstScope* m_aboveScopep; // Scope that instantiates this scope - PackageScopeMap m_packageScopes; // Scopes for each package - VarScopeMap m_varScopes; // Varscopes created for each scope and var - VarRefScopeSet m_varRefScopes; // Varrefs-in-scopes needing fixup when done + PackageScopeMap m_packageScopes; // Scopes for each package + VarScopeMap m_varScopes; // Varscopes created for each scope and var + VarRefScopeSet m_varRefScopes; // Varrefs-in-scopes needing fixup when done // METHODS VL_DEBUG_FUNC; // Declare debug() void cleanupVarRefs() { - for (VarRefScopeSet::iterator it = m_varRefScopes.begin(); - it!=m_varRefScopes.end(); ++it) { + for (VarRefScopeSet::iterator it = m_varRefScopes.begin(); it != m_varRefScopes.end(); + ++it) { AstVarRef* nodep = it->first; AstScope* scopep = it->second; - if (nodep->packagep() - && !nodep->varp()->isClassMember()) { + if (nodep->packagep() && !nodep->varp()->isClassMember()) { PackageScopeMap::iterator it2 = m_packageScopes.find(nodep->packagep()); UASSERT_OBJ(it2 != m_packageScopes.end(), nodep, "Can't locate package scope"); scopep = it2->second; @@ -87,7 +86,10 @@ private: // VISITORS virtual void visit(AstNetlist* nodep) VL_OVERRIDE { AstNodeModule* modp = nodep->topModulep(); - if (!modp) { nodep->v3error("No top level module found"); return; } + if (!modp) { + nodep->v3error("No top level module found"); + return; + } // Operate starting at the top of the hierarchy m_aboveCellp = NULL; m_aboveScopep = NULL; @@ -97,22 +99,25 @@ private: virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { // Create required blocks and add to module string scopename; - if (!m_aboveScopep) scopename = "TOP"; - else scopename = m_aboveScopep->name()+"."+m_aboveCellp->name(); + if (!m_aboveScopep) { + scopename = "TOP"; + } else { + scopename = m_aboveScopep->name() + "." + m_aboveCellp->name(); + } - UINFO(4," MOD AT "<(m_aboveCellp) - : static_cast(nodep)) - ->fileline(), - nodep, scopename, m_aboveScopep, m_aboveCellp); + m_scopep = new AstScope( + (m_aboveCellp ? static_cast(m_aboveCellp) : static_cast(nodep)) + ->fileline(), + nodep, scopename, m_aboveScopep, m_aboveCellp); if (VN_IS(nodep, Package)) { m_packageScopes.insert(make_pair(VN_CAST(nodep, Package), m_scopep)); } // Now for each child cell, iterate the module this cell points to - for (AstNode* cellnextp = nodep->stmtsp(); cellnextp; cellnextp=cellnextp->nextp()) { + for (AstNode* cellnextp = nodep->stmtsp(); cellnextp; cellnextp = cellnextp->nextp()) { if (AstCell* cellp = VN_CAST(cellnextp, Cell)) { AstScope* oldScopep = m_scopep; AstCell* oldAbCellp = m_aboveCellp; @@ -132,7 +137,7 @@ private: } // Create scope for the current usage of this module - UINFO(4," back AT "<isTop()) { @@ -168,8 +173,8 @@ private: AstNode* abovep = (m_aboveCellp ? static_cast(m_aboveCellp) : static_cast(nodep)); - m_scopep = new AstScope(abovep->fileline(), - m_modp, scopename, m_aboveScopep, m_aboveCellp); + m_scopep + = new AstScope(abovep->fileline(), m_modp, scopename, m_aboveScopep, m_aboveCellp); // Create scope for the current usage of this cell AstNode::user1ClearTree(); nodep->addMembersp(m_scopep); @@ -181,7 +186,7 @@ private: m_aboveCellp = oldAbCellp; m_aboveScopep = oldAbScopep; } - virtual void visit(AstCellInline* nodep) VL_OVERRIDE { + virtual void visit(AstCellInline* nodep) VL_OVERRIDE { // nodep->scopep(m_scopep); } virtual void visit(AstActive* nodep) VL_OVERRIDE { @@ -189,7 +194,7 @@ private: } virtual void visit(AstInitial* nodep) VL_OVERRIDE { // Add to list of blocks under this scope - UINFO(4," Move "<cloneTree(false); nodep->user2p(clonep); m_scopep->addActivep(clonep); @@ -197,7 +202,7 @@ private: } virtual void visit(AstFinal* nodep) VL_OVERRIDE { // Add to list of blocks under this scope - UINFO(4," Move "<cloneTree(false); nodep->user2p(clonep); m_scopep->addActivep(clonep); @@ -205,7 +210,7 @@ private: } virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { // Add to list of blocks under this scope - UINFO(4," Move "<cloneTree(false); nodep->user2p(clonep); m_scopep->addActivep(clonep); @@ -213,7 +218,7 @@ private: } virtual void visit(AstAssignVarScope* nodep) VL_OVERRIDE { // Copy under the scope but don't recurse - UINFO(4," Move "<cloneTree(false); nodep->user2p(clonep); m_scopep->addActivep(clonep); @@ -221,7 +226,7 @@ private: } virtual void visit(AstAssignW* nodep) VL_OVERRIDE { // Add to list of blocks under this scope - UINFO(4," Move "<cloneTree(false); nodep->user2p(clonep); m_scopep->addActivep(clonep); @@ -229,7 +234,7 @@ private: } virtual void visit(AstAlways* nodep) VL_OVERRIDE { // Add to list of blocks under this scope - UINFO(4," Move "<cloneTree(false); nodep->user2p(clonep); m_scopep->addActivep(clonep); @@ -237,7 +242,7 @@ private: } virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE { // Add to list of blocks under this scope - UINFO(4," Move "<cloneTree(false); nodep->user2p(clonep); m_scopep->addActivep(clonep); @@ -245,7 +250,7 @@ private: } virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE { // Add to list of blocks under this scope - UINFO(4," Move "<cloneTree(false); nodep->user2p(clonep); m_scopep->addActivep(clonep); @@ -253,7 +258,7 @@ private: } virtual void visit(AstCFunc* nodep) VL_OVERRIDE { // Add to list of blocks under this scope - UINFO(4," CFUNC "<cloneTree(false); nodep->user2p(clonep); m_scopep->addActivep(clonep); @@ -263,7 +268,7 @@ private: } virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { // Add to list of blocks under this scope - UINFO(4," FTASK "<classMethod()) { // Only one scope will be created, so avoid pointless cloning @@ -281,7 +286,7 @@ private: // Make new scope variable if (!nodep->user1p()) { AstVarScope* varscp = new AstVarScope(nodep->fileline(), m_scopep, nodep); - UINFO(6," New scope "<isTrace()) varscp->trace(false); nodep->user1p(varscp); if (v3Global.opt.isClocker(varscp->prettyName())) { @@ -307,10 +312,10 @@ private: // So push to a list and post-correct m_varRefScopes.insert(make_pair(nodep, m_scopep)); } - } + } virtual void visit(AstScopeName* nodep) VL_OVERRIDE { // If there's a %m in the display text, we add a special node that will contain the name() - string prefix = string("__DOT__")+m_scopep->name(); + string prefix = string("__DOT__") + m_scopep->name(); // TOP and above will be the user's name(). // Note 'TOP.' is stripped by scopePrettyName // To keep correct visual order, must add before other Text's @@ -375,36 +380,16 @@ private: } } - virtual void visit(AstInitial* nodep) VL_OVERRIDE { - movedDeleteOrIterate(nodep); - } - virtual void visit(AstFinal* nodep) VL_OVERRIDE { - movedDeleteOrIterate(nodep); - } - virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { - movedDeleteOrIterate(nodep); - } - virtual void visit(AstAssignVarScope* nodep) VL_OVERRIDE { - movedDeleteOrIterate(nodep); - } - virtual void visit(AstAssignW* nodep) VL_OVERRIDE { - movedDeleteOrIterate(nodep); - } - virtual void visit(AstAlways* nodep) VL_OVERRIDE { - movedDeleteOrIterate(nodep); - } - virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE { - movedDeleteOrIterate(nodep); - } - virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE { - movedDeleteOrIterate(nodep); - } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { - movedDeleteOrIterate(nodep); - } - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { - movedDeleteOrIterate(nodep); - } + virtual void visit(AstInitial* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } + virtual void visit(AstFinal* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } + virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } + virtual void visit(AstAssignVarScope* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } + virtual void visit(AstAssignW* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } + virtual void visit(AstAlways* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } + virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } + virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } + virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } + virtual void visit(AstCFunc* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } virtual void visit(AstVarXRef* nodep) VL_OVERRIDE { // The crossrefs are dealt with in V3LinkDot @@ -412,17 +397,17 @@ private: } virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { // The crossrefs are dealt with in V3LinkDot - UINFO(9," Old pkg-taskref "<packagep()) { // Point to the clone UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked"); AstNodeFTask* newp = VN_CAST(nodep->taskp()->user2p(), NodeFTask); UASSERT_OBJ(newp, nodep, "No clone for package function"); nodep->taskp(newp); - UINFO(9," New pkg-taskref "<taskp(NULL); - UINFO(9," New pkg-taskref "<= 3); } diff --git a/src/V3SenTree.h b/src/V3SenTree.h index a40b495ec..50002f7d4 100644 --- a/src/V3SenTree.h +++ b/src/V3SenTree.h @@ -116,8 +116,9 @@ private: // Don't grab SenTrees under Actives, only those that are global (under Scope directly) iterateChildren(nodep); } - virtual void visit(AstSenTree* nodep) VL_OVERRIDE { m_trees.add(nodep); } - + virtual void visit(AstSenTree* nodep) VL_OVERRIDE { // + m_trees.add(nodep); + } virtual void visit(AstNodeStmt*) VL_OVERRIDE {} // Accelerate virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } diff --git a/src/V3Simulate.h b/src/V3Simulate.h index c48ee7907..ac14e601f 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -89,21 +89,21 @@ private: // STATE // Major mode - bool m_checkOnly; ///< Checking only (no simulation) mode - bool m_scoped; ///< Running with AstVarScopes instead of AstVars - bool m_params; ///< Doing parameter propagation + bool m_checkOnly; ///< Checking only (no simulation) mode + bool m_scoped; ///< Running with AstVarScopes instead of AstVars + bool m_params; ///< Doing parameter propagation // Checking: - string m_whyNotOptimizable; ///< String explaining why not optimizable or NULL to optimize - AstNode* m_whyNotNodep; ///< First node not optimizable - bool m_anyAssignDly; ///< True if found a delayed assignment - bool m_anyAssignComb; ///< True if found a non-delayed assignment - bool m_inDlyAssign; ///< Under delayed assignment - int m_instrCount; ///< Number of nodes - int m_dataCount; ///< Bytes of data - AstJumpGo* m_jumpp; ///< Jump label we're branching from + string m_whyNotOptimizable; ///< String explaining why not optimizable or NULL to optimize + AstNode* m_whyNotNodep; ///< First node not optimizable + bool m_anyAssignDly; ///< True if found a delayed assignment + bool m_anyAssignComb; ///< True if found a non-delayed assignment + bool m_inDlyAssign; ///< Under delayed assignment + int m_instrCount; ///< Number of nodes + int m_dataCount; ///< Bytes of data + AstJumpGo* m_jumpp; ///< Jump label we're branching from // Simulating: - ConstPile m_constFreeps; ///< List of all AstConst* free and not in use - ConstPile m_constAllps; ///< List of all AstConst* free and in use + ConstPile m_constFreeps; ///< List of all AstConst* free and not in use + ConstPile m_constAllps; ///< List of all AstConst* free and in use std::deque m_callStack; ///< Call stack for verbose error messages // Cleanup @@ -116,35 +116,35 @@ private: // Potentially very slow, intended for debugging string prettyNumber(const V3Number* nump, AstNodeDType* dtypep) { - if (AstRefDType* refdtypep = VN_CAST(dtypep, RefDType)) { + if (AstRefDType* refdtypep = VN_CAST(dtypep, RefDType)) { // dtypep = refdtypep->skipRefp(); } if (AstStructDType* stp = VN_CAST(dtypep, StructDType)) { if (stp->packed()) { std::ostringstream out; - out<<"'{"; - for (AstMemberDType* itemp = stp->membersp(); - itemp; itemp = VN_CAST(itemp->nextp(), MemberDType)) { + out << "'{"; + for (AstMemberDType* itemp = stp->membersp(); itemp; + itemp = VN_CAST(itemp->nextp(), MemberDType)) { int width = itemp->width(); int lsb = itemp->lsb(); int msb = lsb + width - 1; V3Number fieldNum(nump, width); fieldNum.opSel(*nump, msb, lsb); - out<name()<<": "; + out << itemp->name() << ": "; if (AstNodeDType* childTypep = itemp->subDTypep()) { - out<nextp()) out<<", "; + if (itemp->nextp()) out << ", "; } - out<<"}"; + out << "}"; return out.str(); } } else if (AstPackArrayDType* arrayp = VN_CAST(dtypep, PackArrayDType)) { if (AstNodeDType* childTypep = arrayp->subDTypep()) { std::ostringstream out; - out<<"["; + out << "["; int arrayElements = arrayp->elementsConst(); for (int element = 0; element < arrayElements; ++element) { int width = childTypep->width(); @@ -153,10 +153,10 @@ private: V3Number fieldNum(nump, width); fieldNum.opSel(*nump, msb, lsb); int arrayElem = arrayp->lsb() + element; - out<= 5) { - UINFO(0, "Clear optimizable: "<::iterator it = m_callStack.begin(); it != m_callStack.end(); ++it) { AstFuncRef* funcp = (*it)->m_funcp; - stack<<"\n "<fileline() - <<"... Called from " - <prettyName()<<"() with parameters:"; + stack << "\n " << funcp->fileline() << "... Called from " + << funcp->prettyName() << "() with parameters:"; V3TaskConnects* tconnects = (*it)->m_tconnects; for (V3TaskConnects::iterator conIt = tconnects->begin(); conIt != tconnects->end(); ++conIt) { AstVar* portp = conIt->first; AstNode* pinp = conIt->second->exprp(); AstNodeDType* dtypep = pinp->dtypep(); - stack<<"\n "<prettyName( - )<<" = "<num(), dtypep); + stack << "\n " << portp->prettyName() << " = " + << prettyNumber(&fetchConst(pinp)->num(), dtypep); } } m_whyNotOptimizable += stack.str(); @@ -216,11 +215,12 @@ private: AstConst* constp; AstNodeDType* dtypep = nodep->dtypep(); if (!m_constFreeps[dtypep].empty()) { - //UINFO(7, "Num Reuse "<width()<width() << endl); + constp = m_constFreeps[dtypep].back(); + m_constFreeps[dtypep].pop_back(); constp->num().nodep(nodep); } else { - //UINFO(7, "Num New "<width()<width() << endl); constp = new AstConst(nodep->fileline(), AstConst::DtypedValue(), nodep->dtypep(), 0); m_constAllps[constp->dtypep()].push_back(constp); } @@ -228,6 +228,7 @@ private: constp->num().isString(nodep->isString()); return constp; } + public: void newValue(AstNode* nodep, const AstNode* valuep) { if (const AstConst* constp = VN_CAST_CONST(valuep, Const)) { @@ -245,6 +246,7 @@ public: setOutValue(nodep, newTrackedClone(const_cast(valuep))); } } + private: AstNode* newTrackedClone(AstNode* nodep) { AstNode* newp = nodep->cloneTree(false); @@ -271,30 +273,26 @@ private: return fetchOutConst(nodep); } } + public: - AstNode* fetchValueNull(AstNode* nodep) { - return nodep->user3p(); - } + AstNode* fetchValueNull(AstNode* nodep) { return nodep->user3p(); } + private: - AstNode* fetchOutValueNull(AstNode* nodep) { - return nodep->user2p(); - } - AstConst* fetchConstNull(AstNode* nodep) { - return VN_CAST(fetchValueNull(nodep), Const); - } + AstNode* fetchOutValueNull(AstNode* nodep) { return nodep->user2p(); } + AstConst* fetchConstNull(AstNode* nodep) { return VN_CAST(fetchValueNull(nodep), Const); } AstConst* fetchOutConstNull(AstNode* nodep) { return VN_CAST(fetchOutValueNull(nodep), Const); } AstNode* fetchValue(AstNode* nodep) { AstNode* valuep = fetchValueNull(nodep); UASSERT_OBJ(valuep, nodep, "No value found for node."); - //UINFO(9, " fetch val "<<*valuep<<" on "<num(); return NULL; } + private: void setValue(AstNode* nodep, const AstNode* valuep) { UASSERT_OBJ(valuep, nodep, "Simulate setting null value"); - UINFO(9, " set val "<name()<<" on "<name() << " on " << nodep << endl); nodep->user3p((void*)valuep); } void setOutValue(AstNode* nodep, const AstNode* valuep) { UASSERT_OBJ(valuep, nodep, "Simulate setting null value"); - UINFO(9, " set oval "<name()<<" on "<name() << " on " << nodep << endl); nodep->user2p((void*)valuep); } @@ -331,7 +331,7 @@ private: m_dataCount += nodep->width(); } if (!nodep->isPredictOptimizable()) { - //UINFO(9, " !predictopt "<prettyTypeName()<prettyTypeName() << endl); #endif } } AstNode* varOrScope(AstVarRef* nodep) { AstNode* vscp; - if (m_scoped) vscp = nodep->varScopep(); - else vscp = nodep->varp(); + if (m_scoped) { + vscp = nodep->varScopep(); + } else { + vscp = nodep->varp(); + } UASSERT_OBJ(vscp, nodep, "Not linked"); return vscp; } @@ -420,10 +424,9 @@ private: vscp->user1(vscp->user1() | VU_RV); bool isConst = nodep->varp()->isParam() && nodep->varp()->valuep(); AstNode* valuep = isConst ? fetchValueNull(nodep->varp()->valuep()) : NULL; - if (isConst && valuep) { // Propagate PARAM constants for constant function analysis - if (!m_checkOnly && optimizable()) { - newValue(vscp, valuep); - } + if (isConst + && valuep) { // Propagate PARAM constants for constant function analysis + if (!m_checkOnly && optimizable()) newValue(vscp, valuep); } else { if (m_checkOnly) varRefCb(nodep); } @@ -437,9 +440,11 @@ private: AstNode* valuep = fetchValueNull(vscp); if (!valuep) { if (m_params) { - clearOptimizable(nodep, "Language violation: reference to non-function-local variable"); + clearOptimizable( + nodep, "Language violation: reference to non-function-local variable"); } else { - nodep->v3fatalSrc("Variable value should have been set before any visitor called."); + nodep->v3fatalSrc( + "Variable value should have been set before any visitor called."); } valuep = allocConst(nodep); // Any value; just so recover from error } @@ -449,12 +454,20 @@ private: } virtual void visit(AstVarXRef* nodep) VL_OVERRIDE { if (jumpingOver(nodep)) return; - if (m_scoped) { badNodeType(nodep); return; } - else { clearOptimizable(nodep, "Language violation: Dotted hierarchical references not allowed in constant functions"); } + if (m_scoped) { + badNodeType(nodep); + return; + } else { + clearOptimizable(nodep, "Language violation: Dotted hierarchical references not " + "allowed in constant functions"); + } } virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { if (jumpingOver(nodep)) return; - if (!m_params) { badNodeType(nodep); return; } + if (!m_params) { + badNodeType(nodep); + return; + } if (nodep->dpiImport()) { clearOptimizable(nodep, "DPI import functions aren't simulatable"); } @@ -463,7 +476,7 @@ private: } virtual void visit(AstNodeIf* nodep) VL_OVERRIDE { if (jumpingOver(nodep)) return; - UINFO(5, " IF "<itemp()->valuep(); if (valuep) { iterateAndNextNull(valuep); - if (optimizable()) { - newValue(nodep, fetchValue(valuep)); - } + if (optimizable()) newValue(nodep, fetchValue(valuep)); } else { clearOptimizable(nodep, "No value found for enum item"); } @@ -510,8 +517,7 @@ private: checkNodeInfo(nodep); iterateChildren(nodep); if (!m_checkOnly && optimizable()) { - nodep->numberOperate(newConst(nodep)->num(), - fetchConst(nodep->lhsp())->num()); + nodep->numberOperate(newConst(nodep)->num(), fetchConst(nodep->lhsp())->num()); } } virtual void visit(AstNodeBiop* nodep) VL_OVERRIDE { @@ -519,8 +525,7 @@ private: checkNodeInfo(nodep); iterateChildren(nodep); if (!m_checkOnly && optimizable()) { - nodep->numberOperate(newConst(nodep)->num(), - fetchConst(nodep->lhsp())->num(), + nodep->numberOperate(newConst(nodep)->num(), fetchConst(nodep->lhsp())->num(), fetchConst(nodep->rhsp())->num()); } } @@ -529,8 +534,7 @@ private: checkNodeInfo(nodep); iterateChildren(nodep); if (!m_checkOnly && optimizable()) { - nodep->numberOperate(newConst(nodep)->num(), - fetchConst(nodep->lhsp())->num(), + nodep->numberOperate(newConst(nodep)->num(), fetchConst(nodep->lhsp())->num(), fetchConst(nodep->rhsp())->num(), fetchConst(nodep->thsp())->num()); } @@ -652,7 +656,7 @@ private: } uint32_t index = fetchConst(selp->bitp())->toUInt(); AstNode* valuep = newTrackedClone(fetchValue(nodep->rhsp())); - UINFO(9, " set val["<addIndexValuep(index, valuep); @@ -664,7 +668,7 @@ private: AstVarRef* varrefp = NULL; V3Number lsb(nodep); iterateAndNextNull(nodep->rhsp()); // Value to assign - handleAssignSelRecurse(nodep, selp, varrefp/*ref*/, lsb/*ref*/, 0); + handleAssignSelRecurse(nodep, selp, varrefp /*ref*/, lsb /*ref*/, 0); if (!m_checkOnly && optimizable()) { UASSERT_OBJ(varrefp, nodep, "Indicated optimizable, but no variable found on RHS of select"); @@ -683,15 +687,12 @@ private: outconstp->num().setAllBitsX(); } } - outconstp->num().opSelInto(fetchConst(nodep->rhsp())->num(), - lsb, - selp->widthConst()); + outconstp->num().opSelInto(fetchConst(nodep->rhsp())->num(), lsb, selp->widthConst()); assignOutValue(nodep, vscp, outconstp); } } - void handleAssignSelRecurse(AstNodeAssign* nodep, AstSel* selp, - AstVarRef*& outVarrefpRef, V3Number& lsbRef, - int depth) { + void handleAssignSelRecurse(AstNodeAssign* nodep, AstSel* selp, AstVarRef*& outVarrefpRef, + V3Number& lsbRef, int depth) { // Recurse down to find final variable being set (outVarrefp), with // lsb to be eventually set on lsbRef checkNodeInfo(selp); @@ -702,7 +703,7 @@ private: return; // And presumably still optimizable() } else if (AstSel* subselp = VN_CAST(selp->lhsp(), Sel)) { V3Number sublsb(nodep); - handleAssignSelRecurse(nodep, subselp, outVarrefpRef, sublsb/*ref*/, depth+1); + handleAssignSelRecurse(nodep, subselp, outVarrefpRef, sublsb /*ref*/, depth + 1); if (optimizable()) { lsbRef = sublsb; lsbRef.opAdd(sublsb, fetchConst(selp->lsbp())->num()); @@ -725,20 +726,22 @@ private: } if (AstSel* selp = VN_CAST(nodep->lhsp(), Sel)) { - if (!m_params) { clearOptimizable(nodep, "LHS has select"); return; } + if (!m_params) { + clearOptimizable(nodep, "LHS has select"); + return; + } handleAssignSel(nodep, selp); - } - else if (AstArraySel* selp = VN_CAST(nodep->lhsp(), ArraySel)) { - if (!m_params) { clearOptimizable(nodep, "LHS has select"); return; } + } else if (AstArraySel* selp = VN_CAST(nodep->lhsp(), ArraySel)) { + if (!m_params) { + clearOptimizable(nodep, "LHS has select"); + return; + } handleAssignArray(nodep, selp); - } - else if (!VN_IS(nodep->lhsp(), VarRef)) { + } else if (!VN_IS(nodep->lhsp(), VarRef)) { clearOptimizable(nodep, "LHS isn't simple variable"); - } - else if (m_checkOnly) { + } else if (m_checkOnly) { iterateChildren(nodep); - } - else if (optimizable()) { + } else if (optimizable()) { iterateAndNextNull(nodep->rhsp()); if (optimizable()) { AstNode* vscp = varOrScope(VN_CAST(nodep->lhsp(), VarRef)); @@ -756,7 +759,7 @@ private: AstNode* itemp = initp->getIndexDefaultedValuep(offset); if (!itemp) { clearOptimizable(nodep, "Array initialization has too few elements, need element " - +cvtToStr(offset)); + + cvtToStr(offset)); } else { setValue(nodep, itemp); } @@ -770,15 +773,15 @@ private: } virtual void visit(AstNodeCase* nodep) VL_OVERRIDE { if (jumpingOver(nodep)) return; - UINFO(5, " CASE "<exprp()); bool hit = false; - for (AstCaseItem* itemp = nodep->itemsp(); - itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; + itemp = VN_CAST(itemp->nextp(), CaseItem)) { if (!itemp->isDefault()) { for (AstNode* ep = itemp->condsp(); ep; ep = ep->nextp()) { if (hit) break; @@ -795,8 +798,8 @@ private: } } // Else default match - for (AstCaseItem* itemp = nodep->itemsp(); - itemp; itemp = VN_CAST(itemp->nextp(), CaseItem)) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; + itemp = VN_CAST(itemp->nextp(), CaseItem)) { if (hit) break; if (!hit && itemp->isDefault()) { iterateAndNextNull(itemp->bodysp()); @@ -819,7 +822,7 @@ private: if (jumpingOver(nodep)) return; checkNodeInfo(nodep); if (!m_checkOnly) { - UINFO(5, " JUMP GO "<labelp() == nodep) { - UINFO(5, " JUMP DONE "<initsp()); while (true) { - UINFO(5, " FOR-ITER "<condp()); if (!optimizable()) break; - if (!fetchConst(nodep->condp())->num().isNeqZero()) { + if (!fetchConst(nodep->condp())->num().isNeqZero()) { // break; } iterateAndNextNull(nodep->bodysp()); iterateAndNextNull(nodep->incsp()); - if (loops++ > unrollCount()*16) { + if (loops++ > unrollCount() * 16) { clearOptimizable(nodep, "Loop unrolling took too long; probably this is an" - "infinite loop, or set --unroll-count above " - + cvtToStr(unrollCount())); + "infinite loop, or set --unroll-count above " + + cvtToStr(unrollCount())); break; } } @@ -873,21 +881,24 @@ private: virtual void visit(AstWhile* nodep) VL_OVERRIDE { // Doing lots of Whiles is slow, so only for parameters if (jumpingOver(nodep)) return; - UINFO(5, " WHILE "<precondsp()); if (jumpingOver(nodep)) break; iterateAndNextNull(nodep->condp()); if (jumpingOver(nodep)) break; if (!optimizable()) break; - if (!fetchConst(nodep->condp())->num().isNeqZero()) { + if (!fetchConst(nodep->condp())->num().isNeqZero()) { // break; } iterateAndNextNull(nodep->bodysp()); @@ -896,9 +907,11 @@ private: if (jumpingOver(nodep)) break; // Prep for next loop - if (loops++ > unrollCount()*16) { - clearOptimizable(nodep, "Loop unrolling took too long; probably this is an infinite" - " loop, or set --unroll-count above "+cvtToStr(unrollCount())); + if (loops++ > unrollCount() * 16) { + clearOptimizable(nodep, + "Loop unrolling took too long; probably this is an infinite" + " loop, or set --unroll-count above " + + cvtToStr(unrollCount())); break; } } @@ -908,12 +921,17 @@ private: virtual void visit(AstFuncRef* nodep) VL_OVERRIDE { if (jumpingOver(nodep)) return; if (!optimizable()) return; // Accelerate - UINFO(5, " FUNCREF "<taskp(), NodeFTask); UASSERT_OBJ(funcp, nodep, "Not linked"); - if (m_params) { V3Width::widthParamsEdit(funcp); } VL_DANGLING(funcp); // Make sure we've sized the function - funcp = VN_CAST(nodep->taskp(), NodeFTask); UASSERT_OBJ(funcp, nodep, "Not linked"); + if (m_params) V3Width::widthParamsEdit(funcp); + VL_DANGLING(funcp); // Make sure we've sized the function + funcp = VN_CAST(nodep->taskp(), NodeFTask); + UASSERT_OBJ(funcp, nodep, "Not linked"); // Apply function call values to function V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp()); // Must do this in two steps, eval all params, then apply them @@ -923,7 +941,9 @@ private: AstNode* pinp = it->second->exprp(); if (pinp) { // Else too few arguments in function call - ignore it if (portp->isWritable()) { - clearOptimizable(portp, "Language violation: Outputs/refs not allowed in constant functions"); + clearOptimizable( + portp, + "Language violation: Outputs/refs not allowed in constant functions"); return; } // Evaluate pin value @@ -935,9 +955,7 @@ private: AstNode* pinp = it->second->exprp(); if (pinp) { // Else too few arguments in function call - ignore it // Apply value to the function - if (!m_checkOnly && optimizable()) { - newValue(portp, fetchValue(pinp)); - } + if (!m_checkOnly && optimizable()) newValue(portp, fetchValue(pinp)); } } SimStackNode stackNode(nodep, &tconnects); @@ -954,7 +972,10 @@ private: virtual void visit(AstVar* nodep) VL_OVERRIDE { if (jumpingOver(nodep)) return; - if (!m_params) { badNodeType(nodep); return; } + if (!m_params) { + badNodeType(nodep); + return; + } } virtual void visit(AstScopeName* nodep) VL_OVERRIDE { @@ -986,7 +1007,8 @@ private: nextArgp = nextArgp->nextp(); AstConst* constp = fetchConstNull(argp); if (!constp) { - clearOptimizable(nodep, "Argument for $display like statement is not constant"); + clearOptimizable( + nodep, "Argument for $display like statement is not constant"); break; } string pformat = string("%") + pos[0]; @@ -1051,6 +1073,7 @@ private: iterate(nodep); UASSERT_OBJ(!m_jumpp, m_jumpp, "JumpGo branched to label that wasn't found"); } + public: // CONSTRUCTORS SimulateVisitor() { @@ -1076,26 +1099,24 @@ public: m_constFreeps = m_constAllps; } void mainTableCheck(AstNode* nodep) { - setMode(true/*scoped*/, true/*checking*/, false/*params*/); + setMode(true /*scoped*/, true /*checking*/, false /*params*/); mainGuts(nodep); } void mainTableEmulate(AstNode* nodep) { - setMode(true/*scoped*/, false/*checking*/, false/*params*/); + setMode(true /*scoped*/, false /*checking*/, false /*params*/); mainGuts(nodep); } void mainCheckTree(AstNode* nodep) { - setMode(false/*scoped*/, true/*checking*/, false/*params*/); + setMode(false /*scoped*/, true /*checking*/, false /*params*/); mainGuts(nodep); } void mainParamEmulate(AstNode* nodep) { - setMode(false/*scoped*/, false/*checking*/, true/*params*/); + setMode(false /*scoped*/, false /*checking*/, true /*params*/); mainGuts(nodep); } virtual ~SimulateVisitor() { - for (ConstPile::iterator it = m_constAllps.begin(); - it != m_constAllps.end(); ++it) { - for (ConstDeque::iterator it2 = it->second.begin(); - it2 != it->second.end(); ++it2) { + for (ConstPile::iterator it = m_constAllps.begin(); it != m_constAllps.end(); ++it) { + for (ConstDeque::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) { delete (*it2); } } diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index 87fab6817..c77a28bef 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -52,11 +52,11 @@ class SliceVisitor : public AstNVisitor { // AstNodeAssign::user1() -> bool. True if find is complete // AstNodeUniop::user1() -> bool. True if find is complete // AstArraySel::user1p() -> AstVarRef. The VarRef that the final ArraySel points to - AstUser1InUse m_inuser1; + AstUser1InUse m_inuser1; // STATE - AstNode* m_assignp; // Assignment we are under - bool m_assignError; // True if the current assign already has an error + AstNode* m_assignp; // Assignment we are under + bool m_assignError; // True if the current assign already has an error // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -66,54 +66,59 @@ class SliceVisitor : public AstNVisitor { AstUnpackArrayDType* arrayp = VN_CAST(nodep->dtypep()->skipRefp(), UnpackArrayDType); if (!arrayp) { // V3Width should have complained, but... if (!m_assignError) { - nodep->v3error(nodep->prettyTypeName() - <<" is not an unpacked array, but is in an unpacked array context"); + nodep->v3error( + nodep->prettyTypeName() + << " is not an unpacked array, but is in an unpacked array context"); } m_assignError = true; return nodep->cloneTree(false); // Likely will cause downstream errors } if (arrayp->rangep()->elementsConst() != elements) { - if (!m_assignError) nodep->v3error("Slices of arrays in assignments have different unpacked dimensions, " - <rangep()->elementsConst()); + if (!m_assignError) { + nodep->v3error( + "Slices of arrays in assignments have different unpacked dimensions, " + << elements << " versus " << arrayp->rangep()->elementsConst()); + } m_assignError = true; - elements = 1; offset = 0; + elements = 1; + offset = 0; } AstNode* newp; if (AstInitArray* initp = VN_CAST(nodep, InitArray)) { - UINFO(9," cloneInitArray("<rangep()->littleEndian() - ? arrayp->rangep()->elementsConst()-1-offset : offset; + ? arrayp->rangep()->elementsConst() - 1 - offset + : offset; AstNode* itemp = initp->getIndexDefaultedValuep(leOffset); if (!itemp) { - nodep->v3error("Array initialization has too few elements, need element "<v3error("Array initialization has too few elements, need element " + << offset); itemp = initp->initsp(); } newp = itemp->cloneTree(false); - } - else if (AstNodeCond* snodep = VN_CAST(nodep, NodeCond)) { - UINFO(9," cloneCond("<cloneType(snodep->condp()->cloneTree(false), cloneAndSel(snodep->expr1p(), elements, offset), cloneAndSel(snodep->expr2p(), elements, offset)); - } - else if (AstSliceSel* snodep = VN_CAST(nodep, SliceSel)) { - UINFO(9," cloneSliceSel("<declRange().lo() + (!snodep->declRange().littleEndian() - ? snodep->declRange().elements()-1-offset : offset)); + ? snodep->declRange().elements() - 1 - offset + : offset)); newp = new AstArraySel(nodep->fileline(), snodep->fromp()->cloneTree(false), leOffset); - } - else if (VN_IS(nodep, ArraySel) - || VN_IS(nodep, NodeVarRef) - || VN_IS(nodep, NodeSel)) { - UINFO(9," cloneSel("<rangep()->littleEndian() - ? arrayp->rangep()->elementsConst()-1-offset : offset; + ? arrayp->rangep()->elementsConst() - 1 - offset + : offset; newp = new AstArraySel(nodep->fileline(), nodep->cloneTree(false), leOffset); - } - else { - if (!m_assignError) nodep->v3error(nodep->prettyTypeName()<<" unexpected in assignment to unpacked array"); + } else { + if (!m_assignError) { + nodep->v3error(nodep->prettyTypeName() + << " unexpected in assignment to unpacked array"); + } m_assignError = true; newp = nodep->cloneTree(false); // Likely will cause downstream errors } @@ -122,11 +127,13 @@ class SliceVisitor : public AstNVisitor { virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { // Called recursively on newly created assignments - if (!nodep->user1() - && !VN_IS(nodep, AssignAlias)) { + if (!nodep->user1() && !VN_IS(nodep, AssignAlias)) { nodep->user1(true); m_assignError = false; - if (debug()>=9) { cout<dumpTree(cout, " Deslice-In: "); } + if (debug() >= 9) { + cout << endl; + nodep->dumpTree(cout, " Deslice-In: "); + } AstNodeDType* dtp = nodep->lhsp()->dtypep()->skipRefp(); if (AstUnpackArrayDType* arrayp = VN_CAST(dtp, UnpackArrayDType)) { // Left and right could have different msb/lsbs/endianness, but #elements is common @@ -136,13 +143,17 @@ class SliceVisitor : public AstNVisitor { int elements = arrayp->rangep()->elementsConst(); for (int offset = 0; offset < elements; ++offset) { AstNode* newp = nodep->cloneType // AstNodeAssign - (cloneAndSel(nodep->lhsp(), elements, offset), - cloneAndSel(nodep->rhsp(), elements, offset)); - if (debug()>=9) { newp->dumpTree(cout, "-new "); } + (cloneAndSel(nodep->lhsp(), elements, offset), + cloneAndSel(nodep->rhsp(), elements, offset)); + if (debug() >= 9) { newp->dumpTree(cout, "-new "); } newlistp = AstNode::addNextNull(newlistp, newp); } - if (debug()>=9) { cout<dumpTree(cout, " Deslice-Dn: "); } - nodep->replaceWith(newlistp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + if (debug() >= 9) { + cout << endl; + nodep->dumpTree(cout, " Deslice-Dn: "); + } + nodep->replaceWith(newlistp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); // Normal edit iterator will now iterate on all of the expansion assignments // This will potentially call this function again to resolve next level of slicing return; @@ -154,8 +165,7 @@ class SliceVisitor : public AstNVisitor { } virtual void visit(AstInitArray* nodep) VL_OVERRIDE { - UASSERT_OBJ(!m_assignp, nodep, - "Array initialization should have been removed earlier"); + UASSERT_OBJ(!m_assignp, nodep, "Array initialization should have been removed earlier"); } void expandBiOp(AstNodeBiop* nodep) { @@ -163,30 +173,31 @@ class SliceVisitor : public AstNVisitor { nodep->user1(true); // If it's an unpacked array, blow it up into comparing each element AstNodeDType* fromDtp = nodep->lhsp()->dtypep()->skipRefp(); - UINFO(9, " Bi-Eq/Neq expansion "<lhsp()->dtypep()->skipRefp(), NodeArrayDType)) { - nodep->lhsp()->v3error("Slice operator "<lhsp()->prettyTypeName() - <<" on non-slicable (e.g. non-vector) left-hand-side operand"); - } - else if (!VN_IS(nodep->rhsp()->dtypep()->skipRefp(), NodeArrayDType)) { - nodep->rhsp()->v3error("Slice operator "<rhsp()->prettyTypeName() - <<" on non-slicable (e.g. non-vector) right-hand-side operand"); - } - else { + nodep->lhsp()->v3error( + "Slice operator " + << nodep->lhsp()->prettyTypeName() + << " on non-slicable (e.g. non-vector) left-hand-side operand"); + } else if (!VN_IS(nodep->rhsp()->dtypep()->skipRefp(), NodeArrayDType)) { + nodep->rhsp()->v3error( + "Slice operator " + << nodep->rhsp()->prettyTypeName() + << " on non-slicable (e.g. non-vector) right-hand-side operand"); + } else { for (int index = 0; index < adtypep->rangep()->elementsConst(); ++index) { // EQ(a,b) -> LOGAND(EQ(ARRAYSEL(a,0), ARRAYSEL(b,0)), ...[1]) AstNodeBiop* clonep - = VN_CAST(nodep->cloneType - (new AstArraySel(nodep->fileline(), - nodep->lhsp()->cloneTree(false), - index), - new AstArraySel(nodep->fileline(), - nodep->rhsp()->cloneTree(false), - index)), + = VN_CAST(nodep->cloneType( + new AstArraySel(nodep->fileline(), + nodep->lhsp()->cloneTree(false), index), + new AstArraySel(nodep->fileline(), + nodep->rhsp()->cloneTree(false), index)), NodeBiop); - if (!logp) logp = clonep; + if (!logp) + logp = clonep; else { switch (nodep->type()) { case AstType::atEq: // FALLTHRU @@ -212,18 +223,10 @@ class SliceVisitor : public AstNVisitor { iterateChildren(nodep); } } - virtual void visit(AstEq* nodep) VL_OVERRIDE { - expandBiOp(nodep); - } - virtual void visit(AstNeq* nodep) VL_OVERRIDE { - expandBiOp(nodep); - } - virtual void visit(AstEqCase* nodep) VL_OVERRIDE { - expandBiOp(nodep); - } - virtual void visit(AstNeqCase* nodep) VL_OVERRIDE { - expandBiOp(nodep); - } + virtual void visit(AstEq* nodep) VL_OVERRIDE { expandBiOp(nodep); } + virtual void visit(AstNeq* nodep) VL_OVERRIDE { expandBiOp(nodep); } + virtual void visit(AstEqCase* nodep) VL_OVERRIDE { expandBiOp(nodep); } + virtual void visit(AstNeqCase* nodep) VL_OVERRIDE { expandBiOp(nodep); } virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } @@ -241,9 +244,7 @@ public: // Link class functions void V3Slice::sliceAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Split.cpp b/src/V3Split.cpp index cbfba4dee..6e69257d3 100644 --- a/src/V3Split.cpp +++ b/src/V3Split.cpp @@ -97,18 +97,19 @@ // Support classes class SplitNodeVertex : public V3GraphVertex { - AstNode* m_nodep; + AstNode* m_nodep; + protected: SplitNodeVertex(V3Graph* graphp, AstNode* nodep) - : V3GraphVertex(graphp), m_nodep(nodep) {} + : V3GraphVertex(graphp) + , m_nodep(nodep) {} virtual ~SplitNodeVertex() {} // ACCESSORS // Do not make accessor for nodep(), It may change due to // reordering a lower block, but we don't repair it - virtual string name() const { - return cvtToHex(m_nodep) + ' ' + m_nodep->prettyTypeName(); - } + virtual string name() const { return cvtToHex(m_nodep) + ' ' + m_nodep->prettyTypeName(); } virtual FileLine* fileline() const { return nodep()->fileline(); } + public: virtual AstNode* nodep() const { return m_nodep; } }; @@ -143,7 +144,7 @@ public: SplitVarPostVertex(V3Graph* graphp, AstNode* nodep) : SplitNodeVertex(graphp, nodep) {} virtual ~SplitVarPostVertex() {} - virtual string name() const { return string("POST ")+SplitNodeVertex::name(); } + virtual string name() const { return string("POST ") + SplitNodeVertex::name(); } virtual string dotColor() const { return "CadetBlue"; } }; @@ -155,11 +156,12 @@ class SplitEdge : public V3GraphEdge { static uint32_t s_stepNum; // Global step number protected: enum { WEIGHT_NORMAL = 10 }; - SplitEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, - int weight, bool cutable=CUTABLE) + SplitEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight, + bool cutable = CUTABLE) : V3GraphEdge(graphp, fromp, top, weight, cutable) , m_ignoreInStep(0) {} virtual ~SplitEdge() {} + public: // Iterator for graph functions static void incrementStep() { ++s_stepNum; } @@ -181,7 +183,7 @@ public: return ignoreThisStep() ? "dotted" : V3GraphEdge::dotStyle(); } }; -uint32_t SplitEdge::s_stepNum = 0; +uint32_t SplitEdge::s_stepNum = 0; class SplitPostEdge : public SplitEdge { public: @@ -240,28 +242,26 @@ private: // AstVarScope::user2p -> Var SplitNodeVertex* for delayed assignment var, 0=not set yet // Ast*::user3p -> Statement SplitLogicVertex* (temporary only) // Ast*::user4 -> Current ordering number (reorderBlock usage) - AstUser1InUse m_inuser1; - AstUser2InUse m_inuser2; - AstUser3InUse m_inuser3; - AstUser4InUse m_inuser4; + AstUser1InUse m_inuser1; + AstUser2InUse m_inuser2; + AstUser3InUse m_inuser3; + AstUser4InUse m_inuser4; protected: // TYPES typedef std::vector VStack; // STATE - string m_noReorderWhy; // Reason we can't reorder - VStack m_stmtStackps; // Current statements being tracked - SplitPliVertex* m_pliVertexp; // Element specifying PLI ordering - V3Graph m_graph; // Scoreboard of var usages/dependencies - bool m_inDly; // Inside ASSIGNDLY - VDouble0 m_statSplits; // Statistic tracking + string m_noReorderWhy; // Reason we can't reorder + VStack m_stmtStackps; // Current statements being tracked + SplitPliVertex* m_pliVertexp; // Element specifying PLI ordering + V3Graph m_graph; // Scoreboard of var usages/dependencies + bool m_inDly; // Inside ASSIGNDLY + VDouble0 m_statSplits; // Statistic tracking // CONSTRUCTORS public: - SplitReorderBaseVisitor() { - scoreboardClear(); - } + SplitReorderBaseVisitor() { scoreboardClear(); } virtual ~SplitReorderBaseVisitor() { V3Stats::addStat("Optimizations, Split always", m_statSplits); } @@ -271,7 +271,7 @@ protected: VL_DEBUG_FUNC; // Declare debug() void scoreboardClear() { - //VV***** We reset user1p() and user2p on each block!!! + // VV***** We reset user1p() and user2p on each block!!! m_inDly = false; m_graph.clear(); m_stmtStackps.clear(); @@ -298,14 +298,14 @@ private: } } void scoreboardPushStmt(AstNode* nodep) { - //UINFO(9," push "<user3p(), nodep, "user3p should not be used; cleared in processBlock"); nodep->user3p(vertexp); } void scoreboardPopStmt() { - //UINFO(9," pop"<nextp()) { + for (AstNode* nextp = nodep; nextp; nextp = nextp->nextp()) { scoreboardPushStmt(nextp); iterate(nextp); scoreboardPopStmt(); @@ -321,17 +321,15 @@ protected: } void pruneDepsOnInputs() { - for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); - vertexp; vertexp=vertexp->verticesNextp()) { - if (!vertexp->outBeginp() - && dynamic_cast(vertexp)) { + for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp; + vertexp = vertexp->verticesNextp()) { + if (!vertexp->outBeginp() && dynamic_cast(vertexp)) { if (debug() >= 9) { SplitVarStdVertex* stdp = static_cast(vertexp); - UINFO(0, "Will prune deps on var "<nodep()<nodep() << endl); stdp->nodep()->dumpTree(cout, "- "); } - for (V3GraphEdge* edgep = vertexp->inBeginp(); - edgep; edgep=edgep->inNextp()) { + for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { SplitEdge* oedgep = dynamic_cast(edgep); oedgep->setIgnoreThisStep(); } @@ -350,7 +348,7 @@ protected: virtual void visit(AstAssignDly* nodep) VL_OVERRIDE { m_inDly = true; - UINFO(4," ASSIGNDLY "<lvalue()) { - UINFO(4," VARREFDLY: "<user2p()) { SplitVarPostVertex* vpostp = new SplitVarPostVertex(&m_graph, vscp); @@ -396,21 +394,21 @@ protected: SplitVarPostVertex* vpostp = reinterpret_cast(vscp->user2p()); // Add edges - for (VStack::iterator it = m_stmtStackps.begin(); - it != m_stmtStackps.end(); ++it) { + for (VStack::iterator it = m_stmtStackps.begin(); it != m_stmtStackps.end(); + ++it) { new SplitLVEdge(&m_graph, vpostp, *it); } } else { // Nondelayed assignment if (nodep->lvalue()) { // Non-delay; need to maintain existing ordering // with all consumers of the signal - UINFO(4," VARREFLV: "<isPure()) { - UINFO(9," NotSplittable "<=9) { + if (debug() >= 9) { m_graph.dumpDotFilePrefixed("reorderg_nodup", false); - //m_graph.dump(); cout<nextp()) { + for (AstNode* nextp = nodep; nextp; nextp = nextp->nextp()) { SplitLogicVertex* vvertexp = reinterpret_cast(nextp->user3p()); vvertexp->user(true); } @@ -484,16 +480,17 @@ protected: // For reordering this single block only, mark all logic // vertexes not involved with this step as unimportant - for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); - vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp; + vertexp = vertexp->verticesNextp()) { if (SplitLogicVertex* vvertexp = dynamic_cast(vertexp)) { if (!vvertexp->user()) { - for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep=edgep->inNextp()) { + for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; + edgep = edgep->inNextp()) { SplitEdge* oedgep = dynamic_cast(edgep); oedgep->setIgnoreThisStep(); } - for (V3GraphEdge* edgep = vertexp->outBeginp(); - edgep; edgep=edgep->outNextp()) { + for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; + edgep = edgep->outNextp()) { SplitEdge* oedgep = dynamic_cast(edgep); oedgep->setIgnoreThisStep(); } @@ -507,7 +504,7 @@ protected: // Add hard orderings between all nodes of same color, in the order they appeared vl_unordered_map lastOfColor; - for (AstNode* nextp=nodep; nextp; nextp=nextp->nextp()) { + for (AstNode* nextp = nodep; nextp; nextp = nextp->nextp()) { SplitLogicVertex* vvertexp = reinterpret_cast(nextp->user3p()); uint32_t color = vvertexp->color(); UASSERT_OBJ(color, nextp, "No node color assigned"); @@ -520,20 +517,20 @@ protected: // And a real ordering to get the statements into something reasonable // We don't care if there's cutable violations here... // Non-cutable violations should be impossible; as those edges are program-order - if (debug()>=9) m_graph.dumpDotFilePrefixed(string("splitg_preo"), false); + if (debug() >= 9) m_graph.dumpDotFilePrefixed(string("splitg_preo"), false); m_graph.acyclic(&SplitEdge::followCyclic); m_graph.rank(&SplitEdge::followCyclic); // Or order(), but that's more expensive - if (debug()>=9) m_graph.dumpDotFilePrefixed(string("splitg_opt"), false); + if (debug() >= 9) m_graph.dumpDotFilePrefixed(string("splitg_opt"), false); } void reorderBlock(AstNode* nodep) { // Reorder statements in the completed graph // Map the rank numbers into nodes they associate with - typedef std::multimap RankNodeMap; + typedef std::multimap RankNodeMap; RankNodeMap rankMap; int currOrder = 0; // Existing sequence number of assignment - for (AstNode* nextp=nodep; nextp; nextp=nextp->nextp()) { + for (AstNode* nextp = nodep; nextp; nextp = nextp->nextp()) { SplitLogicVertex* vvertexp = reinterpret_cast(nextp->user3p()); rankMap.insert(make_pair(vvertexp->rank(), nextp)); nextp->user4(++currOrder); // Record current ordering @@ -542,23 +539,28 @@ protected: // Is the current ordering OK? bool leaveAlone = true; int newOrder = 0; // New sequence number of assignment - for (RankNodeMap::const_iterator it = rankMap.begin(); - it != rankMap.end(); ++it) { + for (RankNodeMap::const_iterator it = rankMap.begin(); it != rankMap.end(); ++it) { AstNode* nextp = it->second; if (++newOrder != nextp->user4()) leaveAlone = false; } if (leaveAlone) { - UINFO(6," No changes\n"); + UINFO(6, " No changes\n"); } else { AstNRelinker replaceHandle; // Where to add the list AstNode* newListp = NULL; for (RankNodeMap::const_iterator it = rankMap.begin(); it != rankMap.end(); ++it) { AstNode* nextp = it->second; - UINFO(6, " New order: "<unlinkFrBack(&replaceHandle); - else nextp->unlinkFrBack(); - if (newListp) newListp = newListp->addNext(nextp); - else newListp = nextp; + UINFO(6, " New order: " << nextp << endl); + if (nextp == nodep) { + nodep->unlinkFrBack(&replaceHandle); + } else { + nextp->unlinkFrBack(); + } + if (newListp) { + newListp = newListp->addNext(nextp); + } else { + newListp = nextp; + } } replaceHandle.relink(newListp); } @@ -579,19 +581,19 @@ protected: // Just one, so can't reorder. Just look for more blocks/statements. iterate(nodep); } else { - UINFO(9," processBlock "<backp()->nextp()==firstp) firstp = firstp->backp(); - for (AstNode* nextp=firstp; nextp; nextp=nextp->nextp()) { + while (firstp->backp()->nextp() == firstp) firstp = firstp->backp(); + for (AstNode* nextp = firstp; nextp; nextp = nextp->nextp()) { SplitLogicVertex* vvertexp = reinterpret_cast(nextp->user3p()); vvertexp->unlinkDelete(&m_graph); @@ -603,19 +605,20 @@ protected: } virtual void visit(AstAlways* nodep) VL_OVERRIDE { - UINFO(4," ALW "<=9) nodep->dumpTree(cout, " alwIn:: "); + UINFO(4, " ALW " << nodep << endl); + if (debug() >= 9) nodep->dumpTree(cout, " alwIn:: "); scoreboardClear(); processBlock(nodep->bodysp()); - if (debug()>=9) nodep->dumpTree(cout, " alwOut: "); + if (debug() >= 9) nodep->dumpTree(cout, " alwOut: "); } virtual void visit(AstNodeIf* nodep) VL_OVERRIDE { - UINFO(4," IF "<condp()); processBlock(nodep->ifsp()); processBlock(nodep->elsesp()); } + private: VL_UNCOPYABLE(ReorderVisitor); }; @@ -638,9 +641,7 @@ class IfColorVisitor : public AstNVisitor { public: // Visit through *nodep and map each AstNodeIf within to the set of // colors it will participate in. Also find the whole set of colors. - explicit IfColorVisitor(AstAlways* nodep) { - iterate(nodep); - } + explicit IfColorVisitor(AstAlways* nodep) { iterate(nodep); } virtual ~IfColorVisitor() {} // METHODS @@ -660,8 +661,7 @@ private: UINFO(8, " SVL " << vertexp << " has color " << color << "\n"); // Record that all containing ifs have this color. - for (IfStack::const_iterator it = m_ifStack.begin(); - it != m_ifStack.end(); ++it) { + for (IfStack::const_iterator it = m_ifStack.begin(); it != m_ifStack.end(); ++it) { m_ifColors[*it].insert(color); } } @@ -700,9 +700,7 @@ public: // EmitSplitVisitor visits through always block *nodep // and generates its split blocks, writing the split blocks // into *newBlocksp. - EmitSplitVisitor(AstAlways* nodep, - const IfColorVisitor* ifColorp, - AlwaysVec* newBlocksp) + EmitSplitVisitor(AstAlways* nodep, const IfColorVisitor* ifColorp, AlwaysVec* newBlocksp) : m_origAlwaysp(nodep) , m_ifColorp(ifColorp) , m_newBlocksp(newBlocksp) { @@ -715,13 +713,11 @@ public: void go() { // Create a new always for each color const ColorSet& colors = m_ifColorp->colors(); - for (ColorSet::const_iterator color = colors.begin(); - color != colors.end(); ++color) { + for (ColorSet::const_iterator color = colors.begin(); color != colors.end(); ++color) { // We don't need to clone m_origAlwaysp->sensesp() here; // V3Activate already moved it to a parent node. - AstAlways* alwaysp = - new AstAlways(m_origAlwaysp->fileline(), VAlwaysKwd::ALWAYS, - NULL, NULL); + AstAlways* alwaysp + = new AstAlways(m_origAlwaysp->fileline(), VAlwaysKwd::ALWAYS, NULL, NULL); // Put a placeholder node into stmtp to track our position. // We'll strip these out after the blocks are fully cloned. AstSplitPlaceholder* placeholderp = makePlaceholderp(); @@ -769,16 +765,12 @@ protected: typedef vl_unordered_map CloneMap; CloneMap clones; - for (ColorSet::const_iterator color = colors.begin(); - color != colors.end(); ++color) { + for (ColorSet::const_iterator color = colors.begin(); color != colors.end(); ++color) { // Clone this if into its set of split blocks AstSplitPlaceholder* if_placeholderp = makePlaceholderp(); AstSplitPlaceholder* else_placeholderp = makePlaceholderp(); - AstIf* clonep = - new AstIf(nodep->fileline(), - nodep->condp()->cloneTree(true), - if_placeholderp, - else_placeholderp); + AstIf* clonep = new AstIf(nodep->fileline(), nodep->condp()->cloneTree(true), + if_placeholderp, else_placeholderp); AstIf* origp = VN_CAST(nodep, If); if (origp) { // Preserve pragmas from unique if's @@ -794,15 +786,13 @@ protected: iterateAndNextNull(nodep->ifsp()); - for (ColorSet::const_iterator color = colors.begin(); - color != colors.end(); ++color) { + for (ColorSet::const_iterator color = colors.begin(); color != colors.end(); ++color) { m_addAfter[*color] = clones[*color]->elsesp(); } iterateAndNextNull(nodep->elsesp()); - for (ColorSet::const_iterator color = colors.begin(); - color != colors.end(); ++color) { + for (ColorSet::const_iterator color = colors.begin(); color != colors.end(); ++color) { m_addAfter[*color] = clones[*color]; } } @@ -817,17 +807,14 @@ class RemovePlaceholdersVisitor : public AstNVisitor { public: explicit RemovePlaceholdersVisitor(AstNode* nodep) { iterate(nodep); - for (NodeSet::const_iterator it = m_removeSet.begin(); - it != m_removeSet.end(); ++it) { + for (NodeSet::const_iterator it = m_removeSet.begin(); it != m_removeSet.end(); ++it) { AstNode* np = *it; np->unlinkFrBack(); // Without next VL_DO_DANGLING(np->deleteTree(), np); } } virtual ~RemovePlaceholdersVisitor() {} - virtual void visit(AstSplitPlaceholder* nodep) VL_OVERRIDE { - m_removeSet.insert(nodep); - } + virtual void visit(AstSplitPlaceholder* nodep) VL_OVERRIDE { m_removeSet.insert(nodep); } virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } private: @@ -854,11 +841,11 @@ public: // Splice newly-split blocks into the tree. Remove placeholders // from newly-split blocks. Delete the original always blocks // that we're replacing. - for (ReplaceMap::iterator it = m_replaceBlocks.begin(); - it != m_replaceBlocks.end(); ++it) { + for (ReplaceMap::iterator it = m_replaceBlocks.begin(); it != m_replaceBlocks.end(); + ++it) { AstAlways* origp = it->first; - for (AlwaysVec::iterator addme = it->second.begin(); - addme != it->second.end(); ++addme) { + for (AlwaysVec::iterator addme = it->second.begin(); addme != it->second.end(); + ++addme) { origp->addNextHere(*addme); RemovePlaceholdersVisitor removePlaceholders(*addme); } @@ -876,9 +863,7 @@ protected: // not rvalues in the if/else bodies. for (VStack::const_iterator it = m_stmtStackps.begin(); it != m_stmtStackps.end(); ++it) { AstNodeIf* ifNodep = VN_CAST((*it)->nodep(), NodeIf); - if (ifNodep && (m_curIfConditional != ifNodep)) { - continue; - } + if (ifNodep && (m_curIfConditional != ifNodep)) continue; new SplitRVEdge(&m_graph, *it, vstdp); } } @@ -899,8 +884,8 @@ protected: // For any 'if' node whose deps have all been pruned // (meaning, its conditional expression only looks at primary // inputs) prune all edges that depend on the 'if'. - for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); - vertexp; vertexp=vertexp->verticesNextp()) { + for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp; + vertexp = vertexp->verticesNextp()) { SplitLogicVertex* logicp = dynamic_cast(vertexp); if (!logicp) continue; @@ -908,8 +893,7 @@ protected: if (!ifNodep) continue; bool pruneMe = true; - for (V3GraphEdge* edgep = logicp->outBeginp(); - edgep; edgep = edgep->outNextp()) { + for (V3GraphEdge* edgep = logicp->outBeginp(); edgep; edgep = edgep->outNextp()) { SplitEdge* oedgep = dynamic_cast(edgep); if (!oedgep->ignoreThisStep()) { // This if conditional depends on something we can't @@ -921,8 +905,8 @@ protected: if (debug() >= 9) { V3GraphVertex* vxp = oedgep->top(); SplitNodeVertex* nvxp = dynamic_cast(vxp); - UINFO(0, "Cannot prune if-node due to edge "<nodep()<nodep() << endl); nvxp->nodep()->dumpTree(cout, "- "); } @@ -933,21 +917,20 @@ protected: if (!pruneMe) continue; // This if can be split; prune dependencies on it. - for (V3GraphEdge* edgep = logicp->inBeginp(); - edgep; edgep = edgep->inNextp()) { + for (V3GraphEdge* edgep = logicp->inBeginp(); edgep; edgep = edgep->inNextp()) { SplitEdge* oedgep = dynamic_cast(edgep); oedgep->setIgnoreThisStep(); } } - if (debug()>=9) m_graph.dumpDotFilePrefixed("splitg_nodup", false); + if (debug() >= 9) m_graph.dumpDotFilePrefixed("splitg_nodup", false); // Weak coloring to determine what needs to remain grouped // in a single always. This follows all edges excluding: // - those we pruned above // - PostEdges, which are done later m_graph.weaklyConnected(&SplitEdge::followScoreboard); - if (debug()>=9) m_graph.dumpDotFilePrefixed("splitg_colored", false); + if (debug() >= 9) m_graph.dumpDotFilePrefixed("splitg_colored", false); } virtual void visit(AstAlways* nodep) VL_OVERRIDE { @@ -957,13 +940,13 @@ protected: if (m_noReorderWhy != "") { // We saw a jump or something else rare that we don't handle. - UINFO(9," NoSplitBlock because "<condp()); m_curIfConditional = NULL; scanBlock(nodep->ifsp()); scanBlock(nodep->elsesp()); } + private: VL_UNCOPYABLE(SplitVisitor); }; @@ -999,16 +982,12 @@ private: // Split class functions void V3Split::splitReorderAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } void V3Split::splitAlwaysAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3SplitAs.cpp b/src/V3SplitAs.cpp index 0a4b76736..d600cc819 100644 --- a/src/V3SplitAs.cpp +++ b/src/V3SplitAs.cpp @@ -52,8 +52,7 @@ private: // METHODS virtual void visit(AstVarRef* nodep) VL_OVERRIDE { - if (nodep->lvalue() && !m_splitVscp - && nodep->varp()->attrIsolateAssign()) { + if (nodep->lvalue() && !m_splitVscp && nodep->varp()->attrIsolateAssign()) { m_splitVscp = nodep->varScopep(); } } @@ -76,16 +75,16 @@ public: class SplitAsCleanVisitor : public SplitAsBaseVisitor { private: // STATE - AstVarScope* m_splitVscp; // Variable we want to split - bool m_modeMatch; // Remove matching Vscp, else non-matching - bool m_keepStmt; // Current Statement must be preserved - bool m_matches; // Statement below has matching lvalue reference + AstVarScope* m_splitVscp; // Variable we want to split + bool m_modeMatch; // Remove matching Vscp, else non-matching + bool m_keepStmt; // Current Statement must be preserved + bool m_matches; // Statement below has matching lvalue reference // METHODS virtual void visit(AstVarRef* nodep) VL_OVERRIDE { if (nodep->lvalue()) { - if (nodep->varScopep()==m_splitVscp) { - UINFO(6," CL VAR "<varScopep() == m_splitVscp) { + UINFO(6, " CL VAR " << nodep << endl); m_matches = true; } } @@ -95,7 +94,7 @@ private: iterateChildren(nodep); return; } - UINFO(6," CL STMT "<unlinkFrBack(); pushDeletep(nodep); + UINFO(6, " Delete STMT " << nodep << endl); + nodep->unlinkFrBack(); + pushDeletep(nodep); } } // If something below matches, the upper statement remains too. m_keepStmt = oldKeep || m_keepStmt; - UINFO(9," upKeep="< bool. True if already processed - AstUser1InUse m_inuser1; + AstUser1InUse m_inuser1; // STATE VDouble0 m_statSplits; // Statistic tracking @@ -145,20 +144,20 @@ private: // METHODS void splitAlways(AstAlways* nodep) { - UINFO(3,"Split "<=9) nodep->dumpTree(cout, "-in : "); + UINFO(3, "Split " << nodep << endl); + UINFO(3, " For " << m_splitVscp << endl); + if (debug() >= 9) nodep->dumpTree(cout, "-in : "); // Duplicate it and link in AstAlways* newp = nodep->cloneTree(false); newp->user1(true); // So we don't clone it again nodep->addNextHere(newp); - { // Delete stuff we don't want in old - SplitAsCleanVisitor visitor (nodep, m_splitVscp, false); - if (debug()>=9) nodep->dumpTree(cout, "-out0: "); + { // Delete stuff we don't want in old + SplitAsCleanVisitor visitor(nodep, m_splitVscp, false); + if (debug() >= 9) nodep->dumpTree(cout, "-out0: "); } - { // Delete stuff we don't want in new - SplitAsCleanVisitor visitor (newp, m_splitVscp, true); - if (debug()>=9) newp->dumpTree(cout, "-out1: "); + { // Delete stuff we don't want in new + SplitAsCleanVisitor visitor(newp, m_splitVscp, true); + if (debug() >= 9) newp->dumpTree(cout, "-out1: "); } } @@ -168,13 +167,12 @@ private: AstVarScope* lastSplitVscp = NULL; while (!nodep->user1()) { // Find any splittable variables - SplitAsFindVisitor visitor (nodep); + SplitAsFindVisitor visitor(nodep); m_splitVscp = visitor.splitVscp(); if (m_splitVscp && m_splitVscp == lastSplitVscp) { // We did this last time! Something's stuck! nodep->v3fatalSrc("Infinite loop in isolate_assignments removal for: " - <prettyNameQ()) - m_splitVscp = NULL; + << m_splitVscp->prettyNameQ()); } lastSplitVscp = m_splitVscp; // Now isolate the always @@ -207,9 +205,7 @@ public: // SplitAs class functions void V3SplitAs::splitAsAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3SplitVar.cpp b/src/V3SplitVar.cpp index fe0f9c057..51d96d6cf 100644 --- a/src/V3SplitVar.cpp +++ b/src/V3SplitVar.cpp @@ -133,7 +133,7 @@ struct SplitVarImpl { return new AstAssign(fileline, lhsp, rhsp); } else { return new AstAssignW(fileline, lhsp, rhsp); - } + } } static const char* const notSplitMsg; @@ -523,10 +523,10 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { iterate(argp); if (reason) { for (VarSet::iterator it = m_foundTargetVar.begin(), - it_end = m_foundTargetVar.end(); + it_end = m_foundTargetVar.end(); it != it_end; ++it) { argp->v3warn(SPLITVAR, (*it)->prettyNameQ() - << notSplitMsg << reason << ".\n"); + << notSplitMsg << reason << ".\n"); m_refs.remove(*it); } } @@ -574,7 +574,7 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { m_refsForPackedSplit[m_modp].add(nodep); } virtual void visit(AstSel* nodep) VL_OVERRIDE { - if (VN_IS(nodep->fromp(), VarRef)) m_refsForPackedSplit[m_modp].add(nodep); + if (VN_IS(nodep->fromp(), VarRef)) m_refsForPackedSplit[m_modp].add(nodep); iterateChildren(nodep); } virtual void visit(AstArraySel* nodep) VL_OVERRIDE { @@ -815,8 +815,10 @@ public: if (dim.second < 1 || !VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType)) reason = "it is not an unpacked array"; if (!reason) reason = cannotSplitVarCommonReason(nodep); - if (reason) UINFO(5, "Check " << nodep->prettyNameQ() - << " cannot split because" << reason << ".\n"); + if (reason) { + UINFO(5, + "Check " << nodep->prettyNameQ() << " cannot split because" << reason << ".\n"); + } return reason; } }; @@ -900,7 +902,7 @@ class PackedVarRef { std::vector vect; vect.reserve(nodes.size()); for (vl_unordered_map::const_iterator it = nodes.begin(), - it_end = nodes.end(); + it_end = nodes.end(); it != it_end; ++it) { vect.push_back(refs[it->second]); } @@ -1047,11 +1049,13 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { PackedVarRefEntry(nodep, consts[0]->toSInt() + refit->second.basicp()->lsb(), consts[1]->toUInt()), vrefp->lvalue()); - UINFO(5, varp->prettyName() << " [" << consts[0]->toSInt() << ":+" - << consts[1]->toSInt() << "] lsb:" << refit->second.basicp()->lsb() << "\n"); + UINFO(5, varp->prettyName() + << " [" << consts[0]->toSInt() << ":+" << consts[1]->toSInt() + << "] lsb:" << refit->second.basicp()->lsb() << "\n"); } else { - nodep->v3warn(SPLITVAR, vrefp->prettyNameQ() << notSplitMsg - << "its bit range cannot be determined statically."); + nodep->v3warn(SPLITVAR, vrefp->prettyNameQ() + << notSplitMsg + << "its bit range cannot be determined statically."); if (!consts[0]) { UINFO(4, "LSB " << nodep->lsbp() << " is expected to be constant, but not\n"); } @@ -1076,7 +1080,7 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { const int msb = std::min(ref.msb(), var.msb()); const int bitwidth = msb + 1 - lsb; UINFO(4, var.varp()->prettyNameQ() << "[" << msb << ":" << lsb << "] used for " - << ref.nodep()->prettyNameQ() << '\n'); + << ref.nodep()->prettyNameQ() << '\n'); // LSB of varp is always 0. "lsb - var.lsb()" means this. see also SplitNewVar AstSel* selp = new AstSel(ref.nodep()->fileline(), refp, lsb - var.lsb(), bitwidth); return selp; @@ -1091,9 +1095,9 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { } const bool in = portp->isReadOnly(); for (size_t i = 0; i < vars.size(); ++i) { - AstNode* rhsp = new AstSel(portp->fileline(), - new AstVarRef(portp->fileline(), portp, !in), - vars[i].lsb(), vars[i].bitwidth()); + AstNode* rhsp + = new AstSel(portp->fileline(), new AstVarRef(portp->fileline(), portp, !in), + vars[i].lsb(), vars[i].bitwidth()); AstNode* lhsp = new AstVarRef(portp->fileline(), vars[i].varp(), in); if (!in) std::swap(lhsp, rhsp); AstNodeAssign* assignp = newAssign(portp->fileline(), lhsp, rhsp, portp); @@ -1117,8 +1121,7 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { = (left == right) ? varp->name() + "__BRA__" + AstNode::encodeNumber(left) + "__KET__" : varp->name() + "__BRA__" + AstNode::encodeNumber(left) - + AstNode::encodeName(":") + AstNode::encodeNumber(right) - + "__KET__"; + + AstNode::encodeName(":") + AstNode::encodeNumber(right) + "__KET__"; AstBasicDType* dtypep; switch (basicp->keyword()) { @@ -1226,9 +1229,8 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { new AstVarRef(varp->fileline(), vars[i].varp(), false), rhsp); } - varp->addNextHere(newAssign(varp->fileline(), - new AstVarRef(varp->fileline(), varp, true), - rhsp, varp)); + varp->addNextHere(newAssign( + varp->fileline(), new AstVarRef(varp->fileline(), varp, true), rhsp, varp)); } else { // the original variable is not used anymore. VL_DO_DANGLING(varp->unlinkFrBack()->deleteTree(), varp); } @@ -1274,8 +1276,9 @@ public: } else { reason = "its type is unknown"; } - if (reason) UINFO(5, "Check " << nodep->prettyNameQ() - << " cannot split because" << reason << endl); + if (reason) + UINFO(5, + "Check " << nodep->prettyNameQ() << " cannot split because" << reason << endl); return reason; } VL_DEBUG_FUNC; // Declare debug() diff --git a/src/V3Subst.cpp b/src/V3Subst.cpp index 6c4eee97b..f79964434 100644 --- a/src/V3Subst.cpp +++ b/src/V3Subst.cpp @@ -49,10 +49,10 @@ public: class SubstVarWord { protected: // MEMBERS - AstNodeAssign* m_assignp; // Last assignment to each word of this var - int m_step; // Step number of last assignment - bool m_use; // True if each word was consumed - bool m_complex; // True if each word is complex + AstNodeAssign* m_assignp; // Last assignment to each word of this var + int m_step; // Step number of last assignment + bool m_use; // True if each word was consumed + bool m_complex; // True if each word is complex friend class SubstVarEntry; // METHODS void clear() { @@ -68,10 +68,10 @@ protected: class SubstVarEntry { // MEMBERS - AstVar* m_varp; // Variable this tracks - bool m_wordAssign; // True if any word assignments - bool m_wordUse; // True if any individual word usage - SubstVarWord m_whole; // Data for whole vector used at once + AstVar* m_varp; // Variable this tracks + bool m_wordAssign; // True if any word assignments + bool m_wordUse; // True if any individual word usage + SubstVarWord m_whole; // Data for whole vector used at once std::vector m_words; // Data for every word, if multi word variable int debug() { return SubstBaseVisitor::debug(); } @@ -83,20 +83,21 @@ public: m_wordUse = false; m_words.resize(varp->widthWords()); m_whole.clear(); - for (int i=0; iwidthWords(); i++) { - m_words[i].clear(); - } + for (int i = 0; i < varp->widthWords(); i++) m_words[i].clear(); } ~SubstVarEntry() {} + private: // METHODS - bool wordNumOk(int word) const { - return word < m_varp->widthWords(); - } + bool wordNumOk(int word) const { return word < m_varp->widthWords(); } AstNodeAssign* getWordAssignp(int word) const { - if (!wordNumOk(word)) return NULL; - else return m_words[word].m_assignp; + if (!wordNumOk(word)) { + return NULL; + } else { + return m_words[word].m_assignp; + } } + public: void assignWhole(int step, AstNodeAssign* assp) { if (m_whole.m_assignp) m_whole.m_complex = true; @@ -104,8 +105,9 @@ public: m_whole.m_step = step; } void assignWord(int step, int word, AstNodeAssign* assp) { - if (!wordNumOk(word) || getWordAssignp(word) - || m_words[word].m_complex) m_whole.m_complex = true; + if (!wordNumOk(word) || getWordAssignp(word) || m_words[word].m_complex) { + m_whole.m_complex = true; + } m_wordAssign = true; if (wordNumOk(word)) { m_words[word].m_assignp = assp; @@ -113,13 +115,12 @@ public: } } void assignWordComplex(int word) { - if (!wordNumOk(word) || getWordAssignp(word) - || m_words[word].m_complex) m_whole.m_complex = true; + if (!wordNumOk(word) || getWordAssignp(word) || m_words[word].m_complex) { + m_whole.m_complex = true; + } m_words[word].m_complex = true; } - void assignComplex() { - m_whole.m_complex = true; - } + void assignComplex() { m_whole.m_complex = true; } void consumeWhole() { //==consumeComplex as we don't know the difference m_whole.m_use = true; } @@ -129,8 +130,7 @@ public: } // ACCESSORS AstNode* substWhole(AstNode* errp) { - if (!m_varp->isWide() - && !m_whole.m_complex && m_whole.m_assignp && !m_wordAssign) { + if (!m_varp->isWide() && !m_whole.m_complex && m_whole.m_assignp && !m_wordAssign) { AstNodeAssign* assp = m_whole.m_assignp; UASSERT_OBJ(assp, errp, "Reading whole that was never assigned"); return (assp->rhsp()); @@ -138,7 +138,8 @@ public: return NULL; } } - AstNode* substWord(AstNode* errp, int word) { // Return what to substitute given word number for + // Return what to substitute given word number for + AstNode* substWord(AstNode* errp, int word) { if (!m_whole.m_complex && !m_whole.m_assignp && !m_words[word].m_complex) { AstNodeAssign* assp = getWordAssignp(word); UASSERT_OBJ(assp, errp, "Reading a word that was never assigned, or bad word #"); @@ -147,14 +148,16 @@ public: return NULL; } } - int getWholeStep() const { - return m_whole.m_step; - } + int getWholeStep() const { return m_whole.m_step; } int getWordStep(int word) const { - if (!wordNumOk(word)) return 0; else return m_words[word].m_step; + if (!wordNumOk(word)) { + return 0; + } else { + return m_words[word].m_step; + } } void deleteAssign(AstNodeAssign* nodep) { - UINFO(5, "Delete "<unlinkFrBack()->deleteTree(), nodep); } void deleteUnusedAssign() { @@ -162,9 +165,9 @@ public: if (!m_whole.m_use && !m_wordUse && m_whole.m_assignp) { VL_DO_CLEAR(deleteAssign(m_whole.m_assignp), m_whole.m_assignp = NULL); } - for (unsigned i=0; ivarp()->user2()) { - if (m_ok) UINFO(9," RHS variable changed since subst recorded: "< SubstVar* for usage var, 0=not set yet // AstVar::user2 -> int step number for last assignment, 0=not set yet - AstUser1InUse m_inuser1; - AstUser2InUse m_inuser2; + AstUser1InUse m_inuser1; + AstUser2InUse m_inuser2; // STATE - std::vector m_entryps; // Nodes to delete when we are finished - int m_ops; // Number of operators on assign rhs - int m_assignStep; // Assignment number to determine var lifetime - VDouble0 m_statSubsts; // Statistic tracking + std::vector m_entryps; // Nodes to delete when we are finished + int m_ops; // Number of operators on assign rhs + int m_assignStep; // Assignment number to determine var lifetime + VDouble0 m_statSubsts; // Statistic tracking - enum { SUBST_MAX_OPS_SUBST = 30, // Maximum number of ops to substitute in - SUBST_MAX_OPS_NA = 9999 }; // Not allowed to substitute + enum { + SUBST_MAX_OPS_SUBST = 30, // Maximum number of ops to substitute in + SUBST_MAX_OPS_NA = 9999 + }; // Not allowed to substitute // METHODS SubstVarEntry* getEntryp(AstVarRef* nodep) { @@ -251,57 +258,51 @@ private: return entryp; } } - inline bool isSubstVar(AstVar* nodep) { - return nodep->isStatementTemp() && !nodep->noSubst(); - } + inline bool isSubstVar(AstVar* nodep) { return nodep->isStatementTemp() && !nodep->noSubst(); } // VISITORS virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { m_ops = 0; m_assignStep++; iterateAndNextNull(nodep->rhsp()); - bool hit=false; + bool hit = false; if (AstVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef)) { if (isSubstVar(varrefp->varp())) { SubstVarEntry* entryp = getEntryp(varrefp); hit = true; if (m_ops > SUBST_MAX_OPS_SUBST) { - UINFO(8," ASSIGNtooDeep "<assignComplex(); } else { - UINFO(8," ASSIGNwhole "<assignWhole(m_assignStep, nodep); } } - } - else if (AstWordSel* wordp = VN_CAST(nodep->lhsp(), WordSel)) { + } else if (AstWordSel* wordp = VN_CAST(nodep->lhsp(), WordSel)) { if (AstVarRef* varrefp = VN_CAST(wordp->lhsp(), VarRef)) { - if (VN_IS(wordp->rhsp(), Const) - && isSubstVar(varrefp->varp())) { + if (VN_IS(wordp->rhsp(), Const) && isSubstVar(varrefp->varp())) { int word = VN_CAST(wordp->rhsp(), Const)->toUInt(); SubstVarEntry* entryp = getEntryp(varrefp); hit = true; if (m_ops > SUBST_MAX_OPS_SUBST) { - UINFO(8," ASSIGNtooDeep "<assignWordComplex(word); } else { - UINFO(8," ASSIGNword"<assignWord(m_assignStep, word, nodep); } } } } - if (!hit) { - iterate(nodep->lhsp()); - } + if (!hit) iterate(nodep->lhsp()); } void replaceSubstEtc(AstNode* nodep, AstNode* substp) { - if (debug()>5) nodep->dumpTree(cout, " substw_old: "); + if (debug() > 5) nodep->dumpTree(cout, " substw_old: "); AstNode* newp = substp->cloneTree(true); if (!nodep->isQuad() && newp->isQuad()) { newp = new AstCCast(newp->fileline(), newp, nodep); } - if (debug()>5) newp->dumpTree(cout, " w_new: "); + if (debug() > 5) newp->dumpTree(cout, " w_new: "); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); ++m_statSubsts; @@ -310,17 +311,15 @@ private: iterate(nodep->rhsp()); AstVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef); AstConst* constp = VN_CAST(nodep->rhsp(), Const); - if (varrefp && isSubstVar(varrefp->varp()) - && !varrefp->lvalue() - && constp) { + if (varrefp && isSubstVar(varrefp->varp()) && !varrefp->lvalue() && constp) { // Nicely formed lvalues handled in NodeAssign // Other lvalues handled as unknown mess in AstVarRef int word = constp->toUInt(); - UINFO(8," USEword"<substWord(nodep, word)) { // Check that the RHS hasn't changed value since we recorded it. - SubstUseVisitor visitor (substp, entryp->getWordStep(word)); + SubstUseVisitor visitor(substp, entryp->getWordStep(word)); if (visitor.ok()) { VL_DO_DANGLING(replaceSubstEtc(nodep, substp), nodep); } else { @@ -338,25 +337,25 @@ private: if (nodep->lvalue()) { m_assignStep++; nodep->varp()->user2(m_assignStep); - UINFO(9, " ASSIGNstep u2="<varp()->user2()<<" "<varp())) { SubstVarEntry* entryp = getEntryp(nodep); if (nodep->lvalue()) { - UINFO(8," ASSIGNcpx "<assignComplex(); } else if (AstNode* substp = entryp->substWhole(nodep)) { // Check that the RHS hasn't changed value since we recorded it. - SubstUseVisitor visitor (substp, entryp->getWholeStep()); + SubstUseVisitor visitor(substp, entryp->getWholeStep()); if (visitor.ok()) { - UINFO(8," USEwhole "<consumeWhole(); } } else { // Consumed w/o substitute - UINFO(8," USEwtf "<consumeWhole(); } } @@ -365,11 +364,10 @@ private: virtual void visit(AstConst*) VL_OVERRIDE {} virtual void visit(AstNode* nodep) VL_OVERRIDE { m_ops++; - if (!nodep->isSubstOptimizable()) { - m_ops = SUBST_MAX_OPS_NA; - } + if (!nodep->isSubstOptimizable()) m_ops = SUBST_MAX_OPS_NA; iterateChildren(nodep); } + public: // CONSTRUCTORS explicit SubstVisitor(AstNode* nodep) { @@ -381,8 +379,8 @@ public: } virtual ~SubstVisitor() { V3Stats::addStat("Optimizations, Substituted temps", m_statSubsts); - for (std::vector::iterator it = m_entryps.begin(); - it != m_entryps.end(); ++it) { + for (std::vector::iterator it = m_entryps.begin(); it != m_entryps.end(); + ++it) { (*it)->deleteUnusedAssign(); delete (*it); } @@ -393,9 +391,7 @@ public: // Subst class functions void V3Subst::substituteAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3TSP.cpp b/src/V3TSP.cpp index 2bf83be6c..7ac74a154 100644 --- a/src/V3TSP.cpp +++ b/src/V3TSP.cpp @@ -47,32 +47,33 @@ // Support classes namespace V3TSP { - static unsigned edgeIdNext = 0; +static unsigned edgeIdNext = 0; - static void selfTestStates(); - static void selfTestString(); +static void selfTestStates(); +static void selfTestString(); - VL_DEBUG_FUNC; // Declare debug() +VL_DEBUG_FUNC; // Declare debug() } // namespace V3TSP // Vertex that tracks a per-vertex key -template -class TspVertexTmpl : public V3GraphVertex { +template class TspVertexTmpl : public V3GraphVertex { private: T_Key m_key; + public: TspVertexTmpl(V3Graph* graphp, const T_Key& k) - : V3GraphVertex(graphp), m_key(k) {} + : V3GraphVertex(graphp) + , m_key(k) {} virtual ~TspVertexTmpl() {} const T_Key& key() const { return m_key; } + private: VL_UNCOPYABLE(TspVertexTmpl); }; // TspGraphTmpl represents a complete graph, templatized to work with // different T_Key types. -template -class TspGraphTmpl : public V3Graph { +template class TspGraphTmpl : public V3Graph { public: // TYPES typedef TspVertexTmpl Vertex; @@ -82,14 +83,15 @@ public: VMap m_vertices; // T_Key to Vertex lookup map // CONSTRUCTORS - TspGraphTmpl() : V3Graph() {} + TspGraphTmpl() + : V3Graph() {} virtual ~TspGraphTmpl() {} // METHODS - void addVertex(const T_Key &key) { + void addVertex(const T_Key& key) { typename VMap::iterator itr = m_vertices.find(key); UASSERT(itr == m_vertices.end(), "Vertex already exists with same key"); - Vertex *v = new Vertex(this, key); + Vertex* v = new Vertex(this, key); m_vertices[key] = v; } @@ -118,9 +120,7 @@ public: std::list keysToVertexList(const std::vector& odds) { std::list vertices; - for(unsigned i = 0; i < odds.size(); ++i) { - vertices.push_back(findVertex(odds.at(i))); - } + for (unsigned i = 0; i < odds.size(); ++i) { vertices.push_back(findVertex(odds.at(i))); } return vertices; } @@ -132,7 +132,7 @@ public: // CONSTRUCTORS EdgeCmp() {} // METHODS - bool operator() (const V3GraphEdge* ap, const V3GraphEdge* bp) { + bool operator()(const V3GraphEdge* ap, const V3GraphEdge* bp) { int aCost = ap->weight(); int bCost = bp->weight(); // Sort first on cost, lowest cost edges first: @@ -141,13 +141,12 @@ public: // Costs are equal. Compare edgeId's which should be unique. return ap->user() < bp->user(); } + private: VL_UNCOPYABLE(EdgeCmp); }; - static Vertex* castVertexp(V3GraphVertex* vxp) { - return dynamic_cast(vxp); - } + static Vertex* castVertexp(V3GraphVertex* vxp) { return dynamic_cast(vxp); } // From *this, populate *mstp with the minimum spanning tree. // *mstp must be initially empty. @@ -164,8 +163,7 @@ public: PendingEdgeSet pendingEdges(cmp); vluint32_t vertCount = 0; - for (V3GraphVertex* vxp = verticesBeginp(); - vxp; vxp = vxp->verticesNextp()) { + for (V3GraphVertex* vxp = verticesBeginp(); vxp; vxp = vxp->verticesNextp()) { mstp->addVertex(castVertexp(vxp)->key()); vertCount++; } @@ -174,8 +172,7 @@ public: // all incident edges from this vertex go into a pending edge set. Vertex* start_vertexp = castVertexp(verticesBeginp()); visited_set.insert(start_vertexp); - for (V3GraphEdge* edgep = start_vertexp->outBeginp(); - edgep; edgep = edgep->outNextp()) { + for (V3GraphEdge* edgep = start_vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { pendingEdges.insert(edgep); } @@ -198,9 +195,8 @@ public: Vertex* neighborp = castVertexp(bestEdgep->top()); if (visited_set.find(neighborp) == visited_set.end()) { int bestCost = bestEdgep->weight(); - UINFO(6, "bestCost = "<key() - <<" to "<key()<key() << " to " + << neighborp->key() << endl); // Create the edge in our output MST graph mstp->addEdge(from_vertexp->key(), neighborp->key(), bestCost); @@ -210,13 +206,13 @@ public: visited_set.insert(neighborp); // Update the pending edges with new edges - for (V3GraphEdge* edgep = neighborp->outBeginp(); - edgep; edgep = edgep->outNextp()) { + for (V3GraphEdge* edgep = neighborp->outBeginp(); edgep; + edgep = edgep->outNextp()) { pendingEdges.insert(edgep); } } else { - UINFO(6, "Discarding edge to already-visited neighbor " - <key()<key() << endl); } } @@ -226,8 +222,7 @@ public: // Populate *outp with a minimal perfect matching of *this. // *outp must be initially empty. - void perfectMatching(const std::vector& oddKeys, - TspGraphTmpl* outp) { + void perfectMatching(const std::vector& oddKeys, TspGraphTmpl* outp) { UASSERT(outp->empty(), "Output graph must start empty"); std::list odds = keysToVertexList(oddKeys); @@ -261,8 +256,7 @@ public: PendingEdgeSet pendingEdges(cmp); for (VertexListIt it = odds.begin(); it != odds.end(); ++it) { - for (V3GraphEdge* edgep = (*it)->outBeginp(); - edgep; edgep = edgep->outNextp()) { + for (V3GraphEdge* edgep = (*it)->outBeginp(); edgep; edgep = edgep->outNextp()) { pendingEdges.insert(edgep); } } @@ -270,8 +264,8 @@ public: // Iterate over all edges, in order from low to high cost. // For any edge whose ends are both odd-order vertices which // haven't been matched yet, match them. - for (typename PendingEdgeSet::iterator it = pendingEdges.begin(); - it != pendingEdges.end(); ++it) { + for (typename PendingEdgeSet::iterator it = pendingEdges.begin(); it != pendingEdges.end(); + ++it) { Vertex* fromp = castVertexp((*it)->fromp()); Vertex* top = castVertexp((*it)->top()); if ((unmatchedOdds.find(fromp) != unmatchedOdds.end()) @@ -298,49 +292,43 @@ public: } } - void findEulerTourRecurse(vl_unordered_set* markedEdgesp, - Vertex* startp, + void findEulerTourRecurse(vl_unordered_set* markedEdgesp, Vertex* startp, std::vector* sortedOutp) { Vertex* cur_vertexp = startp; // Go on a random tour. Fun! std::vector tour; do { - UINFO(6, "Adding "<key()<<" to tour.\n"); + UINFO(6, "Adding " << cur_vertexp->key() << " to tour.\n"); tour.push_back(cur_vertexp); // Look for an arbitrary edge we've not yet marked - for (V3GraphEdge* edgep = cur_vertexp->outBeginp(); - edgep; edgep = edgep->outNextp()) { + for (V3GraphEdge* edgep = cur_vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { vluint32_t edgeId = edgep->user(); if (markedEdgesp->end() == markedEdgesp->find(edgeId)) { // This edge is not yet marked, so follow it. markedEdgesp->insert(edgeId); Vertex* neighborp = castVertexp(edgep->top()); - UINFO(6, "following edge "<key() - <<" to "<key()<key() + << " to " << neighborp->key() << endl); cur_vertexp = neighborp; goto found; } } v3fatalSrc("No unmarked edges found in tour"); - found: - ; + found:; } while (cur_vertexp != startp); - UINFO(6, "stopped, got back to start of tour @ "<key()<key() << endl); // Look for nodes on the tour that still have // un-marked edges. If we find one, recurse. - for (typename std::vector::iterator it = tour.begin(); - it != tour.end(); ++it) { + for (typename std::vector::iterator it = tour.begin(); it != tour.end(); ++it) { Vertex* vxp = *it; bool recursed; do { recursed = false; // Look for an arbitrary edge at vxp we've not yet marked - for (V3GraphEdge* edgep = vxp->outBeginp(); - edgep; edgep = edgep->outNextp()) { + for (V3GraphEdge* edgep = vxp->outBeginp(); edgep; edgep = edgep->outNextp()) { vluint32_t edgeId = edgep->user(); if (markedEdgesp->end() == markedEdgesp->find(edgeId)) { UINFO(6, "Recursing.\n"); @@ -349,38 +337,36 @@ public: goto recursed; } } - recursed: - ; + recursed:; } while (recursed); sortedOutp->push_back(vxp->key()); } UINFO(6, "Tour was: "); - for (typename std::vector::iterator it = tour.begin(); - it != tour.end(); ++it) { + for (typename std::vector::iterator it = tour.begin(); it != tour.end(); ++it) { Vertex* vxp = *it; - UINFONL(6, " "<key()); + UINFONL(6, " " << vxp->key()); } UINFONL(6, "\n"); } void dumpGraph(std::ostream& os, const string& nameComment) const { // UINFO(0) as controlled by caller - os<<"At "<verticesNextp()) { Vertex* tspvp = castVertexp(vxp); - os<<" "<key()<key() << endl; for (V3GraphEdge* edgep = tspvp->outBeginp(); edgep; edgep = edgep->outNextp()) { Vertex* neighborp = castVertexp(edgep->top()); - os<<" has edge "<user()<<" to "<key()<user() << " to " << neighborp->key() << endl; } } } void dumpGraphFilePrefixed(const string& nameComment) const { if (v3Global.opt.dumpTree()) { - string filename = v3Global.debugFilename(nameComment)+".txt"; + string filename = v3Global.debugFilename(nameComment) + ".txt"; const vl_unique_ptr logp(V3File::new_ofstream(filename)); - if (logp->fail()) v3fatal("Can't write "<fail()) v3fatal("Can't write " << filename); dumpGraph(*logp, nameComment); } } @@ -402,9 +388,7 @@ public: for (V3GraphEdge* edgep = vxp->outBeginp(); edgep; edgep = edgep->outNextp()) { degree++; } - if (degree & 1) { - result.push_back(tspvp->key()); - } + if (degree & 1) { result.push_back(tspvp->key()); } } return result; } @@ -427,9 +411,7 @@ void V3TSP::tspSort(const V3TSP::StateVec& states, V3TSP::StateVec* resultp) { // Make this TSP implementation work for graphs of size 0 or 1 // which, unfortunately, is a special case as the following // code assumes >= 2 nodes. - if (states.empty()) { - return; - } + if (states.empty()) { return; } if (states.size() == 1) { resultp->push_back(*(states.begin())); return; @@ -470,8 +452,8 @@ void V3TSP::tspSort(const V3TSP::StateVec& states, V3TSP::StateVec* resultp) { // Discard duplicate nodes that the Euler tour might contain. { vl_unordered_set seen; - for (V3TSP::StateVec::iterator it = prelim_result.begin(); - it != prelim_result.end(); ++it) { + for (V3TSP::StateVec::iterator it = prelim_result.begin(); it != prelim_result.end(); + ++it) { const TspStateBase* elemp = *it; if (seen.find(elemp) == seen.end()) { seen.insert(elemp); @@ -492,7 +474,7 @@ void V3TSP::tspSort(const V3TSP::StateVec& states, V3TSP::StateVec* resultp) { for (unsigned i = 0; i < resultp->size(); ++i) { const TspStateBase* ap = (*resultp)[i]; const TspStateBase* bp - = (i+1 == resultp->size()) ? (*resultp)[0] : (*resultp)[i+1]; + = (i + 1 == resultp->size()) ? (*resultp)[0] : (*resultp)[i + 1]; unsigned cost = ap->cost(bp); if (cost > max_cost) { max_cost = cost; @@ -508,12 +490,10 @@ void V3TSP::tspSort(const V3TSP::StateVec& states, V3TSP::StateVec* resultp) { V3TSP::StateVec new_result; unsigned i = max_cost_idx + 1; UASSERT(i < resultp->size(), "Algorithm size error"); - while(i != max_cost_idx) { + while (i != max_cost_idx) { new_result.push_back((*resultp)[i]); i++; - if (i >= resultp->size()) { - i = 0; - } + if (i >= resultp->size()) { i = 0; } } new_result.push_back((*resultp)[i]); @@ -527,17 +507,17 @@ void V3TSP::tspSort(const V3TSP::StateVec& states, V3TSP::StateVec* resultp) { class TspTestState : public V3TSP::TspStateBase { public: - TspTestState(unsigned xpos, unsigned ypos) : - m_xpos(xpos), - m_ypos(ypos), - m_serial(++m_serialNext) {} + TspTestState(unsigned xpos, unsigned ypos) + : m_xpos(xpos) + , m_ypos(ypos) + , m_serial(++m_serialNext) {} ~TspTestState() {} virtual int cost(const TspStateBase* otherp) const { return cost(dynamic_cast(otherp)); } static unsigned diff(unsigned a, unsigned b) { - if (a>b) return a-b; - return b-a; + if (a > b) return a - b; + return b - a; } virtual int cost(const TspTestState* otherp) const { // For test purposes, each TspTestState is merely a point @@ -546,21 +526,16 @@ public: unsigned xabs, yabs; xabs = diff(otherp->m_xpos, m_xpos); yabs = diff(otherp->m_ypos, m_ypos); - return lround(sqrt(xabs*xabs + yabs*yabs)); - } - unsigned xpos() const { - return m_xpos; - } - unsigned ypos() const { - return m_ypos; + return lround(sqrt(xabs * xabs + yabs * yabs)); } + unsigned xpos() const { return m_xpos; } + unsigned ypos() const { return m_ypos; } - bool operator< (const TspStateBase& other) const { - return operator< (dynamic_cast(other)); - } - bool operator< (const TspTestState& other) const { - return m_serial < other.m_serial; + bool operator<(const TspStateBase& other) const { + return operator<(dynamic_cast(other)); } + bool operator<(const TspTestState& other) const { return m_serial < other.m_serial; } + private: unsigned m_xpos; unsigned m_ypos; @@ -574,11 +549,11 @@ void V3TSP::selfTestStates() { // Linear test -- coords all along the x-axis { V3TSP::StateVec states; - TspTestState s10(10,0); - TspTestState s60(60,0); - TspTestState s20(20,0); - TspTestState s100(100,0); - TspTestState s5(5,0); + TspTestState s10(10, 0); + TspTestState s60(60, 0); + TspTestState s20(20, 0); + TspTestState s100(100, 0); + TspTestState s5(5, 0); states.push_back(&s10); states.push_back(&s60); states.push_back(&s20); @@ -595,12 +570,11 @@ void V3TSP::selfTestStates() { expect.push_back(&s10); expect.push_back(&s5); if (VL_UNCOVERABLE(expect != result)) { - for (V3TSP::StateVec::iterator it = result.begin(); - it != result.end(); ++it) { + for (V3TSP::StateVec::iterator it = result.begin(); it != result.end(); ++it) { const TspTestState* statep = dynamic_cast(*it); - cout<xpos()<<" "; + cout << statep->xpos() << " "; } - cout<(*it); - cout<xpos()<<","<ypos()<<" "; + cout << statep->xpos() << "," << statep->ypos() << " "; } - cout<::const_iterator it = result.begin(); it != result.end(); ++it) { - cout<<*it<<" "; + cout << *it << " "; } - cout< ModTableVector; ModTableVector m_modTableVscs; // All tables created // State cleared on each scope - AstScope* m_scopep; // Current SCOPE + AstScope* m_scopep; // Current SCOPE // State cleared on each always/assignw - bool m_assignDly; // Consists of delayed assignments instead of normal assignments - int m_inWidth; // Input table width - int m_outWidth; // Output table width + bool m_assignDly; // Consists of delayed assignments instead of normal assignments + int m_inWidth; // Input table width + int m_outWidth; // Output table width std::deque m_inVarps; // Input variable list - std::deque m_outVarps; // Output variable list - std::deque m_outNotSet; // True if output variable is not set at some point + std::deque m_outVarps; // Output variable list + std::deque m_outNotSet; // True if output variable is not set at some point // When creating a table - std::deque m_tableVarps; // Table being created + std::deque m_tableVarps; // Table being created // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -105,7 +106,7 @@ private: m_outNotSet.clear(); // Collect stats - TableSimulateVisitor chkvis (this); + TableSimulateVisitor chkvis(this); chkvis.mainTableCheck(nodep); m_assignDly = chkvis.isAssignDly(); // Also sets m_inWidth @@ -115,12 +116,12 @@ private: // Calc data storage in bytes size_t chgWidth = m_outVarps.size(); // Width of one change-it-vector - if (chgWidth<8) chgWidth = 8; + if (chgWidth < 8) chgWidth = 8; double space = (pow(static_cast(2.0), static_cast(m_inWidth)) * static_cast(m_outWidth + chgWidth)); // Instruction count bytes (ok, it's space also not time :) double bytesPerInst = 4; - double time = ((chkvis.instrCount()*bytesPerInst + chkvis.dataCount()) + double time = ((chkvis.instrCount() * bytesPerInst + chkvis.dataCount()) + 1); // +1 so won't div by zero if (chkvis.instrCount() < TABLE_MIN_NODE_COUNT) { chkvis.clearOptimizable(nodep, "Table has too few nodes involved"); @@ -134,16 +135,15 @@ private: if (m_totalBytes > TABLE_TOTAL_BYTES) { chkvis.clearOptimizable(nodep, "Table out of memory"); } - if (!m_outWidth || !m_inWidth) { - chkvis.clearOptimizable(nodep, "Table has no outputs"); - } - UINFO(4, " Test: Opt="<<(chkvis.optimizable()?"OK":"NO") - <<", Instrs="<varScopep(); if (nodep->lvalue()) { m_outWidth += nodep->varp()->dtypeSkipRefp()->widthTotalBytes(); @@ -172,25 +172,21 @@ private: ++m_statTablesCre; // Index into our table - AstVar* indexVarp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, - "__Vtableidx" + cvtToStr(m_modTables), - VFlagBitPacked(), m_inWidth); + AstVar* indexVarp + = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, + "__Vtableidx" + cvtToStr(m_modTables), VFlagBitPacked(), m_inWidth); m_modp->addStmtp(indexVarp); AstVarScope* indexVscp = new AstVarScope(indexVarp->fileline(), m_scopep, indexVarp); m_scopep->addVarp(indexVscp); // Change it variable FileLine* fl = nodep->fileline(); - AstNodeArrayDType* dtypep - = new AstUnpackArrayDType(fl, - nodep->findBitDType(m_outVarps.size(), - m_outVarps.size(), AstNumeric::UNSIGNED), - new AstRange(fl, VL_MASK_I(m_inWidth), 0)); + AstNodeArrayDType* dtypep = new AstUnpackArrayDType( + fl, nodep->findBitDType(m_outVarps.size(), m_outVarps.size(), AstNumeric::UNSIGNED), + new AstRange(fl, VL_MASK_I(m_inWidth), 0)); v3Global.rootp()->typeTablep()->addTypesp(dtypep); - AstVar* chgVarp - = new AstVar(fl, AstVarType::MODULETEMP, - "__Vtablechg" + cvtToStr(m_modTables), - dtypep); + AstVar* chgVarp = new AstVar(fl, AstVarType::MODULETEMP, + "__Vtablechg" + cvtToStr(m_modTables), dtypep); chgVarp->isConst(true); chgVarp->valuep(new AstInitArray(nodep->fileline(), dtypep, NULL)); m_modp->addStmtp(chgVarp); @@ -215,7 +211,7 @@ private: // Keep sensitivity list, but delete all else nodeap->bodysp()->unlinkFrBackWithNext()->deleteTree(); nodeap->addStmtp(stmtsp); - if (debug()>=6) nodeap->dumpTree(cout, " table_new: "); + if (debug() >= 6) nodeap->dumpTree(cout, " table_new: "); } else { // LCOV_EXCL_LINE nodep->v3fatalSrc("Creating table under unknown node type"); } @@ -226,23 +222,22 @@ private: void createTableVars(AstNode* nodep) { // Create table for each output - typedef std::map NameCounts; + typedef std::map NameCounts; NameCounts namecounts; - for (std::deque::iterator it = m_outVarps.begin(); - it != m_outVarps.end(); ++it) { + for (std::deque::iterator it = m_outVarps.begin(); it != m_outVarps.end(); + ++it) { AstVarScope* outvscp = *it; AstVar* outvarp = outvscp->varp(); FileLine* fl = nodep->fileline(); - AstNodeArrayDType* dtypep - = new AstUnpackArrayDType(fl, outvarp->dtypep(), - new AstRange(fl, VL_MASK_I(m_inWidth), 0)); + AstNodeArrayDType* dtypep = new AstUnpackArrayDType( + fl, outvarp->dtypep(), new AstRange(fl, VL_MASK_I(m_inWidth), 0)); v3Global.rootp()->typeTablep()->addTypesp(dtypep); - string name = "__Vtable"+cvtToStr(m_modTables)+"_"+outvarp->name(); + string name = "__Vtable" + cvtToStr(m_modTables) + "_" + outvarp->name(); NameCounts::iterator nit = namecounts.find(name); if (nit != namecounts.end()) { // Multiple scopes can have same var name. We could append the // scope name but that is very long, so just deduplicate. - name += "__dedup"+cvtToStr(++nit->second); + name += "__dedup" + cvtToStr(++nit->second); } else { namecounts[name] = 0; } @@ -261,18 +256,19 @@ private: // Concat inputs into a single temp variable (inside always) // First var in inVars becomes the LSB of the concat AstNode* concatp = NULL; - for (std::deque::iterator it = m_inVarps.begin(); it!=m_inVarps.end(); ++it) { + for (std::deque::iterator it = m_inVarps.begin(); it != m_inVarps.end(); + ++it) { AstVarScope* invscp = *it; AstVarRef* refp = new AstVarRef(nodep->fileline(), invscp, false); if (concatp) { concatp = new AstConcat(nodep->fileline(), refp, concatp); - } else concatp = refp; + } else { + concatp = refp; + } } - AstNode* stmtsp = new AstAssign - (nodep->fileline(), - new AstVarRef(nodep->fileline(), indexVscp, true), - concatp); + AstNode* stmtsp = new AstAssign( + nodep->fileline(), new AstVarRef(nodep->fileline(), indexVscp, true), concatp); return stmtsp; } @@ -281,15 +277,15 @@ private: // There may be a simulation path by which the output doesn't change value. // We could bail on these cases, or we can have a "change it" boolean. // We've chosen the latter route, since recirc is common in large FSMs. - for (std::deque::iterator it = m_outVarps.begin(); - it != m_outVarps.end(); ++it) { + for (std::deque::iterator it = m_outVarps.begin(); it != m_outVarps.end(); + ++it) { m_outNotSet.push_back(false); } uint32_t inValueNextInitArray = 0; - TableSimulateVisitor simvis (this); - for (uint32_t inValue=0; inValue <= VL_MASK_I(m_inWidth); inValue++) { + TableSimulateVisitor simvis(this); + for (uint32_t inValue = 0; inValue <= VL_MASK_I(m_inWidth); inValue++) { // Make a new simulation structure so we can set new input values - UINFO(8," Simulating "<::iterator it = m_inVarps.begin(); - it != m_inVarps.end(); ++it) { + for (std::deque::iterator it = m_inVarps.begin(); it != m_inVarps.end(); + ++it) { AstVarScope* invscp = *it; // LSB is first variable, so extract it that way AstConst cnst(invscp->fileline(), AstConst::WidthedValue(), invscp->width(), - VL_MASK_I(invscp->width()) & (inValue>>shift)); + VL_MASK_I(invscp->width()) & (inValue >> shift)); simvis.newValue(invscp, &cnst); shift += invscp->width(); // We're just using32 bit arithmetic, because there's no // way the input table can be 2^32 bytes! UASSERT_OBJ(shift <= 32, nodep, "shift overflow"); - UINFO(8," Input "<name()<<" = "<name() << " = " << cnst.name() << endl); } // Simulate simvis.mainTableEmulate(nodep); UASSERT_OBJ(simvis.optimizable(), simvis.whyNotNodep(), "Optimizable cleared, even though earlier test run said not: " - <::iterator it = m_outVarps.begin(); it != m_outVarps.end(); ++it) { AstVarScope* outvscp = *it; V3Number* outnump = simvis.fetchOutNumberNull(outvscp); AstNode* setp; if (!outnump) { - UINFO(8," Output "<name()<<" never set\n"); + UINFO(8, " Output " << outvscp->name() << " never set\n"); m_outNotSet[outnum] = true; // Value in table is arbitrary, but we need something - setp = new AstConst(outvscp->fileline(), - AstConst::WidthedValue(), outvscp->width(), 0); + setp = new AstConst(outvscp->fileline(), AstConst::WidthedValue(), + outvscp->width(), 0); } else { - UINFO(8," Output "<name()<<" = "<<*outnump<name() << " = " << *outnump << endl); // m_tableVarps[inValue] = num; // Mark changed bit, too outputChgMask.setBit(outnum, 1); @@ -343,7 +339,7 @@ private: outnum++; } - { // Set changed table + { // Set changed table UASSERT_OBJ(inValue == inValueNextInitArray, nodep, "InitArray requires us to have the values in inValue order"); inValueNextInitArray++; @@ -359,7 +355,7 @@ private: AstVar* var1p = vsc1p->varp(); for (std::deque::iterator it = m_modTableVscs.begin(); it != m_modTableVscs.end(); ++it) { - AstVarScope* vsc2p= *it; + AstVarScope* vsc2p = *it; AstVar* var2p = vsc2p->varp(); if (var1p->width() == var2p->width() && (var1p->dtypep()->arrayUnpackedElements() @@ -367,7 +363,7 @@ private: const AstNode* init1p = VN_CAST(var1p->valuep(), InitArray); const AstNode* init2p = VN_CAST(var2p->valuep(), InitArray); if (init1p->sameGateTree(init2p)) { - UINFO(8," Duplicate table var "<unlinkFrBack()->deleteTree(), vsc1p); return vsc2p; } @@ -377,31 +373,30 @@ private: return vsc1p; } - void createOutputAssigns(AstNode* nodep, AstNode* stmtsp, - AstVarScope* indexVscp, AstVarScope* chgVscp) { + void createOutputAssigns(AstNode* nodep, AstNode* stmtsp, AstVarScope* indexVscp, + AstVarScope* chgVscp) { // We walk through the changemask table, and if all ones know // the output is set on all branches and therefore eliminate the // if. If all uses of the changemask disappear, dead code // elimination will remove it for us. // Set each output from array ref into our table int outnum = 0; - for (std::deque::iterator it = m_outVarps.begin(); - it != m_outVarps.end(); ++it) { + for (std::deque::iterator it = m_outVarps.begin(); it != m_outVarps.end(); + ++it) { AstVarScope* outvscp = *it; AstNode* alhsp = new AstVarRef(nodep->fileline(), outvscp, true); - AstNode* arhsp - = new AstArraySel(nodep->fileline(), - new AstVarRef(nodep->fileline(), m_tableVarps[outnum], false), - new AstVarRef(nodep->fileline(), indexVscp, false)); + AstNode* arhsp = new AstArraySel( + nodep->fileline(), new AstVarRef(nodep->fileline(), m_tableVarps[outnum], false), + new AstVarRef(nodep->fileline(), indexVscp, false)); AstNode* outasnp = (m_assignDly - ? static_cast(new AstAssignDly(nodep->fileline(), alhsp, arhsp)) - : static_cast(new AstAssign(nodep->fileline(), alhsp, arhsp))); + ? static_cast(new AstAssignDly(nodep->fileline(), alhsp, arhsp)) + : static_cast(new AstAssign(nodep->fileline(), alhsp, arhsp))); AstNode* outsetp = outasnp; // Is the value set in only some branches of the table? if (m_outNotSet[outnum]) { - V3Number outputChgMask (nodep, m_outVarps.size(), 0); + V3Number outputChgMask(nodep, m_outVarps.size(), 0); outputChgMask.setBit(outnum, 1); outsetp = new AstIf( nodep->fileline(), @@ -418,11 +413,8 @@ private: } } - // VISITORS - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { - iterateChildren(nodep); - } + virtual void visit(AstNetlist* nodep) VL_OVERRIDE { iterateChildren(nodep); } virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { AstNodeModule* origModp = m_modp; int origModTables = m_modTables; @@ -438,13 +430,13 @@ private: m_modTableVscs = origModTableVscs; } virtual void visit(AstScope* nodep) VL_OVERRIDE { - UINFO(4," SCOPE "<= 3); } diff --git a/src/V3Task.cpp b/src/V3Task.cpp index e92e97b21..3ab819107 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -42,13 +42,15 @@ // Graph subclasses class TaskBaseVertex : public V3GraphVertex { - AstNode* m_impurep; // Node causing impure function w/ outside references - bool m_noInline; // Marked with pragma + AstNode* m_impurep; // Node causing impure function w/ outside references + bool m_noInline; // Marked with pragma public: explicit TaskBaseVertex(V3Graph* graphp) - : V3GraphVertex(graphp), m_impurep(NULL), m_noInline(false) {} + : V3GraphVertex(graphp) + , m_impurep(NULL) + , m_noInline(false) {} virtual ~TaskBaseVertex() {} - bool pure() const { return m_impurep==NULL; } + bool pure() const { return m_impurep == NULL; } AstNode* impureNode() const { return m_impurep; } void impure(AstNode* nodep) { m_impurep = nodep; } bool noInline() const { return m_noInline; } @@ -59,9 +61,11 @@ class TaskFTaskVertex : public TaskBaseVertex { // Every task gets a vertex, and we link tasks together based on funcrefs. AstNodeFTask* m_nodep; AstCFunc* m_cFuncp; + public: TaskFTaskVertex(V3Graph* graphp, AstNodeFTask* nodep) - : TaskBaseVertex(graphp), m_nodep(nodep) { + : TaskBaseVertex(graphp) + , m_nodep(nodep) { m_cFuncp = NULL; } virtual ~TaskFTaskVertex() {} @@ -88,7 +92,7 @@ public: TaskEdge(V3Graph* graphp, TaskBaseVertex* fromp, TaskBaseVertex* top) : V3GraphEdge(graphp, fromp, top, 1, false) {} virtual ~TaskEdge() {} - virtual string dotLabel() const { return "w"+cvtToStr(weight()); } + virtual string dotLabel() const { return "w" + cvtToStr(weight()); } }; //###################################################################### @@ -101,16 +105,16 @@ private: // AstNodeFTask::user4p // GraphFTaskVertex* this FTask is under // AstVar::user4p // GraphFTaskVertex* this variable is declared in - AstUser3InUse m_inuser3; - AstUser4InUse m_inuser4; + AstUser3InUse m_inuser3; + AstUser4InUse m_inuser4; // TYPES - typedef std::map,AstVarScope*> VarToScopeMap; + typedef std::map, AstVarScope*> VarToScopeMap; // MEMBERS - VarToScopeMap m_varToScopeMap; // Map for Var -> VarScope mappings - AstAssignW* m_assignwp; // Current assignment - V3Graph m_callGraph; // Task call graph - TaskBaseVertex* m_curVxp; // Current vertex we're adding to + VarToScopeMap m_varToScopeMap; // Map for Var -> VarScope mappings + AstAssignW* m_assignwp; // Current assignment + V3Graph m_callGraph; // Task call graph + TaskBaseVertex* m_curVxp; // Current vertex we're adding to public: // METHODS @@ -124,37 +128,32 @@ public: UASSERT_OBJ(iter != m_varToScopeMap.end(), nodep, "No scope for var"); return iter->second; } - bool ftaskNoInline(AstNodeFTask* nodep) { - return getFTaskVertex(nodep)->noInline(); - } - AstCFunc* ftaskCFuncp(AstNodeFTask* nodep) { - return getFTaskVertex(nodep)->cFuncp(); - } + bool ftaskNoInline(AstNodeFTask* nodep) { return getFTaskVertex(nodep)->noInline(); } + AstCFunc* ftaskCFuncp(AstNodeFTask* nodep) { return getFTaskVertex(nodep)->cFuncp(); } void ftaskCFuncp(AstNodeFTask* nodep, AstCFunc* cfuncp) { getFTaskVertex(nodep)->cFuncp(cfuncp); } - void checkPurity(AstNodeFTask* nodep) { - checkPurity(nodep, getFTaskVertex(nodep)); - } + void checkPurity(AstNodeFTask* nodep) { checkPurity(nodep, getFTaskVertex(nodep)); } void checkPurity(AstNodeFTask* nodep, TaskBaseVertex* vxp) { if (!vxp->pure()) { - nodep->v3warn(IMPURE, "Unsupported: External variable referenced by non-inlined function/task: " - <prettyNameQ()<warnContextPrimary()<impureNode()->warnOther()<<"... Location of the external reference: " - <impureNode()->prettyNameQ()<impureNode()->warnContextSecondary()); + nodep->v3warn( + IMPURE, "Unsupported: External variable referenced by non-inlined function/task: " + << nodep->prettyNameQ() << endl + << nodep->warnContextPrimary() << endl + << vxp->impureNode()->warnOther() + << "... Location of the external reference: " + << vxp->impureNode()->prettyNameQ() << endl + << vxp->impureNode()->warnContextSecondary()); } // And, we need to check all tasks this task calls - for (V3GraphEdge* edgep = vxp->outBeginp(); edgep; edgep=edgep->outNextp()) { + for (V3GraphEdge* edgep = vxp->outBeginp(); edgep; edgep = edgep->outNextp()) { checkPurity(nodep, static_cast(edgep->top())); } } + private: TaskFTaskVertex* getFTaskVertex(AstNodeFTask* nodep) { - if (!nodep->user4p()) { - nodep->user4p(new TaskFTaskVertex(&m_callGraph, nodep)); - } + if (!nodep->user4p()) nodep->user4p(new TaskFTaskVertex(&m_callGraph, nodep)); return static_cast(nodep->user4u().toGraphVertex()); } @@ -164,19 +163,18 @@ private: // pointers to what scope the FTask is to be invoked under. // However, to create variables, we need to track the scopes involved. // Find all var->varscope mappings, for later cleanup - for (AstNode* stmtp = nodep->varsp(); stmtp; stmtp=stmtp->nextp()) { + for (AstNode* stmtp = nodep->varsp(); stmtp; stmtp = stmtp->nextp()) { if (AstVarScope* vscp = VN_CAST(stmtp, VarScope)) { if (vscp->varp()->isFuncLocal()) { - UINFO(9," funcvsc "<varp()), vscp)); + UINFO(9, " funcvsc " << vscp << endl); + m_varToScopeMap.insert( + std::make_pair(std::make_pair(nodep, vscp->varp()), vscp)); } } } // Likewise, all FTask->scope mappings - for (AstNode* stmtp = nodep->blocksp(); stmtp; stmtp=stmtp->nextp()) { - if (AstNodeFTask* taskp = VN_CAST(stmtp, NodeFTask)) { - taskp->user3p(nodep); - } + for (AstNode* stmtp = nodep->blocksp(); stmtp; stmtp = stmtp->nextp()) { + if (AstNodeFTask* taskp = VN_CAST(stmtp, NodeFTask)) { taskp->user3p(nodep); } } iterateChildren(nodep); } @@ -190,7 +188,7 @@ private: if (m_assignwp) { // Wire assigns must become always statements to deal with insertion // of multiple statements. Perhaps someday make all wassigns into always's? - UINFO(5," IM_WireRep "<convertToAlways(); VL_DO_CLEAR(pushDeletep(m_assignwp), m_assignwp = NULL); } @@ -199,7 +197,7 @@ private: new TaskEdge(&m_callGraph, m_curVxp, getFTaskVertex(nodep->taskp())); } virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { - UINFO(9," TASK "<dpiImport()) m_curVxp->noInline(true); @@ -213,8 +211,7 @@ private: // Just mark for the next steps, and we're done with it. m_curVxp->noInline(true); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } - else { + } else { iterateChildren(nodep); } } @@ -225,10 +222,7 @@ private: virtual void visit(AstVarRef* nodep) VL_OVERRIDE { iterateChildren(nodep); if (nodep->varp()->user4u().toGraphVertex() != m_curVxp) { - if (m_curVxp->pure() - && !nodep->varp()->isXTemp()) { - m_curVxp->impure(nodep); - } + if (m_curVxp->pure() && !nodep->varp()->isXTemp()) m_curVxp->impure(nodep); } } //-------------------- @@ -264,7 +258,8 @@ private: virtual void visit(AstVarRef* nodep) VL_OVERRIDE { // Similar code in V3Inline if (nodep->varp()->user2p()) { // It's being converted to an alias. - UINFO(9, " relinkVar "<varp()->user2p())<<" "<varp()->user2p()) << " " << nodep << endl); AstVarScope* newvscp = VN_CAST(nodep->varp()->user2p(), VarScope); UASSERT_OBJ(newvscp, nodep, "not linked"); nodep->varScopep(newvscp); @@ -297,33 +292,32 @@ private: // to TaskRelinkVisitor: // AstVar::user2p // AstVarScope* to replace varref with - AstUser1InUse m_inuser1; - AstUser2InUse m_inuser2; + AstUser1InUse m_inuser1; + AstUser2InUse m_inuser2; // TYPES - enum InsertMode { - IM_BEFORE, // Pointing at statement ref is in, insert before this - IM_AFTER, // Pointing at last inserted stmt, insert after - IM_WHILE_PRECOND // Pointing to for loop, add to body end + enum InsertMode { + IM_BEFORE, // Pointing at statement ref is in, insert before this + IM_AFTER, // Pointing at last inserted stmt, insert after + IM_WHILE_PRECOND // Pointing to for loop, add to body end }; - typedef std::map > DpiNames; + typedef std::map > DpiNames; // STATE - TaskStateVisitor* m_statep; // Common state between visitors - AstNodeModule* m_modp; // Current module - AstTopScope* m_topScopep; // Current top scope - AstScope* m_scopep; // Current scope - InsertMode m_insMode; // How to insert - AstNode* m_insStmtp; // Where to insert statement - int m_modNCalls; // Incrementing func # for making symbols - DpiNames m_dpiNames; // Map of all created DPI functions + TaskStateVisitor* m_statep; // Common state between visitors + AstNodeModule* m_modp; // Current module + AstTopScope* m_topScopep; // Current top scope + AstScope* m_scopep; // Current scope + InsertMode m_insMode; // How to insert + AstNode* m_insStmtp; // Where to insert statement + int m_modNCalls; // Incrementing func # for making symbols + DpiNames m_dpiNames; // Map of all created DPI functions // METHODS VL_DEBUG_FUNC; // Declare debug() AstVarScope* createFuncVar(AstCFunc* funcp, const string& name, AstVar* examplep) { - AstVar* newvarp = new AstVar(funcp->fileline(), AstVarType::BLOCKTEMP, name, - examplep); + AstVar* newvarp = new AstVar(funcp->fileline(), AstVarType::BLOCKTEMP, name, examplep); newvarp->funcLocal(true); funcp->addInitsp(newvarp); AstVarScope* newvscp = new AstVarScope(funcp->fileline(), m_scopep, newvarp); @@ -345,8 +339,7 @@ private: // It shouldn't matter, as they are only local variables. // We choose to do it under whichever called this function, which results // in more cache locality. - AstVar* newvarp = new AstVar(invarp->fileline(), AstVarType::BLOCKTEMP, - name, invarp); + AstVar* newvarp = new AstVar(invarp->fileline(), AstVarType::BLOCKTEMP, name, invarp); newvarp->funcLocal(false); newvarp->propagateAttrFrom(invarp); m_modp->addStmtp(newvarp); @@ -355,39 +348,38 @@ private: return newvscp; } - AstNode* createInlinedFTask(AstNodeFTaskRef* refp, - const string& namePrefix, AstVarScope* outvscp) { + AstNode* createInlinedFTask(AstNodeFTaskRef* refp, const string& namePrefix, + AstVarScope* outvscp) { // outvscp is the variable for functions only, if NULL, it's a task UASSERT_OBJ(refp->taskp(), refp, "Unlinked?"); AstNode* newbodysp = AstNode::cloneTreeNull(refp->taskp()->stmtsp(), true); // Maybe NULL - AstNode* beginp = new AstComment(refp->fileline(), - string("Function: ")+refp->name(), true); + AstNode* beginp + = new AstComment(refp->fileline(), string("Function: ") + refp->name(), true); if (newbodysp) beginp->addNext(newbodysp); - if (debug()>=9) { beginp->dumpTreeAndNext(cout, "-newbegi:"); } + if (debug() >= 9) beginp->dumpTreeAndNext(cout, "-newbegi:"); // // Create input variables AstNode::user2ClearTree(); V3TaskConnects tconnects = V3Task::taskConnects(refp, beginp); - for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) { + for (V3TaskConnects::iterator it = tconnects.begin(); it != tconnects.end(); ++it) { AstVar* portp = it->first; AstArg* argp = it->second; AstNode* pinp = argp->exprp(); - portp->unlinkFrBack(); pushDeletep(portp); // Remove it from the clone (not original) - if (pinp==NULL) { + portp->unlinkFrBack(); + pushDeletep(portp); // Remove it from the clone (not original) + if (!pinp) { // Too few arguments in function call } else { - UINFO(9, " Port "<unlinkFrBack(); // Relinked to assignment below VL_DO_DANGLING(argp->unlinkFrBack()->deleteTree(), argp); // Args no longer needed // if (portp->isWritable() && VN_IS(pinp, Const)) { - pinp->v3error("Function/task " - +portp->direction().prettyName() // e.g. "output" - +" connected to constant instead of variable: " - +portp->prettyNameQ()); - } - else if (portp->isInoutish()) { + pinp->v3error( + "Function/task " + portp->direction().prettyName() // e.g. "output" + + " connected to constant instead of variable: " + portp->prettyNameQ()); + } else if (portp->isInoutish()) { // Correct lvalue; see comments below V3LinkLValue::linkLValueSet(pinp); @@ -398,10 +390,11 @@ private: portp->user2p(localVscp); pushDeletep(pinp); } else { - pinp->v3warn(E_TASKNSVAR, "Unsupported: Function/task input argument is not simple variable"); + pinp->v3warn( + E_TASKNSVAR, + "Unsupported: Function/task input argument is not simple variable"); } - } - else if (portp->isWritable()) { + } else if (portp->isWritable()) { // Make output variables // Correct lvalue; we didn't know when we linked // This is slightly scary; are we sure no decisions were made @@ -412,24 +405,24 @@ private: // Even if it's referencing a varref, we still make a temporary // Else task(x,x,x) might produce incorrect results AstVarScope* tempvscp - = createVarScope(portp, namePrefix+"__"+portp->shortName()); + = createVarScope(portp, namePrefix + "__" + portp->shortName()); portp->user2p(tempvscp); AstAssign* assp = new AstAssign(pinp->fileline(), pinp, new AstVarRef(tempvscp->fileline(), tempvscp, false)); - assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Ok if in <= block + assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, + true); // Ok if in <= block // Put assignment BEHIND of all other statements beginp->addNext(assp); - } - else if (portp->isNonOutput()) { + } else if (portp->isNonOutput()) { // Make input variable AstVarScope* inVscp - = createVarScope(portp, namePrefix+"__"+portp->shortName()); + = createVarScope(portp, namePrefix + "__" + portp->shortName()); portp->user2p(inVscp); - AstAssign* assp = new AstAssign(pinp->fileline(), - new AstVarRef(inVscp->fileline(), inVscp, true), - pinp); - assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Ok if in <= block + AstAssign* assp = new AstAssign( + pinp->fileline(), new AstVarRef(inVscp->fileline(), inVscp, true), pinp); + assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, + true); // Ok if in <= block // Put assignment in FRONT of all other statements if (AstNode* afterp = beginp->nextp()) { afterp->unlinkFrBackWithNext(); @@ -442,15 +435,16 @@ private: UASSERT_OBJ(!refp->pinsp(), refp, "Pin wasn't removed by above loop"); { AstNode* nextstmtp; - for (AstNode* stmtp = beginp; stmtp; stmtp=nextstmtp) { + for (AstNode* stmtp = beginp; stmtp; stmtp = nextstmtp) { nextstmtp = stmtp->nextp(); if (AstVar* portp = VN_CAST(stmtp, Var)) { // Any I/O variables that fell out of above loop were already linked if (!portp->user2p()) { // Move it to a new localized variable - portp->unlinkFrBack(); pushDeletep(portp); // Remove it from the clone (not original) + portp->unlinkFrBack(); + pushDeletep(portp); // Remove it from the clone (not original) AstVarScope* localVscp - = createVarScope(portp, namePrefix+"__"+portp->shortName()); + = createVarScope(portp, namePrefix + "__" + portp->shortName()); portp->user2p(localVscp); } } @@ -458,7 +452,7 @@ private: } // Create function output variables if (outvscp) { - //UINFO(0, "setflag on "<fvarp()<<" to "<fvarp() << " to " << outvscp << endl); refp->taskp()->fvarp()->user2p(outvscp); } // Replace variable refs @@ -470,7 +464,7 @@ private: VL_DO_DANGLING(tempp->deleteTree(), tempp); } // - if (debug()>=9) { beginp->dumpTreeAndNext(cout, "-iotask: "); } + if (debug() >= 9) beginp->dumpTreeAndNext(cout, "-iotask: "); return beginp; } @@ -481,8 +475,8 @@ private: AstCFunc* cfuncp = m_statep->ftaskCFuncp(refp->taskp()); UASSERT_OBJ(cfuncp, refp, "No non-inline task associated with this task call?"); // - AstNode* beginp = new AstComment(refp->fileline(), - string("Function: ")+refp->name(), true); + AstNode* beginp + = new AstComment(refp->fileline(), string("Function: ") + refp->name(), true); AstNodeCCall* ccallp; if (AstNew* mrefp = VN_CAST(refp, New)) { AstCNew* cnewp = new AstCNew(refp->fileline(), cfuncp); @@ -500,31 +494,30 @@ private: // Convert complicated outputs to temp signals V3TaskConnects tconnects = V3Task::taskConnects(refp, refp->taskp()->stmtsp()); - for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) { + for (V3TaskConnects::iterator it = tconnects.begin(); it != tconnects.end(); ++it) { AstVar* portp = it->first; AstNode* pinp = it->second->exprp(); if (!pinp) { // Too few arguments in function call } else { - UINFO(9, " Port "<isWritable() && VN_IS(pinp, Const)) { - pinp->v3error("Function/task " - +portp->direction().prettyName() // e.g. "output" - +" connected to constant instead of variable: " - +portp->prettyNameQ()); - } - else if (portp->isInoutish()) { + pinp->v3error( + "Function/task " + portp->direction().prettyName() // e.g. "output" + + " connected to constant instead of variable: " + portp->prettyNameQ()); + } else if (portp->isInoutish()) { // Correct lvalue; see comments below V3LinkLValue::linkLValueSet(pinp); if (VN_IS(pinp, VarRef)) { // Connect to this exact variable } else { - pinp->v3warn(E_TASKNSVAR, "Unsupported: Function/task input argument is not simple variable"); + pinp->v3warn( + E_TASKNSVAR, + "Unsupported: Function/task input argument is not simple variable"); } - } - else if (portp->isWritable()) { + } else if (portp->isWritable()) { // Make output variables // Correct lvalue; we didn't know when we linked // This is slightly scary; are we sure no decisions were made @@ -559,14 +552,14 @@ private: ccallp->addArgsp(snp); // __Vfilenamep ccallp->addArgsp(new AstCMath(refp->fileline(), - "\""+refp->fileline()->filename()+"\"", 64, true)); + "\"" + refp->fileline()->filename() + "\"", 64, true)); // __Vlineno ccallp->addArgsp(new AstConst(refp->fileline(), refp->fileline()->lineno())); } // Create connections AstNode* nextpinp; - for (AstNode* pinp = refp->pinsp(); pinp; pinp=nextpinp) { + for (AstNode* pinp = refp->pinsp(); pinp; pinp = nextpinp) { nextpinp = pinp->nextp(); // Move pin to the CCall, removing all Arg's AstNode* exprp = VN_CAST(pinp, Arg)->exprp(); @@ -574,11 +567,9 @@ private: ccallp->addArgsp(exprp); } - if (outvscp) { - ccallp->addArgsp(new AstVarRef(refp->fileline(), outvscp, true)); - } + if (outvscp) ccallp->addArgsp(new AstVarRef(refp->fileline(), outvscp, true)); - if (debug()>=9) { beginp->dumpTreeAndNext(cout, "-nitask: "); } + if (debug() >= 9) beginp->dumpTreeAndNext(cout, "-nitask: "); return beginp; } @@ -589,12 +580,15 @@ private: if (nodep->pure()) dpiproto += "pure "; if (nodep->dpiContext()) dpiproto += "context "; dpiproto += rtnvarp ? rtnvarp->dpiArgType(true, true) : "void"; - dpiproto += " "+nodep->cname()+" ("; + dpiproto += " " + nodep->cname() + " ("; string args; - for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) { + for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) { if (const AstVar* portp = VN_CAST(stmtp, Var)) { - if (portp->isIO() && !portp->isFuncReturn() && portp!=rtnvarp) { - if (args != "") { args+= ", "; dpiproto+= ", "; } + if (portp->isIO() && !portp->isFuncReturn() && portp != rtnvarp) { + if (args != "") { + args += ", "; + dpiproto += ", "; + } args += portp->name(); // Leftover so ,'s look nice if (nodep->dpiImport()) dpiproto += portp->dpiArgType(false, false); } @@ -605,7 +599,7 @@ private: } AstNode* createDpiTemp(AstVar* portp, const string& suffix) { - string stmt = portp->dpiArgType(false, true) + " " +portp->name()+suffix; + string stmt = portp->dpiArgType(false, true) + " " + portp->name() + suffix; if (!portp->basicp()->isDpiPrimitive()) { stmt += "[" + cvtToStr(portp->widthWords()) + "]"; } @@ -627,7 +621,7 @@ private: if (useSetWSvlv) { AstNode* linesp = new AstText(portp->fileline(), frstmt); linesp->addNext(new AstVarRef(portp->fileline(), portvscp, true)); - linesp->addNext(new AstText(portp->fileline(), ","+frName+");")); + linesp->addNext(new AstText(portp->fileline(), "," + frName + ");")); return new AstCStmt(portp->fileline(), linesp); } // Use a AstCMath, as we want V3Clean to mask off bits that don't make sense. @@ -639,18 +633,15 @@ private: cwidth = portp->basicp()->keyword().width(); } } - AstNode* newp = new AstAssign(portp->fileline(), - new AstVarRef(portp->fileline(), portvscp, true), - new AstSel(portp->fileline(), - new AstCMath(portp->fileline(), frstmt, cwidth, false), - 0, portp->width())); + AstNode* newp = new AstAssign( + portp->fileline(), new AstVarRef(portp->fileline(), portvscp, true), + new AstSel(portp->fileline(), new AstCMath(portp->fileline(), frstmt, cwidth, false), + 0, portp->width())); return newp; } void makeDpiExportWrapper(AstNodeFTask* nodep, AstVar* rtnvarp) { - AstCFunc* dpip = new AstCFunc(nodep->fileline(), - nodep->cname(), - m_scopep, + AstCFunc* dpip = new AstCFunc(nodep->fileline(), nodep->cname(), m_scopep, (rtnvarp ? rtnvarp->dpiArgType(true, true) : "")); dpip->dontCombine(true); dpip->entryPoint(true); @@ -672,42 +663,44 @@ private: // but the compare is only done on first call then memoized, so // it's not worth optimizing. string stmt; - stmt += "static int __Vfuncnum = -1;\n"; // Static doesn't need save-restore as if below will re-fill proper value + // Static doesn't need save-restore as if below will re-fill proper value + stmt += "static int __Vfuncnum = -1;\n"; // First time init (faster than what the compiler does if we did a singleton stmt += "if (VL_UNLIKELY(__Vfuncnum==-1)) { __Vfuncnum = Verilated::exportFuncNum(\"" - +nodep->cname()+"\"); }\n"; + + nodep->cname() + "\"); }\n"; // If the find fails, it will throw an error stmt += "const VerilatedScope* __Vscopep = Verilated::dpiScope();\n"; // If dpiScope is fails and is null; the exportFind function throws and error - string cbtype = VIdProtect::protect(v3Global.opt.prefix() - +"__Vcb_"+nodep->cname()+"_t"); - stmt += cbtype+" __Vcb = ("+cbtype+")(VerilatedScope::exportFind(__Vscopep, __Vfuncnum));\n"; // Can't use static_cast + string cbtype + = VIdProtect::protect(v3Global.opt.prefix() + "__Vcb_" + nodep->cname() + "_t"); + stmt += cbtype + " __Vcb = (" + cbtype + + ")(VerilatedScope::exportFind(__Vscopep, __Vfuncnum));\n"; // Can't use + // static_cast // If __Vcb is null the exportFind function throws and error dpip->addStmtsp(new AstCStmt(nodep->fileline(), stmt)); } // Convert input/inout DPI arguments to Internal types string args; - args += ("("+EmitCBaseVisitor::symClassName() - +"*)(__Vscopep->symsp())"); // Upcast w/o overhead + args += ("(" + EmitCBaseVisitor::symClassName() + + "*)(__Vscopep->symsp())"); // Upcast w/o overhead AstNode* argnodesp = NULL; - for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) { + for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) { if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO() && !portp->isFuncReturn() && portp != rtnvarp) { // No createDpiTemp; we make a real internal variable instead // SAME CODE BELOW - args+= ", "; + args += ", "; if (args != "") { - argnodesp = argnodesp->addNext( - new AstText(portp->fileline(), args, true)); + argnodesp = argnodesp->addNext(new AstText(portp->fileline(), args, true)); args = ""; } - AstVarScope* outvscp = createFuncVar(dpip, portp->name()+"__Vcvt", portp); + AstVarScope* outvscp = createFuncVar(dpip, portp->name() + "__Vcvt", portp); // No information exposure; is already visible in import/export func template outvscp->varp()->protect(false); portp->protect(false); - AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp, - portp->isWritable()); + AstVarRef* refp + = new AstVarRef(portp->fileline(), outvscp, portp->isWritable()); argnodesp = argnodesp->addNextNull(refp); if (portp->isNonOutput()) { @@ -723,12 +716,12 @@ private: if (rtnvarp) { AstVar* portp = rtnvarp; // SAME CODE ABOVE - args+= ", "; + args += ", "; if (args != "") { argnodesp = argnodesp->addNext(new AstText(portp->fileline(), args, true)); - args=""; + args = ""; } - AstVarScope* outvscp = createFuncVar(dpip, portp->name()+"__Vcvt", portp); + AstVarScope* outvscp = createFuncVar(dpip, portp->name() + "__Vcvt", portp); // No information exposure; is already visible in import/export func template outvscp->varp()->protect(false); AstVarRef* refp = new AstVarRef(portp->fileline(), outvscp, portp->isWritable()); @@ -742,13 +735,14 @@ private: stmt += "(*__Vcb)("; args += ");\n"; AstCStmt* newp = new AstCStmt(nodep->fileline(), stmt); - newp->addBodysp(argnodesp); VL_DANGLING(argnodesp); + newp->addBodysp(argnodesp); + VL_DANGLING(argnodesp); newp->addBodysp(new AstText(nodep->fileline(), args, true)); dpip->addStmtsp(newp); } // Convert output/inout arguments back to internal type - for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) { + for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) { if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO() && portp->isWritable() && !portp->isFuncReturn()) { dpip->addStmtsp(createAssignInternalToDpi(portp, true, "__Vcvt", "")); @@ -769,16 +763,13 @@ private: void makeDpiImportProto(AstNodeFTask* nodep, AstVar* rtnvarp) { if (nodep->cname() != AstNode::prettyName(nodep->cname())) { nodep->v3error("DPI function has illegal characters in C identifier name: " - <cname())); + << AstNode::prettyNameQ(nodep->cname())); } - AstCFunc* dpip = new AstCFunc(nodep->fileline(), - nodep->cname(), - m_scopep, + AstCFunc* dpip = new AstCFunc(nodep->fileline(), nodep->cname(), m_scopep, (rtnvarp ? rtnvarp->dpiArgType(true, true) - // Tasks (but not void functions) - // return bool indicating disabled - : nodep->dpiTask() ? "int" - : "")); + // Tasks (but not void functions) + // return bool indicating disabled + : nodep->dpiTask() ? "int" : "")); dpip->dontCombine(true); dpip->entryPoint(false); dpip->funcPublic(true); @@ -798,25 +789,24 @@ private: if (iter == m_dpiNames.end()) { m_dpiNames.insert(make_pair(nodep->cname(), make_pair(nodep, dpiproto))); return false; - } - else if (iter->second.second != dpiproto) { - nodep->v3error("Duplicate declaration of DPI function with different formal arguments: " - <prettyNameQ()<warnContextPrimary()<warnMore()<<"... New prototype: "<second.first->warnOther()<<"... Original prototype: " - <second.second<second.first->warnContextSecondary()); + } else if (iter->second.second != dpiproto) { + nodep->v3error( + "Duplicate declaration of DPI function with different formal arguments: " + << nodep->prettyNameQ() << endl + << nodep->warnContextPrimary() << endl + << nodep->warnMore() << "... New prototype: " << dpiproto << endl + << iter->second.first->warnOther() + << "... Original prototype: " << iter->second.second << endl + << iter->second.first->warnContextSecondary()); return true; - } - else { + } else { return true; } } void makePortList(AstNodeFTask* nodep, AstCFunc* dpip) { // Copy nodep's list of function I/O to the new dpip c function - for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) { + for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) { if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO()) { // Move it to new function @@ -824,9 +814,11 @@ private: newPortp->funcLocal(true); dpip->addArgsp(newPortp); if (!portp->basicp()) { - portp->v3error("Unsupported: DPI argument of type " - <basicp()->prettyTypeName()<warnMore()<<"... For best portability, use bit, byte, int, or longint"); + portp->v3error( + "Unsupported: DPI argument of type " + << portp->basicp()->prettyTypeName() << endl + << portp->warnMore() + << "... For best portability, use bit, byte, int, or longint"); // We don't warn on logic either, although the 4-stateness is lost. // That's what other simulators do. } @@ -838,41 +830,41 @@ private: void bodyDpiImportFunc(AstNodeFTask* nodep, AstVarScope* rtnvscp, AstCFunc* cfuncp) { // Convert input/inout arguments to DPI types string args; - for (AstNode* stmtp = cfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) { + for (AstNode* stmtp = cfuncp->argsp(); stmtp; stmtp = stmtp->nextp()) { if (AstVar* portp = VN_CAST(stmtp, Var)) { - AstVarScope* portvscp = VN_CAST(portp->user2p(), VarScope); // Remembered when we created it earlier + AstVarScope* portvscp + = VN_CAST(portp->user2p(), VarScope); // Remembered when we created it earlier if (portp->isIO() && !portp->isFuncReturn() && portvscp != rtnvscp && portp->name() != "__Vscopep" // Passed to dpiContext, not callee - && portp->name() != "__Vfilenamep" - && portp->name() != "__Vlineno") { + && portp->name() != "__Vfilenamep" && portp->name() != "__Vlineno") { - if (args != "") { args+= ", "; } + if (args != "") args += ", "; if (portp->isDpiOpenArray()) { // Ideally we'd make a table of variable // characteristics, and reuse it wherever we can // At least put them into the module's CTOR as static? - string propName = portp->name()+"__Vopenprops"; - string propCode = ("static const VerilatedVarProps "+propName - +"("+portp->vlPropInit()+");\n"); + string propName = portp->name() + "__Vopenprops"; + string propCode = ("static const VerilatedVarProps " + propName + "(" + + portp->vlPropInit() + ");\n"); cfuncp->addStmtsp(new AstCStmt(portp->fileline(), propCode)); // // At runtime we need the svOpenArrayHandle to // point to this task & thread's data, in addition // to static info about the variable - string name = portp->name()+"__Vopenarray"; - string varCode = ("VerilatedDpiOpenVar " - // NOLINTNEXTLINE(performance-inefficient-string-concatenation) - +name+" (&"+propName+", &"+portp->name()+");\n"); + string name = portp->name() + "__Vopenarray"; + string varCode + = ("VerilatedDpiOpenVar " + // NOLINTNEXTLINE(performance-inefficient-string-concatenation) + + name + " (&" + propName + ", &" + portp->name() + ");\n"); cfuncp->addStmtsp(new AstCStmt(portp->fileline(), varCode)); - args += "&"+name; - } - else { + args += "&" + name; + } else { if (portp->isWritable() && portp->basicp()->isDpiPrimitive()) { args += "&"; } - args += portp->name()+"__Vcvt"; + args += portp->name() + "__Vcvt"; cfuncp->addStmtsp(createDpiTemp(portp, "__Vcvt")); if (portp->isNonOutput()) { @@ -897,17 +889,18 @@ private: stmt = rtnvscp->varp()->name() + "__Vcvt"; stmt += rtnvscp->varp()->basicp()->isDpiPrimitive() ? " = " : "[0] = "; } - stmt += nodep->cname()+"("+args+");\n"; + stmt += nodep->cname() + "(" + args + ");\n"; cfuncp->addStmtsp(new AstCStmt(nodep->fileline(), stmt)); } // Convert output/inout arguments back to internal type - for (AstNode* stmtp = cfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) { + for (AstNode* stmtp = cfuncp->argsp(); stmtp; stmtp = stmtp->nextp()) { if (AstVar* portp = VN_CAST(stmtp, Var)) { portp->protect(false); // No additional exposure - already part of shown proto if (portp->isIO() && (portp->isWritable() || portp->isFuncReturn()) && !portp->isDpiOpenArray()) { - AstVarScope* portvscp = VN_CAST(portp->user2p(), VarScope); // Remembered when we created it earlier + AstVarScope* portvscp = VN_CAST( + portp->user2p(), VarScope); // Remembered when we created it earlier cfuncp->addStmtsp( createAssignDpiToInternal(portvscp, portp->name() + "__Vcvt")); } @@ -953,7 +946,8 @@ private: portp->unlinkFrBack(); rtnvarp = portp; rtnvarp->funcLocal(true); - rtnvarp->name(rtnvarp->name()+"__Vfuncrtn"); // Avoid conflict with DPI function name + rtnvarp->name(rtnvarp->name() + + "__Vfuncrtn"); // Avoid conflict with DPI function name if (nodep->dpiImport() || nodep->dpiExport()) rtnvarp->protect(false); } @@ -961,12 +955,9 @@ private: if (nodep->dpiOpenChild()) { // The parent will make the dpi proto UASSERT_OBJ(!nodep->dpiOpenParent(), nodep, "DPI task should be parent or wrapper, not both"); - } - else { // Parent or not open child, make wrapper + } else { // Parent or not open child, make wrapper string dpiproto = dpiprotoName(nodep, rtnvarp); - if (!duplicatedDpiProto(nodep, dpiproto)) { - makeDpiImportProto(nodep, rtnvarp); - } + if (!duplicatedDpiProto(nodep, dpiproto)) makeDpiImportProto(nodep, rtnvarp); if (nodep->dpiOpenParent()) { // No need to make more than just the c prototype, children will VL_DO_DANGLING(pushDeletep(nodep), nodep); @@ -976,9 +967,7 @@ private: } else if (nodep->dpiExport()) { string dpiproto = dpiprotoName(nodep, rtnvarp); - if (!duplicatedDpiProto(nodep, dpiproto)) { - makeDpiExportWrapper(nodep, rtnvarp); - } + if (!duplicatedDpiProto(nodep, dpiproto)) makeDpiExportWrapper(nodep, rtnvarp); } AstVarScope* rtnvscp = NULL; @@ -989,21 +978,21 @@ private: } string prefix; - if (nodep->dpiImport()) prefix = "__Vdpiimwrap_"; - else if (nodep->dpiExport()) prefix = "__Vdpiexp_"; - else if (ftaskNoInline) prefix = "__VnoInFunc_"; + if (nodep->dpiImport()) { + prefix = "__Vdpiimwrap_"; + } else if (nodep->dpiExport()) { + prefix = "__Vdpiexp_"; + } else if (ftaskNoInline) { + prefix = "__VnoInFunc_"; + } // Unless public, v3Descope will not uniquify function names even if duplicate per-scope, // so make it unique now. string suffix; // So, make them unique - if (!nodep->taskPublic()) suffix = "_"+m_scopep->nameDotless(); - string name = ((nodep->name() == "new") ? "new" - : prefix + nodep->name() + suffix); - AstCFunc* cfuncp = new AstCFunc(nodep->fileline(), - name, - m_scopep, - ((nodep->taskPublic() && rtnvarp) - ? rtnvarp->cPubArgType(true, true) - : "")); + if (!nodep->taskPublic()) suffix = "_" + m_scopep->nameDotless(); + string name = ((nodep->name() == "new") ? "new" : prefix + nodep->name() + suffix); + AstCFunc* cfuncp = new AstCFunc( + nodep->fileline(), name, m_scopep, + ((nodep->taskPublic() && rtnvarp) ? rtnvarp->cPubArgType(true, true) : "")); // It's ok to combine imports because this is just a wrapper; // duplicate wrappers can get merged. cfuncp->dontCombine(!nodep->dpiImport()); @@ -1014,7 +1003,7 @@ private: cfuncp->isStatic(!(nodep->dpiImport() || nodep->taskPublic() || nodep->classMethod())); cfuncp->pure(nodep->pure()); cfuncp->isConstructor(nodep->name() == "new"); - //cfuncp->dpiImport // Not set in the wrapper - the called function has it set + // cfuncp->dpiImport // Not set in the wrapper - the called function has it set if (cfuncp->dpiExport()) cfuncp->cname(nodep->cname()); bool needSyms = !nodep->dpiImport(); @@ -1022,9 +1011,8 @@ private: if (nodep->taskPublic()) { // We need to get a pointer to all of our variables (may // have eval'ed something else earlier) - cfuncp->addInitsp( - new AstCStmt(nodep->fileline(), - EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp;\n")); + cfuncp->addInitsp(new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symClassVar() + + " = this->__VlSymsp;\n")); } else { // Need symbol table cfuncp->argTypes(EmitCBaseVisitor::symClassVar()); @@ -1042,20 +1030,21 @@ private: } if (!nodep->dpiImport()) { - cfuncp->addInitsp(new AstCStmt(nodep->fileline(), - EmitCBaseVisitor::symTopAssign()+"\n")); + cfuncp->addInitsp( + new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign() + "\n")); } if (nodep->dpiExport()) { AstScopeName* snp = nodep->scopeNamep(); UASSERT_OBJ(snp, nodep, "Missing scoping context"); - snp->dpiExport(true); // The AstScopeName is really a statement(ish) for tracking, not a function + snp->dpiExport( + true); // The AstScopeName is really a statement(ish) for tracking, not a function snp->unlinkFrBack(); cfuncp->addInitsp(snp); } // Create list of arguments and move to function - for (AstNode* nextp, *stmtp = nodep->stmtsp(); stmtp; stmtp = nextp) { + for (AstNode *nextp, *stmtp = nodep->stmtsp(); stmtp; stmtp = nextp) { nextp = stmtp->nextp(); if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO()) { @@ -1081,10 +1070,11 @@ private: // Move body AstNode* bodysp = nodep->stmtsp(); - if (bodysp) { bodysp->unlinkFrBackWithNext(); cfuncp->addStmtsp(bodysp); } - if (nodep->dpiImport()) { - bodyDpiImportFunc(nodep, rtnvscp, cfuncp); + if (bodysp) { + bodysp->unlinkFrBackWithNext(); + cfuncp->addStmtsp(bodysp); } + if (nodep->dpiImport()) bodyDpiImportFunc(nodep, rtnvscp, cfuncp); // Return statement if (rtnvscp && nodep->taskPublic()) { @@ -1101,7 +1091,7 @@ private: } // Delete rest of cloned task and return new func VL_DO_DANGLING(pushDeletep(nodep), nodep); - if (debug()>=9) { cfuncp->dumpTree(cout, "-userFunc: "); } + if (debug() >= 9) cfuncp->dumpTree(cout, "-userFunc: "); return cfuncp; } @@ -1120,27 +1110,24 @@ private: AstNode* insertBeforeStmt(AstNode* nodep, AstNode* newp) { // Return node that must be visited, if any // See also AstNode::addBeforeStmt; this predates that function - if (debug()>=9) { nodep->dumpTree(cout, "-newstmt:"); } + if (debug() >= 9) nodep->dumpTree(cout, "-newstmt:"); UASSERT_OBJ(m_insStmtp, nodep, "Function not underneath a statement"); AstNode* visitp = NULL; if (m_insMode == IM_BEFORE) { // Add the whole thing before insertAt - UINFO(5," IM_Before "<=9) { newp->dumpTree(cout, "-newfunc:"); } + UINFO(5, " IM_Before " << m_insStmtp << endl); + if (debug() >= 9) newp->dumpTree(cout, "-newfunc:"); m_insStmtp->addHereThisAsNext(newp); - } - else if (m_insMode == IM_AFTER) { - UINFO(5," IM_After "<addNextHere(newp); - } - else if (m_insMode == IM_WHILE_PRECOND) { - UINFO(5," IM_While_Precond "<addPrecondsp(newp); visitp = newp; - } - else { + } else { nodep->v3fatalSrc("Unknown InsertMode"); } m_insMode = IM_AFTER; @@ -1175,17 +1162,17 @@ private: // Includes handling AstMethodCall, AstNew UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked?"); iterateIntoFTask(nodep->taskp()); // First, do hierarchical funcs - UINFO(4," FTask REF "<=9) { nodep->dumpTree(cout, "-inlfunc:"); } + UINFO(4, " FTask REF " << nodep << endl); + if (debug() >= 9) nodep->dumpTree(cout, "-inlfunc:"); UASSERT_OBJ(m_scopep, nodep, "func ref not under scope"); - string namePrefix = ((VN_IS(nodep, FuncRef) ? "__Vfunc_":"__Vtask_") - +nodep->taskp()->shortName()+"__"+cvtToStr(m_modNCalls++)); + string namePrefix = ((VN_IS(nodep, FuncRef) ? "__Vfunc_" : "__Vtask_") + + nodep->taskp()->shortName() + "__" + cvtToStr(m_modNCalls++)); // Create output variable AstVarScope* outvscp = NULL; if (nodep->taskp()->isFunction()) { // Not that it's a FUNCREF, but that we're calling a function (perhaps as a task) - outvscp = createVarScope(VN_CAST(nodep->taskp()->fvarp(), Var), - namePrefix+"__Vfuncout"); + outvscp + = createVarScope(VN_CAST(nodep->taskp()->fvarp(), Var), namePrefix + "__Vfuncout"); } // Create cloned statements AstNode* beginp; @@ -1211,8 +1198,9 @@ private: visitp = insertBeforeStmt(nodep, beginp); } else { if (nodep->taskp()->isFunction()) { - nodep->v3warn(IGNOREDRETURN, - "Ignoring return value of non-void function (IEEE 1800-2017 13.4.1)"); + nodep->v3warn( + IGNOREDRETURN, + "Ignoring return value of non-void function (IEEE 1800-2017 13.4.1)"); } // outvscp maybe non-NULL if calling a function in a taskref, // but if so we want to simply ignore the function result @@ -1220,12 +1208,12 @@ private: } // Cleanup VL_DO_DANGLING(nodep->deleteTree(), nodep); - UINFO(4," FTask REF Done.\n"); + UINFO(4, " FTask REF Done.\n"); // Visit nodes that normal iteration won't find if (visitp) iterateAndNextNull(visitp); } virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { - UINFO(4," Inline "<isFunction()) { if (AstVar* portp = VN_CAST(nodep->fvarp(), Var)) { AstVarScope* vscp = m_statep->findVarScope(m_scopep, portp); - UINFO(9," funcremovevsc "<unlinkFrBack()), vscp); } } - for (AstNode* nextp, *stmtp = nodep->stmtsp(); stmtp; stmtp = nextp) { + for (AstNode *nextp, *stmtp = nodep->stmtsp(); stmtp; stmtp = nextp) { nextp = stmtp->nextp(); if (AstVar* portp = VN_CAST(stmtp, Var)) { AstVarScope* vscp = m_statep->findVarScope(m_scopep, portp); - UINFO(9," funcremovevsc "<unlinkFrBack()), vscp); } } @@ -1309,7 +1297,8 @@ private: m_insStmtp = NULL; // Next thing should be new statement } virtual void visit(AstNodeFor* nodep) VL_OVERRIDE { - nodep->v3fatalSrc("For statements should have been converted to while statements in V3Begin.cpp"); + nodep->v3fatalSrc( + "For statements should have been converted to while statements in V3Begin.cpp"); } virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE { if (!nodep->isStatement()) { @@ -1386,14 +1375,14 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) NameToIndex::iterator it = nameToIndex.find(argp->name()); if (it == nameToIndex.end()) { pinp->v3error("No such argument " << argp->prettyNameQ() << " in function call to " - << nodep->taskp()->prettyTypeName()); + << nodep->taskp()->prettyTypeName()); // We'll just delete it; seems less error prone than making a false argument VL_DO_DANGLING(pinp->unlinkFrBack()->deleteTree(), pinp); } else { if (tconnects[it->second].second) { pinp->v3error("Duplicate argument " << argp->prettyNameQ() - << " in function call to " - << nodep->taskp()->prettyTypeName()); + << " in function call to " + << nodep->taskp()->prettyTypeName()); } argp->name(""); // Can forget name as will add back in pin order tconnects[it->second].second = argp; @@ -1487,16 +1476,15 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) return tconnects; } -string V3Task::assignInternalToDpi(AstVar* portp, bool isPtr, - const string& frSuffix, const string& toSuffix, - const string& frPrefix) { +string V3Task::assignInternalToDpi(AstVar* portp, bool isPtr, const string& frSuffix, + const string& toSuffix, const string& frPrefix) { // Create assignment from internal format into DPI temporary string stmt; string ket; // Someday we'll have better type support, and this can make variables and casts. // But for now, we'll just text-bash it. - string frName = frPrefix+portp->name()+frSuffix; - string toName = portp->name()+toSuffix; + string frName = frPrefix + portp->name() + frSuffix; + string toName = portp->name() + toSuffix; if (portp->basicp()->isDpiBitVec()) { stmt += ("VL_SET_SVBV_" + string(portp->dtypep()->charIQWN()) + "(" + cvtToStr(portp->width()) + ", " + toName + ", " + frName + ")"); @@ -1505,13 +1493,13 @@ string V3Task::assignInternalToDpi(AstVar* portp, bool isPtr, + cvtToStr(portp->width()) + ", " + toName + ", " + frName + ")"); } else { if (isPtr) stmt += "*"; // DPI outputs are pointers - stmt += toName+" = "; - if (portp->basicp() && portp->basicp()->keyword()==AstBasicDTypeKwd::CHANDLE) { + stmt += toName + " = "; + if (portp->basicp() && portp->basicp()->keyword() == AstBasicDTypeKwd::CHANDLE) { stmt += "VL_CVT_Q_VP("; ket += ")"; } stmt += frName; - if (portp->basicp() && portp->basicp()->keyword()==AstBasicDTypeKwd::STRING) { + if (portp->basicp() && portp->basicp()->keyword() == AstBasicDTypeKwd::STRING) { stmt += ".c_str()"; } } @@ -1520,8 +1508,8 @@ string V3Task::assignInternalToDpi(AstVar* portp, bool isPtr, } bool V3Task::dpiToInternalFrStmt(AstVar* portp, const string& frName, string& frstmt) { - if (portp->basicp() && portp->basicp()->keyword()==AstBasicDTypeKwd::CHANDLE) { - frstmt = "VL_CVT_VP_Q("+frName+")"; + if (portp->basicp() && portp->basicp()->keyword() == AstBasicDTypeKwd::CHANDLE) { + frstmt = "VL_CVT_VP_Q(" + frName + ")"; } else if ((portp->basicp() && portp->basicp()->isDpiPrimitive())) { frstmt = frName; } else { @@ -1539,10 +1527,10 @@ bool V3Task::dpiToInternalFrStmt(AstVar* portp, const string& frName, string& fr } void V3Task::taskAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp index 39602289f..76e125592 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -551,7 +551,7 @@ private: // Assign trace code, add to tree, return node for change tree or null // Look for identical copies uint32_t codePreassigned = 0; - // if (debug()>=9) nodep->dumpTree(cout, "- assnnode: "); + // if (debug() >= 9) nodep->dumpTree(cout, "- assnnode: "); // Find non-duplicated node; note some nodep's maybe null, as they were deleted below TraceTraceVertex* dupvertexp = vvertexp; if (dupvertexp->duplicatep()) { diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 4886e99d6..c2c0e8436 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -82,28 +82,29 @@ public: // Graph support classes class TristateVertex : public V3GraphVertex { - AstNode* m_nodep; - bool m_isTristate; // Logic indicates a tristate - bool m_feedsTri; // Propagates to a tristate node (on RHS) - bool m_processed; // Tristating was cleaned up + AstNode* m_nodep; + bool m_isTristate; // Logic indicates a tristate + bool m_feedsTri; // Propagates to a tristate node (on RHS) + bool m_processed; // Tristating was cleaned up public: TristateVertex(V3Graph* graphp, AstNode* nodep) : V3GraphVertex(graphp) - , m_nodep(nodep), m_isTristate(false), m_feedsTri(false), m_processed(false) {} + , m_nodep(nodep) + , m_isTristate(false) + , m_feedsTri(false) + , m_processed(false) {} virtual ~TristateVertex() {} // ACCESSORS AstNode* nodep() const { return m_nodep; } AstVar* varp() const { return VN_CAST(nodep(), Var); } virtual string name() const { - return ((isTristate() ? "tri\\n" - : feedsTri() ? "feed\\n" : "-\\n") - +(nodep()->prettyTypeName()+" "+cvtToHex(nodep()))); } + return ((isTristate() ? "tri\\n" : feedsTri() ? "feed\\n" : "-\\n") + + (nodep()->prettyTypeName() + " " + cvtToHex(nodep()))); + } virtual string dotColor() const { - return (varp() - ? (isTristate() ? "darkblue" - :feedsTri() ? "blue" : "lightblue") - : (isTristate() ? "darkgreen" - :feedsTri() ? "green" : "lightgreen")); } + return (varp() ? (isTristate() ? "darkblue" : feedsTri() ? "blue" : "lightblue") + : (isTristate() ? "darkgreen" : feedsTri() ? "green" : "lightgreen")); + } virtual FileLine* fileline() const { return nodep()->fileline(); } void isTristate(bool flag) { m_isTristate = flag; } bool isTristate() const { return m_isTristate; } @@ -118,13 +119,13 @@ public: class TristateGraph { // NODE STATE // AstVar::user5p -> TristateVertex* for variable being built - //AstUser5InUse m_inuser5; // In visitor below + // AstUser5InUse m_inuser5; // In visitor below // TYPES public: typedef std::vector VarVec; -private: +private: // MEMBERS V3Graph m_graph; // Logic graph @@ -141,7 +142,7 @@ private: TristateVertex* makeVertex(AstNode* nodep) { TristateVertex* vertexp = reinterpret_cast(nodep->user5p()); if (!vertexp) { - UINFO(6," New vertex "<user5p(vertexp); } @@ -156,21 +157,21 @@ private: if (!vtxp->isTristate()) return; // tristate involved if (vtxp->user() == 1) return; vtxp->user(1); // Recursed - UINFO(9," Mark tri "<varp()) { // not a var where we stop the recursion - for (V3GraphEdge* edgep = vtxp->outBeginp(); edgep; edgep=edgep->outNextp()) { + for (V3GraphEdge* edgep = vtxp->outBeginp(); edgep; edgep = edgep->outNextp()) { TristateVertex* vvertexp = dynamic_cast(edgep->top()); // Doesn't hurt to not check if already set, but by doing so when we // print out the debug messages, we'll see this node at level 0 instead. if (!vvertexp->isTristate()) { vvertexp->isTristate(true); - graphWalkRecurseFwd(vvertexp, level+1); + graphWalkRecurseFwd(vvertexp, level + 1); } } } else { // A variable is tristated. Find all of the LHS VARREFs that // drive this signal now need tristate drivers - for (V3GraphEdge* edgep = vtxp->inBeginp(); edgep; edgep=edgep->inNextp()) { + for (V3GraphEdge* edgep = vtxp->inBeginp(); edgep; edgep = edgep->inNextp()) { TristateVertex* vvertexp = dynamic_cast(edgep->fromp()); if (const AstVarRef* refp = VN_CAST(vvertexp->nodep(), VarRef)) { if (refp->lvalue() @@ -178,7 +179,7 @@ private: // print out the debug messages, we'll see this node at level 0 instead. && !vvertexp->isTristate()) { vvertexp->isTristate(true); - graphWalkRecurseFwd(vvertexp, level+1); + graphWalkRecurseFwd(vvertexp, level + 1); } } } @@ -193,15 +194,15 @@ private: if (!(vtxp->isTristate() || vtxp->feedsTri())) return; // tristate involved if (vtxp->user() == 3) return; vtxp->user(3); // Recursed - UINFO(9," Mark feedstri "<varp()) { // not a var where we stop the recursion - for (V3GraphEdge* edgep = vtxp->inBeginp(); edgep; edgep=edgep->inNextp()) { + for (V3GraphEdge* edgep = vtxp->inBeginp(); edgep; edgep = edgep->inNextp()) { TristateVertex* vvertexp = dynamic_cast(edgep->fromp()); // Doesn't hurt to not check if already set, but by doing so when we // print out the debug messages, we'll see this node at level 0 instead. if (!vvertexp->feedsTri()) { vvertexp->feedsTri(true); - graphWalkRecurseBack(vvertexp, level+1); + graphWalkRecurseBack(vvertexp, level + 1); } } } @@ -211,32 +212,30 @@ public: // METHODS bool empty() const { return m_graph.empty(); } void clear() { - for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) { + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { TristateVertex* vvertexp = static_cast(itp); if (vvertexp->isTristate() && !vvertexp->processed()) { // Not v3errorSrc as no reason to stop the world vvertexp->nodep()->v3error("Unsupported tristate construct" " (in graph; not converted): " - <nodep()->prettyTypeName()); + << vvertexp->nodep()->prettyTypeName()); } } m_graph.clear(); AstNode::user5ClearTree(); // Wipe all node user5p's that point to vertexes } void graphWalk(AstNodeModule* nodep) { - //if (debug()>=9) m_graph.dumpDotFilePrefixed("tri_pre__"+nodep->name()); - UINFO(9," Walking "<verticesNextp()) { + // if (debug() >= 9) m_graph.dumpDotFilePrefixed("tri_pre__" + nodep->name()); + UINFO(9, " Walking " << nodep << endl); + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { graphWalkRecurseFwd(static_cast(itp), 0); } - for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) { + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { graphWalkRecurseBack(static_cast(itp), 0); } - if (debug()>=9) m_graph.dumpDotFilePrefixed("tri_pos__"+nodep->name()); - } - void setTristate(AstNode* nodep) { - makeVertex(nodep)->isTristate(true); + if (debug() >= 9) m_graph.dumpDotFilePrefixed("tri_pos__" + nodep->name()); } + void setTristate(AstNode* nodep) { makeVertex(nodep)->isTristate(true); } void associate(AstNode* fromp, AstNode* top) { new V3GraphEdge(&m_graph, makeVertex(fromp), makeVertex(top), 1); } @@ -253,7 +252,7 @@ public: if (!vertexp) { // Not v3errorSrc as no reason to stop the world nodep->v3error("Unsupported tristate construct (not in propagation graph): " - <prettyTypeName()); + << nodep->prettyTypeName()); } else { // We don't warn if no vertexp->isTristate() as the creation // process makes midling nodes that don't have it set @@ -264,12 +263,10 @@ public: VarVec tristateVars() { // Return all tristate variables VarVec v; - for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) { + for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { TristateVertex* vvertexp = static_cast(itp); if (vvertexp->isTristate()) { - if (AstVar* nodep = VN_CAST(vvertexp->nodep(), Var)) { - v.push_back(nodep); - } + if (AstVar* nodep = VN_CAST(vvertexp->nodep(), Var)) v.push_back(nodep); } } return v; @@ -286,13 +283,13 @@ class TristatePinVisitor : public TristateBaseVisitor { // VISITORS virtual void visit(AstVarRef* nodep) VL_OVERRIDE { if (m_lvalue && !nodep->lvalue()) { - UINFO(9," Flip-to-LValue "<lvalue(true); } else if (!m_lvalue && nodep->lvalue()) { - UINFO(9," Flip-to-RValue "<lvalue(false); // Mark the ex-output as tristated - UINFO(9," setTristate-subpin "<varp()<varp() << endl); m_tgraph.setTristate(nodep->varp()); } } @@ -311,7 +308,8 @@ class TristatePinVisitor : public TristateBaseVisitor { public: // CONSTRUCTORS TristatePinVisitor(AstNode* nodep, TristateGraph& tgraph, bool lvalue) - : m_tgraph(tgraph), m_lvalue(lvalue) { + : m_tgraph(tgraph) + , m_lvalue(lvalue) { iterate(nodep); } virtual ~TristatePinVisitor() {} @@ -328,43 +326,43 @@ class TristateVisitor : public TristateBaseVisitor { // See TristateGraph: // AstVar::user5p -> TristateVertex* for variable being built // AstStmt*::user5p -> TristateVertex* for this statement - AstUser1InUse m_inuser1; - AstUser2InUse m_inuser2; - AstUser3InUse m_inuser3; - AstUser4InUse m_inuser4; - AstUser5InUse m_inuser5; + AstUser1InUse m_inuser1; + AstUser2InUse m_inuser2; + AstUser3InUse m_inuser3; + AstUser4InUse m_inuser4; + AstUser5InUse m_inuser5; // TYPES typedef std::vector RefVec; typedef std::map VarMap; - enum { U2_GRAPHING=1, // bit[0] if did m_graphing visit - U2_NONGRAPH=2, // bit[1] if did !m_graphing visit - U2_BOTH=3 }; // Both bits set + enum { + U2_GRAPHING = 1, // bit[0] if did m_graphing visit + U2_NONGRAPH = 2, // bit[1] if did !m_graphing visit + U2_BOTH = 3 + }; // Both bits set // MEMBERS - bool m_graphing; // Major mode - creating graph + bool m_graphing; // Major mode - creating graph // - AstNodeModule* m_modp; // Current module - AstCell* m_cellp; // current cell - VarMap m_lhsmap; // LHS driver map - int m_unique; - bool m_alhs; // On LHS of assignment - AstNode* m_logicp; // Current logic being built - TristateGraph m_tgraph; // Logic graph + AstNodeModule* m_modp; // Current module + AstCell* m_cellp; // current cell + VarMap m_lhsmap; // LHS driver map + int m_unique; + bool m_alhs; // On LHS of assignment + AstNode* m_logicp; // Current logic being built + TristateGraph m_tgraph; // Logic graph // STATS VDouble0 m_statTriSigs; // stat tracking // METHODS string dbgState() { - string o = (m_graphing?" gr ":" ng "); + string o = (m_graphing ? " gr " : " ng "); if (m_alhs) o += "alhs "; return o; } void associateLogic(AstNode* fromp, AstNode* top) { - if (m_logicp) { - m_tgraph.associate(fromp, top); - } + if (m_logicp) m_tgraph.associate(fromp, top); } AstNode* getEnp(AstNode* nodep) { // checks if user1p() is null, and if so, adds a constant output @@ -381,14 +379,15 @@ class TristateVisitor : public TristateBaseVisitor { AstVar* getCreateEnVarp(AstVar* invarp) { // Return the master __en for the specified input variable if (!invarp->user1p()) { - AstVar* newp = new AstVar(invarp->fileline(), - AstVarType::MODULETEMP, - invarp->name()+"__en", - invarp); - UINFO(9," newenv "<v3error("Unsupported: Creating tristate signal not underneath a module: " - <prettyNameQ()); } - else m_modp->addStmtp(newp); + AstVar* newp = new AstVar(invarp->fileline(), AstVarType::MODULETEMP, + invarp->name() + "__en", invarp); + UINFO(9, " newenv " << newp << endl); + if (!m_modp) { + invarp->v3error("Unsupported: Creating tristate signal not underneath a module: " + << invarp->prettyNameQ()); + } else { + m_modp->addStmtp(newp); + } invarp->user1p(newp); // find envar given invarp } return VN_CAST(invarp->user1p(), Var); @@ -397,34 +396,36 @@ class TristateVisitor : public TristateBaseVisitor { AstVar* getCreateOutVarp(AstVar* invarp) { // Return the master __out for the specified input variable if (!invarp->user4p()) { - AstVar* newp = new AstVar(invarp->fileline(), - AstVarType::MODULETEMP, - invarp->name()+"__out", - invarp); - UINFO(9," newout "<v3error("Unsupported: Creating tristate signal not underneath a module: " - <prettyNameQ()); } - else m_modp->addStmtp(newp); + AstVar* newp = new AstVar(invarp->fileline(), AstVarType::MODULETEMP, + invarp->name() + "__out", invarp); + UINFO(9, " newout " << newp << endl); + if (!m_modp) { + invarp->v3error("Unsupported: Creating tristate signal not underneath a module: " + << invarp->prettyNameQ()); + } else { + m_modp->addStmtp(newp); + } invarp->user4p(newp); // find outvar given invarp } return VN_CAST(invarp->user4p(), Var); } AstVar* getCreateUnconnVarp(AstNode* fromp, AstNodeDType* dtypep) { - AstVar* newp = new AstVar(fromp->fileline(), - AstVarType::MODULETEMP, - "__Vtriunconn"+cvtToStr(m_unique++), - dtypep); - UINFO(9," newunc "<v3error("Unsupported: Creating tristate signal not underneath a module"); } - else m_modp->addStmtp(newp); + AstVar* newp = new AstVar(fromp->fileline(), AstVarType::MODULETEMP, + "__Vtriunconn" + cvtToStr(m_unique++), dtypep); + UINFO(9, " newunc " << newp << endl); + if (!m_modp) { + newp->v3error("Unsupported: Creating tristate signal not underneath a module"); + } else { + m_modp->addStmtp(newp); + } return newp; } void mapInsertLhsVarRef(AstVarRef* nodep) { AstVar* key = nodep->varp(); VarMap::iterator it = m_lhsmap.find(key); - UINFO(9," mapInsertLhsVarRef "<push_back(nodep); @@ -438,11 +439,8 @@ class TristateVisitor : public TristateBaseVisitor { // Form a "deposit" instruction for given enable, using existing select as a template. // Would be nicer if we made this a new AST type AstNode* newp = new AstShiftL(selp->fileline(), - new AstExtend(selp->fileline(), - enp, - selp->fromp()->width()), - selp->lsbp()->cloneTree(false), - selp->fromp()->width()); + new AstExtend(selp->fileline(), enp, selp->fromp()->width()), + selp->lsbp()->cloneTree(false), selp->fromp()->width()); return newp; } @@ -453,9 +451,9 @@ class TristateVisitor : public TristateBaseVisitor { } else { if (oldpullp->direction() != pullp->direction()) { pullp->v3error("Unsupported: Conflicting pull directions.\n" - <warnContextPrimary()<warnOther()<<"... Location of conflicting pull.\n" - <warnContextSecondary()); + << pullp->warnContextPrimary() << endl + << oldpullp->warnOther() << "... Location of conflicting pull.\n" + << oldpullp->warnContextSecondary()); } } } @@ -465,14 +463,14 @@ class TristateVisitor : public TristateBaseVisitor { // The best way would be to visit the tree again and find any user1p() // pointers that did not get picked up and expanded. if (m_alhs && nodep->user1p()) { - nodep->v3error("Unsupported LHS tristate construct: "<prettyTypeName()); + nodep->v3error("Unsupported LHS tristate construct: " << nodep->prettyTypeName()); } // Ignore Var's because they end up adjacent to statements if ((nodep->op1p() && nodep->op1p()->user1p() && !VN_IS(nodep->op1p(), Var)) || (nodep->op2p() && nodep->op2p()->user1p() && !VN_IS(nodep->op1p(), Var)) || (nodep->op3p() && nodep->op3p()->user1p() && !VN_IS(nodep->op1p(), Var)) || (nodep->op4p() && nodep->op4p()->user1p() && !VN_IS(nodep->op1p(), Var))) { - nodep->v3error("Unsupported tristate construct: "<prettyTypeName()); + nodep->v3error("Unsupported tristate construct: " << nodep->prettyTypeName()); } } @@ -488,14 +486,14 @@ class TristateVisitor : public TristateBaseVisitor { if (it == m_lhsmap.end()) { // set output enable to always be off on this assign // statement so that this var is floating - UINFO(8," Adding driver to var "<fileline(), - AstConst::WidthedValue(), varp->width(), 0); + UINFO(8, " Adding driver to var " << varp << endl); + AstConst* constp = new AstConst(varp->fileline(), AstConst::WidthedValue(), + varp->width(), 0); AstVarRef* varrefp = new AstVarRef(varp->fileline(), varp, true); AstNode* newp = new AstAssignW(varp->fileline(), varrefp, constp); - UINFO(9," newoev "<user1p(new AstConst(varp->fileline(), - AstConst::WidthedValue(), varp->width(), 0)); + UINFO(9, " newoev " << newp << endl); + varrefp->user1p(new AstConst(varp->fileline(), AstConst::WidthedValue(), + varp->width(), 0)); nodep->addStmtp(newp); mapInsertLhsVarRef(varrefp); // insertTristates will convert // // to a varref to the __out# variable @@ -507,7 +505,8 @@ class TristateVisitor : public TristateBaseVisitor { // enable logic for any tristates. // Note there might not be any drivers. for (VarMap::iterator nextit, it = m_lhsmap.begin(); it != m_lhsmap.end(); it = nextit) { - nextit = it; ++nextit; + nextit = it; + ++nextit; AstVar* invarp = it->first; RefVec* refsp = it->second; @@ -539,14 +538,15 @@ class TristateVisitor : public TristateBaseVisitor { outvarp = getCreateOutVarp(invarp); outvarp->varType2Out(); lhsp = outvarp; // Must assign to __out, not to normal input signal - UINFO(9, " TRISTATE propagates up with "<varType2Out(); // outvarp->user1p(envarp); outvarp->user3p(invarp->user3p()); // AstPull* propagation - if (invarp->user3p()) UINFO(9, "propagate pull to "<user3p()) UINFO(9, "propagate pull to " << outvarp << endl); } else if (invarp->user1p()) { envarp = VN_CAST(invarp->user1p(), Var); // From CASEEQ, foo === 1'bz } @@ -561,27 +561,24 @@ class TristateVisitor : public TristateBaseVisitor { int w = lhsp->width(); // create the new lhs driver for this var - AstVar* newlhsp = new AstVar(lhsp->fileline(), - AstVarType::MODULETEMP, - lhsp->name()+"__out"+cvtToStr(m_unique), + AstVar* newlhsp = new AstVar(lhsp->fileline(), AstVarType::MODULETEMP, + lhsp->name() + "__out" + cvtToStr(m_unique), VFlagBitPacked(), w); // 2-state ok; sep enable - UINFO(9," newout "<addStmtp(newlhsp); refp->varp(newlhsp); // assign the new var to the varref refp->name(newlhsp->name()); // create a new var for this drivers enable signal - AstVar* newenp = new AstVar(lhsp->fileline(), - AstVarType::MODULETEMP, - lhsp->name()+"__en"+cvtToStr(m_unique++), - VFlagBitPacked(), w); // 2-state ok - UINFO(9," newenp "<fileline(), AstVarType::MODULETEMP, + lhsp->name() + "__en" + cvtToStr(m_unique++), + VFlagBitPacked(), w); // 2-state ok + UINFO(9, " newenp " << newenp << endl); nodep->addStmtp(newenp); - AstNode* enassp = new AstAssignW(refp->fileline(), - new AstVarRef(refp->fileline(), newenp, true), - getEnp(refp)); - UINFO(9," newass "<fileline(), new AstVarRef(refp->fileline(), newenp, true), getEnp(refp)); + UINFO(9, " newass " << enassp << endl); nodep->addStmtp(enassp); // now append this driver to the driver logic. @@ -598,11 +595,11 @@ class TristateVisitor : public TristateBaseVisitor { } AstNode* tmp = new AstNot(newenp->fileline(), new AstVarRef(newenp->fileline(), newenp, false)); - undrivenp = ((!undrivenp) ? tmp - : new AstAnd(refp->fileline(), tmp, undrivenp)); + undrivenp = ((!undrivenp) ? tmp : new AstAnd(refp->fileline(), tmp, undrivenp)); } if (!undrivenp) { // No drivers on the bus - V3Number ones(invarp, lhsp->width()); ones.setAllBits1(); + V3Number ones(invarp, lhsp->width()); + ones.setAllBits1(); undrivenp = new AstConst(invarp->fileline(), ones); } if (!outvarp) { @@ -612,7 +609,7 @@ class TristateVisitor : public TristateBaseVisitor { AstPull* pullp = static_cast(lhsp->user3p()); if (pullp && pullp->direction() == 1) { pull.setAllBits1(); - UINFO(9,"Has pullup "<deleteTree(), undrivenp); } if (envarp) { - nodep->addStmtp(new AstAssignW(enp->fileline(), - new AstVarRef(envarp->fileline(), - envarp, true), enp)); + nodep->addStmtp(new AstAssignW( + enp->fileline(), new AstVarRef(envarp->fileline(), envarp, true), enp)); } // __out (child) or (parent) = drive-value expression AstNode* assp = new AstAssignW(lhsp->fileline(), - new AstVarRef(lhsp->fileline(), - lhsp, - true), - orp); + new AstVarRef(lhsp->fileline(), lhsp, true), orp); assp->user2(U2_BOTH); // Don't process further; already resolved - if (debug()>=9) assp->dumpTree(cout, "-lhsp-eqn: "); + if (debug() >= 9) assp->dumpTree(cout, "-lhsp-eqn: "); nodep->addStmtp(assp); // Delete the map and vector list now that we have expanded it. m_lhsmap.erase(invarp); @@ -644,11 +637,9 @@ class TristateVisitor : public TristateBaseVisitor { // VISITORS virtual void visit(AstConst* nodep) VL_OVERRIDE { - UINFO(9,dbgState()<num().hasZ()) { - m_tgraph.setTristate(nodep); - } + if (!m_alhs && nodep->num().hasZ()) m_tgraph.setTristate(nodep); } else { // Detect any Z consts and convert them to 0's with an enable that is also 0. if (m_alhs && nodep->user1p()) { @@ -657,21 +648,20 @@ class TristateVisitor : public TristateBaseVisitor { // We can ignore the output override by making a temporary AstVar* varp = getCreateUnconnVarp(nodep, nodep->dtypep()); AstNode* newp = new AstVarRef(nodep->fileline(), varp, true); - UINFO(9," const->"<" << newp << endl); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - else if (m_tgraph.isTristate(nodep)) { + } else if (m_tgraph.isTristate(nodep)) { m_tgraph.didProcess(nodep); FileLine* fl = nodep->fileline(); - V3Number numz (nodep, nodep->width()); + V3Number numz(nodep, nodep->width()); numz.opBitsZ(nodep->num()); // Z->1, else 0 V3Number numz0(nodep, nodep->width()); numz0.opNot(numz); // Z->0, else 1 - V3Number num1 (nodep, nodep->width()); + V3Number num1(nodep, nodep->width()); num1.opAnd(nodep->num(), numz0); // 01X->01X, Z->0 AstConst* newconstp = new AstConst(fl, num1); - AstConst* enp = new AstConst(fl, numz0); + AstConst* enp = new AstConst(fl, numz0); nodep->replaceWith(newconstp); VL_DO_DANGLING(pushDeletep(nodep), nodep); newconstp->user1p(enp); // Propagate up constant with non-Z bits as 1 @@ -691,19 +681,19 @@ class TristateVisitor : public TristateBaseVisitor { } } else { if (m_alhs && nodep->user1p()) { - nodep->v3error("Unsupported LHS tristate construct: " - <prettyTypeName()); + nodep->v3error("Unsupported LHS tristate construct: " << nodep->prettyTypeName()); return; } iterateChildren(nodep); - UINFO(9,dbgState()<condp(); + AstNode* condp = nodep->condp(); if (condp->user1p()) { - condp->v3error("Unsupported: don't know how to deal with tristate logic in the conditional expression"); + condp->v3error("Unsupported: don't know how to deal with " + "tristate logic in the conditional expression"); } AstNode* expr1p = nodep->expr1p(); AstNode* expr2p = nodep->expr2p(); @@ -714,7 +704,7 @@ class TristateVisitor : public TristateBaseVisitor { // The output enable of a cond is a cond of the output enable of the // two expressions with the same conditional. AstNode* enp = new AstCond(nodep->fileline(), condp->cloneTree(false), en1p, en2p); - UINFO(9," newcond "<user1p(enp); // propagate up COND(lhsp->enable, rhsp->enable) expr1p->user1p(NULL); expr2p->user1p(NULL); @@ -732,27 +722,28 @@ class TristateVisitor : public TristateBaseVisitor { } } else { if (m_alhs) { - UINFO(9,dbgState()<user1p()) { // Form a "deposit" instruction. Would be nicer if we made this a new AST type AstNode* newp = newEnableDeposit(nodep, nodep->user1p()); nodep->fromp()->user1p(newp); // Push to varref (etc) - if (debug()>=9) newp->dumpTree(cout, "-assign-sel; "); + if (debug() >= 9) newp->dumpTree(cout, "-assign-sel; "); m_tgraph.didProcess(nodep); } iterateChildren(nodep); } else { iterateChildren(nodep); - UINFO(9,dbgState()<lsbp()->user1p()) { - nodep->v3error("Unsupported RHS tristate construct: "<prettyTypeName()); + nodep->v3error( + "Unsupported RHS tristate construct: " << nodep->prettyTypeName()); } if (nodep->fromp()->user1p()) { // SEL(VARREF, lsb) AstNode* en1p = getEnp(nodep->fromp()); - AstNode* enp = new AstSel(nodep->fileline(), en1p, - nodep->lsbp()->cloneTree(true), - nodep->widthp()->cloneTree(true)); - UINFO(9," newsel "<fileline(), en1p, nodep->lsbp()->cloneTree(true), + nodep->widthp()->cloneTree(true)); + UINFO(9, " newsel " << enp << endl); nodep->user1p(enp); // propagate up SEL(fromp->enable, value) m_tgraph.didProcess(nodep); } @@ -770,28 +761,24 @@ class TristateVisitor : public TristateBaseVisitor { associateLogic(nodep->lhsp(), nodep); associateLogic(nodep->rhsp(), nodep); } - } - else { + } else { if (m_alhs) { - UINFO(9,dbgState()<user1p()) { // Each half of the concat gets a select of the enable expression AstNode* enp = nodep->user1p(); nodep->user1p(NULL); - nodep->lhsp()->user1p(new AstSel(nodep->fileline(), - enp->cloneTree(true), + nodep->lhsp()->user1p(new AstSel(nodep->fileline(), enp->cloneTree(true), nodep->rhsp()->width(), nodep->lhsp()->width())); - nodep->rhsp()->user1p(new AstSel(nodep->fileline(), - enp, - 0, - nodep->rhsp()->width())); + nodep->rhsp()->user1p( + new AstSel(nodep->fileline(), enp, 0, nodep->rhsp()->width())); m_tgraph.didProcess(nodep); } iterateChildren(nodep); } else { iterateChildren(nodep); - UINFO(9,dbgState()<lhsp(); @@ -801,7 +788,7 @@ class TristateVisitor : public TristateBaseVisitor { AstNode* en1p = getEnp(expr1p); AstNode* en2p = getEnp(expr2p); AstNode* enp = new AstConcat(nodep->fileline(), en1p, en2p); - UINFO(9," newconc "<user1p(enp); // propagate up CONCAT(lhsp->enable, rhsp->enable) expr1p->user1p(NULL); expr2p->user1p(NULL); @@ -813,14 +800,14 @@ class TristateVisitor : public TristateBaseVisitor { virtual void visit(AstBufIf1* nodep) VL_OVERRIDE { // For BufIf1, the enable is the LHS expression iterateChildren(nodep); - UINFO(9,dbgState()<rhsp(), nodep); m_tgraph.setTristate(nodep); } else { - if (debug()>=9) nodep->backp()->dumpTree(cout, "-bufif: "); + if (debug() >= 9) nodep->backp()->dumpTree(cout, "-bufif: "); if (m_alhs) { - nodep->v3error("Unsupported LHS tristate construct: "<prettyTypeName()); + nodep->v3error("Unsupported LHS tristate construct: " << nodep->prettyTypeName()); return; } m_tgraph.didProcess(nodep); @@ -836,21 +823,21 @@ class TristateVisitor : public TristateBaseVisitor { expr2p->user1p(enp); // Becomes new node // Don't need the BufIf any more, can just have the data direct nodep->replaceWith(expr2p); - UINFO(9," bufif datap="<prettyTypeName()); + nodep->v3error("Unsupported LHS tristate construct: " << nodep->prettyTypeName()); return; } // ANDs and Z's have issues. Earlier optimizations convert @@ -881,27 +868,19 @@ class TristateVisitor : public TristateBaseVisitor { subexpr2p = new AstNot(nodep->fileline(), subexpr2p); } // calc new output enable - AstNode* enp = new AstOr(nodep->fileline(), - new AstAnd(nodep->fileline(), en1p, en2p), - new AstOr(nodep->fileline(), - new AstAnd(nodep->fileline(), - en1p->cloneTree(false), - subexpr1p), - new AstAnd(nodep->fileline(), - en2p->cloneTree(false), - subexpr2p))); - UINFO(9," neweqn "<fileline(), new AstAnd(nodep->fileline(), en1p, en2p), + new AstOr(nodep->fileline(), + new AstAnd(nodep->fileline(), en1p->cloneTree(false), subexpr1p), + new AstAnd(nodep->fileline(), en2p->cloneTree(false), subexpr2p))); + UINFO(9, " neweqn " << enp << endl); nodep->user1p(enp); expr1p->user1p(NULL); expr2p->user1p(NULL); } } - virtual void visit(AstAnd* nodep) VL_OVERRIDE { - visitAndOr(nodep, true); - } - virtual void visit(AstOr* nodep) VL_OVERRIDE { - visitAndOr(nodep, false); - } + virtual void visit(AstAnd* nodep) VL_OVERRIDE { visitAndOr(nodep, true); } + virtual void visit(AstOr* nodep) VL_OVERRIDE { visitAndOr(nodep, false); } void visitAssign(AstNodeAssign* nodep) { if (m_graphing) { @@ -916,11 +895,13 @@ class TristateVisitor : public TristateBaseVisitor { associateLogic(nodep, nodep->lhsp()); m_logicp = NULL; } else { - if (nodep->user2() & U2_NONGRAPH) return; // Iterated here, or created assignment to ignore + if (nodep->user2() & U2_NONGRAPH) { + return; // Iterated here, or created assignment to ignore + } nodep->user2(U2_NONGRAPH); iterateAndNextNull(nodep->rhsp()); - UINFO(9,dbgState()<=9) nodep->dumpTree(cout, "-assign: "); + UINFO(9, dbgState() << nodep << endl); + if (debug() >= 9) nodep->dumpTree(cout, "-assign: "); // if the rhsp of this assign statement has an output enable driver, // then propagate the corresponding output enable assign statement. // down the lvalue tree by recursion for eventual attachment to @@ -928,7 +909,7 @@ class TristateVisitor : public TristateBaseVisitor { if (nodep->rhsp()->user1p()) { nodep->lhsp()->user1p(nodep->rhsp()->user1p()); nodep->rhsp()->user1p(NULL); - UINFO(9," enp<-rhs "<lhsp()->user1p()<lhsp()->user1p() << endl); m_tgraph.didProcess(nodep); } m_alhs = true; // And user1p() will indicate tristate equation, if any @@ -936,12 +917,8 @@ class TristateVisitor : public TristateBaseVisitor { m_alhs = false; } } - virtual void visit(AstAssignW* nodep) VL_OVERRIDE { - visitAssign(nodep); - } - virtual void visit(AstAssign* nodep) VL_OVERRIDE { - visitAssign(nodep); - } + virtual void visit(AstAssignW* nodep) VL_OVERRIDE { visitAssign(nodep); } + virtual void visit(AstAssign* nodep) VL_OVERRIDE { visitAssign(nodep); } void visitCaseEq(AstNodeBiop* nodep, bool neq) { if (m_graphing) { @@ -953,25 +930,26 @@ class TristateVisitor : public TristateBaseVisitor { // Otherwise we'd need to attach an enable to every signal, then optimize them // away later when we determine the signal has no tristate iterateChildren(nodep); - UINFO(9,dbgState()<lhsp(), Const); // Constification always moves const to LHS + UINFO(9, dbgState() << nodep << endl); + // Constification always moves const to LHS + const AstConst* constp = VN_CAST(nodep->lhsp(), Const); AstVarRef* varrefp = VN_CAST(nodep->rhsp(), VarRef); // Input variable if (constp && constp->user1p() && varrefp) { // 3'b1z0 -> ((3'b101 == in__en) && (3'b100 == in)) varrefp->unlinkFrBack(); FileLine* fl = nodep->fileline(); - V3Number oneIfEn = VN_CAST(constp->user1p(), Const)->num(); // visit(AstConst) already split into en/ones + V3Number oneIfEn = VN_CAST(constp->user1p(), Const) + ->num(); // visit(AstConst) already split into en/ones V3Number oneIfEnOne = constp->num(); AstVar* envarp = getCreateEnVarp(varrefp->varp()); - AstNode* newp = new AstLogAnd(fl, new AstEq(fl, new AstConst(fl, oneIfEn), - new AstVarRef(fl, envarp, false)), - // Keep the caseeq if there are X's present - new AstEqCase(fl, new AstConst(fl, oneIfEnOne), - varrefp)); + AstNode* newp = new AstLogAnd( + fl, new AstEq(fl, new AstConst(fl, oneIfEn), new AstVarRef(fl, envarp, false)), + // Keep the caseeq if there are X's present + new AstEqCase(fl, new AstConst(fl, oneIfEnOne), varrefp)); if (neq) newp = new AstLogNot(fl, newp); - UINFO(9," newceq "<=9) nodep->dumpTree(cout, "-caseeq-old: "); - if (debug()>=9) newp->dumpTree(cout, "-caseeq-new: "); + UINFO(9, " newceq " << newp << endl); + if (debug() >= 9) nodep->dumpTree(cout, "-caseeq-old: "); + if (debug() >= 9) newp->dumpTree(cout, "-caseeq-new: "); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } else { @@ -981,30 +959,23 @@ class TristateVisitor : public TristateBaseVisitor { } void visitEqNeqWild(AstNodeBiop* nodep) { if (!VN_IS(nodep->rhsp(), Const)) { - nodep->v3error("Unsupported: RHS of ==? or !=? must be constant to be synthesizable"); // Says spec. + nodep->v3error( // Says spac. + "Unsupported: RHS of ==? or !=? must be constant to be synthesizable"); // rhs we want to keep X/Z intact, so otherwise ignore } iterateAndNextNull(nodep->lhsp()); if (nodep->lhsp()->user1p()) { - nodep->v3error("Unsupported LHS tristate construct: "<prettyTypeName()); + nodep->v3error("Unsupported LHS tristate construct: " << nodep->prettyTypeName()); return; } } - virtual void visit(AstEqCase* nodep) VL_OVERRIDE { - visitCaseEq(nodep, false); - } - virtual void visit(AstNeqCase* nodep) VL_OVERRIDE { - visitCaseEq(nodep, true); - } - virtual void visit(AstEqWild* nodep) VL_OVERRIDE { - visitEqNeqWild(nodep); - } - virtual void visit(AstNeqWild* nodep) VL_OVERRIDE { - visitEqNeqWild(nodep); - } + virtual void visit(AstEqCase* nodep) VL_OVERRIDE { visitCaseEq(nodep, false); } + virtual void visit(AstNeqCase* nodep) VL_OVERRIDE { visitCaseEq(nodep, true); } + virtual void visit(AstEqWild* nodep) VL_OVERRIDE { visitEqNeqWild(nodep); } + virtual void visit(AstNeqWild* nodep) VL_OVERRIDE { visitEqNeqWild(nodep); } virtual void visit(AstPull* nodep) VL_OVERRIDE { - UINFO(9,dbgState()<lhsp(), VarRef)) { varrefp = VN_CAST(nodep->lhsp(), VarRef); @@ -1013,7 +984,7 @@ class TristateVisitor : public TristateBaseVisitor { varrefp = VN_CAST(VN_CAST(nodep->lhsp(), Sel)->fromp(), VarRef); } if (!varrefp) { - if (debug()>=4) nodep->dumpTree(cout, "- "); + if (debug() >= 4) nodep->dumpTree(cout, "- "); nodep->v3error("Unsupported pullup/down (weak driver) construct."); } else { if (m_graphing) { @@ -1052,9 +1023,7 @@ class TristateVisitor : public TristateBaseVisitor { m_logicp = NULL; } else { // All heavy lifting completed in graph visitor. - if (nodep->exprp()) { - m_tgraph.didProcess(nodep); - } + if (nodep->exprp()) m_tgraph.didProcess(nodep); iterateChildren(nodep); } } @@ -1093,8 +1062,8 @@ class TristateVisitor : public TristateBaseVisitor { return; // No __en signals on this pin } // Tristate exists: - UINFO(9,dbgState()<=9) nodep->dumpTree(cout, "-pin-pre: "); + UINFO(9, dbgState() << nodep << endl); + if (debug() >= 9) nodep->dumpTree(cout, "-pin-pre: "); // Empty/in-only; need Z to propagate bool inDeclProcessing = (nodep->exprp() @@ -1105,7 +1074,7 @@ class TristateVisitor : public TristateBaseVisitor { // to have this. && !nodep->modVarp()->declDirection().isWritable()); if (!nodep->exprp()) { // No-connect; covert to empty connection - UINFO(5,"Unconnected pin terminate "<modVarp()->dtypep()); nodep->exprp(new AstVarRef(nodep->fileline(), ucVarp, // We converted, so use declaration output state @@ -1116,7 +1085,7 @@ class TristateVisitor : public TristateBaseVisitor { // Input only may have driver in underneath module which would stomp // the input value. So make a temporary connection. AstAssignW* reAssignp = V3Inst::pinReconnectSimple(nodep, m_cellp, true, true); - UINFO(5,"Input pin buffering: "<lhsp()); } @@ -1126,23 +1095,21 @@ class TristateVisitor : public TristateBaseVisitor { // Create the output enable pin, connect to new signal AstNode* enrefp; { - AstVar* enVarp = new AstVar(nodep->fileline(), - AstVarType::MODULETEMP, + AstVar* enVarp = new AstVar(nodep->fileline(), AstVarType::MODULETEMP, nodep->name() + "__en" + cvtToStr(m_unique++), VFlagBitPacked(), enModVarp->width()); - UINFO(9," newenv "<fileline(), - nodep->pinNum(), + UINFO(9, " newenv " << enVarp << endl); + AstPin* enpinp = new AstPin(nodep->fileline(), nodep->pinNum(), enModVarp->name(), // should be {var}"__en" new AstVarRef(nodep->fileline(), enVarp, true)); enpinp->modVarp(enModVarp); - UINFO(9," newpin "<user2(U2_BOTH); // don't iterate the pin later nodep->addNextHere(enpinp); m_modp->addStmtp(enVarp); enrefp = new AstVarRef(nodep->fileline(), enVarp, false); - UINFO(9," newvrf "<=9) enpinp->dumpTree(cout, "-pin-ena: "); + UINFO(9, " newvrf " << enrefp << endl); + if (debug() >= 9) enpinp->dumpTree(cout, "-pin-ena: "); } // Create new output pin AstAssignW* outAssignp = NULL; // If reconnected, the related assignment @@ -1151,16 +1118,16 @@ class TristateVisitor : public TristateBaseVisitor { if (!outModVarp) { // At top, no need for __out as might be input only. Otherwise resolvable. if (!m_modp->isTop()) { - nodep->v3error("Unsupported: tristate in top-level IO: " << nodep->prettyNameQ()); + nodep->v3error( + "Unsupported: tristate in top-level IO: " << nodep->prettyNameQ()); } } else { AstNode* outexprp = nodep->exprp()->cloneTree(false); // Note has lvalue() set - outpinp = new AstPin(nodep->fileline(), - nodep->pinNum(), + outpinp = new AstPin(nodep->fileline(), nodep->pinNum(), outModVarp->name(), // should be {var}"__out" outexprp); outpinp->modVarp(outModVarp); - UINFO(9," newpin "<user2(U2_BOTH); // don't iterate the pin later nodep->addNextHere(outpinp); // Simplify @@ -1170,20 +1137,22 @@ class TristateVisitor : public TristateBaseVisitor { // simple, it will flip ArraySel's and such, but if the // pin is an input the earlier reconnectSimple made it // a VarRef without any ArraySel, etc - TristatePinVisitor visitor (outexprp, m_tgraph, true); + TristatePinVisitor visitor(outexprp, m_tgraph, true); } - if (debug()>=9) outpinp->dumpTree(cout, "-pin-opr: "); - outAssignp = V3Inst::pinReconnectSimple(outpinp, m_cellp, true); // Note may change outpinp->exprp() - if (debug()>=9) outpinp->dumpTree(cout, "-pin-out: "); - if (debug()>=9 && outAssignp) outAssignp->dumpTree(cout, "-pin-out: "); + if (debug() >= 9) outpinp->dumpTree(cout, "-pin-opr: "); + outAssignp = V3Inst::pinReconnectSimple(outpinp, m_cellp, + true); // Note may change outpinp->exprp() + if (debug() >= 9) outpinp->dumpTree(cout, "-pin-out: "); + if (debug() >= 9 && outAssignp) outAssignp->dumpTree(cout, "-pin-out: "); // Must still iterate the outAssignp, as need to build output equation } // Existing pin becomes an input, and we mark each resulting signal as tristate - TristatePinVisitor visitor (nodep->exprp(), m_tgraph, false); - AstNode* inAssignp = V3Inst::pinReconnectSimple(nodep, m_cellp, true); // Note may change nodep->exprp() - if (debug()>=9) nodep->dumpTree(cout, "-pin-in: "); - if (debug()>=9 && inAssignp) inAssignp->dumpTree(cout, "-pin-as: "); + TristatePinVisitor visitor(nodep->exprp(), m_tgraph, false); + AstNode* inAssignp = V3Inst::pinReconnectSimple( + nodep, m_cellp, true); // Note may change nodep->exprp() + if (debug() >= 9) nodep->dumpTree(cout, "-pin-in: "); + if (debug() >= 9 && inAssignp) inAssignp->dumpTree(cout, "-pin-as: "); // Connect enable to output signal AstVarRef* exprrefp; // Tristate variable that the Pin's expression refers to @@ -1193,18 +1162,24 @@ class TristateVisitor : public TristateBaseVisitor { } else { // pinReconnect should have converted this exprrefp = VN_CAST(outpinp->exprp(), VarRef); - if (!exprrefp) nodep->v3error("Unsupported tristate port expression: " - <exprp()->prettyTypeName()); + if (!exprrefp) { + nodep->v3error("Unsupported tristate port expression: " + << nodep->exprp()->prettyTypeName()); + } } } else { // pinReconnect should have converted this - exprrefp = VN_CAST(outAssignp->rhsp(), VarRef); // This should be the same var as the output pin - if (!exprrefp) nodep->v3error("Unsupported tristate port expression: " - <exprp()->prettyTypeName()); + exprrefp = VN_CAST(outAssignp->rhsp(), + VarRef); // This should be the same var as the output pin + if (!exprrefp) { + nodep->v3error("Unsupported tristate port expression: " + << nodep->exprp()->prettyTypeName()); + } } if (exprrefp) { - UINFO(9,"outref "<user1p(enrefp); // Mark as now tristated; iteration will pick it up from there + UINFO(9, "outref " << exprrefp << endl); + // Mark as now tristated; iteration will pick it up from there + exprrefp->user1p(enrefp); if (!outAssignp) { mapInsertLhsVarRef(exprrefp); // insertTristates will convert // // to a varref to the __out# variable @@ -1214,7 +1189,7 @@ class TristateVisitor : public TristateBaseVisitor { // Propagate any pullups/pulldowns upwards if necessary if (exprrefp) { if (AstPull* pullp = static_cast(nodep->modVarp()->user3p())) { - UINFO(9, "propagate pull on "<varp(), pullp); } } @@ -1228,13 +1203,13 @@ class TristateVisitor : public TristateBaseVisitor { else { if (nodep->user2() & U2_NONGRAPH) return; // This pin is already expanded nodep->user2(U2_NONGRAPH); - UINFO(9," "<lvalue()) { associateLogic(nodep, nodep->varp()); @@ -1248,18 +1223,18 @@ class TristateVisitor : public TristateBaseVisitor { // VarMap so that after the walk through the module we can expand // any tristate logic on the driver. if (nodep->lvalue() && m_tgraph.isTristate(nodep->varp())) { - UINFO(9," Ref-to-lvalue "<lvalue() - && !nodep->user1p() // Not already processed, nor varref from visit(AstPin) creation - // Reference to another tristate variable - && m_tgraph.isTristate(nodep->varp()) - // and in a position where it feeds upstream to another tristate - && m_tgraph.feedsTri(nodep)) { + } else if (!nodep->lvalue() + // Not already processed, nor varref from visit(AstPin) creation + && !nodep->user1p() + // Reference to another tristate variable + && m_tgraph.isTristate(nodep->varp()) + // and in a position where it feeds upstream to another tristate + && m_tgraph.feedsTri(nodep)) { // Then propagate the enable from the original variable - UINFO(9," Ref-to-tri "<varp()); nodep->user1p(new AstVarRef(nodep->fileline(), enVarp, false)); } @@ -1269,16 +1244,16 @@ class TristateVisitor : public TristateBaseVisitor { virtual void visit(AstVar* nodep) VL_OVERRIDE { iterateChildren(nodep); - UINFO(9,dbgState()<user2() & U2_GRAPHING) return; // Already processed nodep->user2(U2_GRAPHING); if (nodep->isPulldown() || nodep->isPullup()) { - AstNode* newp = new AstPull(nodep->fileline(), - new AstVarRef(nodep->fileline(), nodep, true), - nodep->isPullup()); - UINFO(9," newpul "<fileline(), new AstVarRef(nodep->fileline(), nodep, true), + nodep->isPullup()); + UINFO(9, " newpul " << newp << endl); nodep->addNextHere(newp); // We'll iterate on the new AstPull later } @@ -1288,8 +1263,8 @@ class TristateVisitor : public TristateBaseVisitor { // versions and causes outputs that don't come from anywhere to // possibly create connection errors. // One example of problems is this: "output z; task t; z <= {something}; endtask" - ) { - UINFO(9," setTristate-inout "<= 3); } diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp index 8178d6742..6f29dcd03 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -51,16 +51,12 @@ class UndrivenVarEntry { public: // CONSTRUCTORS explicit UndrivenVarEntry(AstVar* varp) { // Construction for when a var is used - UINFO(9, "create "<width() * FLAGS_PER_BIT); - for (int i = 0; i < varp->width() * FLAGS_PER_BIT; i++) { - m_bitFlags[i] = false; - } + for (int i = 0; i < varp->width() * FLAGS_PER_BIT; i++) m_bitFlags[i] = false; } ~UndrivenVarEntry() {} @@ -81,60 +77,63 @@ private: bool prev = false; int msb = 0; // bit==-1 loops below; we do one extra iteration so end with prev=false - for (int bit=(m_bitFlags.size()/FLAGS_PER_BIT)-1; bit >= -1; --bit) { - if (bit>=0 + for (int bit = (m_bitFlags.size() / FLAGS_PER_BIT) - 1; bit >= -1; --bit) { + if (bit >= 0 && ((which == BN_UNUSED && !usedFlag(bit) && drivenFlag(bit)) || (which == BN_UNDRIVEN && usedFlag(bit) && !drivenFlag(bit)) || (which == BN_BOTH && !usedFlag(bit) && !drivenFlag(bit)))) { - if (!prev) { prev=true; msb = bit; } + if (!prev) { + prev = true; + msb = bit; + } } else if (prev) { AstBasicDType* bdtypep = m_varp->basicp(); - int lsb = bit+1; + int lsb = bit + 1; if (bits != "") bits += ","; - if (lsb==msb) { - bits += cvtToStr(lsb+bdtypep->lsb()); + if (lsb == msb) { + bits += cvtToStr(lsb + bdtypep->lsb()); } else { if (bdtypep->littleEndian()) { - bits += cvtToStr(lsb+bdtypep->lsb())+":"+cvtToStr(msb+bdtypep->lsb()); + bits += cvtToStr(lsb + bdtypep->lsb()) + ":" + + cvtToStr(msb + bdtypep->lsb()); } else { - bits += cvtToStr(msb+bdtypep->lsb())+":"+cvtToStr(lsb+bdtypep->lsb()); + bits += cvtToStr(msb + bdtypep->lsb()) + ":" + + cvtToStr(lsb + bdtypep->lsb()); } } prev = false; } } - return "["+bits+"]"; + return "[" + bits + "]"; } + public: void usedWhole() { - UINFO(9, "set u[*] "<name()<name() << endl); m_wholeFlags[FLAG_USED] = true; } void drivenWhole() { - UINFO(9, "set d[*] "<name()<name() << endl); m_wholeFlags[FLAG_DRIVEN] = true; } void usedBit(int bit, int width) { - UINFO(9, "set u["<<(bit+width-1)<<":"<name()<name() << endl); for (int i = 0; i < width; i++) { - if (bitNumOk(bit + i)) { - m_bitFlags[(bit + i) * FLAGS_PER_BIT + FLAG_USED] = true; - } + if (bitNumOk(bit + i)) m_bitFlags[(bit + i) * FLAGS_PER_BIT + FLAG_USED] = true; } } void drivenBit(int bit, int width) { - UINFO(9, "set d["<<(bit+width-1)<<":"<name()<name() << endl); for (int i = 0; i < width; i++) { - if (bitNumOk(bit + i)) { - m_bitFlags[(bit + i) * FLAGS_PER_BIT + FLAG_DRIVEN] = true; - } + if (bitNumOk(bit + i)) m_bitFlags[(bit + i) * FLAGS_PER_BIT + FLAG_DRIVEN] = true; } } bool isUsedNotDrivenBit(int bit, int width) const { for (int i = 0; i < width; i++) { if (bitNumOk(bit + i) && (m_wholeFlags[FLAG_USED] || m_bitFlags[(bit + i) * FLAGS_PER_BIT + FLAG_USED]) - && !(m_wholeFlags[FLAG_DRIVEN] || m_bitFlags[(bit + i) * FLAGS_PER_BIT + FLAG_DRIVEN])) + && !(m_wholeFlags[FLAG_DRIVEN] + || m_bitFlags[(bit + i) * FLAGS_PER_BIT + FLAG_DRIVEN])) return true; } return false; @@ -183,39 +182,43 @@ public: // UNDRIVEN is considered more serious - as is more likely a bug, // thus undriven+unused bits get UNUSED warnings, as they're not as buggy. if (!unusedMatch(nodep)) { - nodep->v3warn(UNUSED, "Signal is not driven, nor used: " - <prettyNameQ()); + nodep->v3warn(UNUSED, + "Signal is not driven, nor used: " << nodep->prettyNameQ()); nodep->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true); // Warn only once } } else if (allD && !anyU) { if (!unusedMatch(nodep)) { - nodep->v3warn(UNUSED, "Signal is not used: "<prettyNameQ()); + nodep->v3warn(UNUSED, "Signal is not used: " << nodep->prettyNameQ()); nodep->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true); // Warn only once } } else if (!anyD && allU) { - nodep->v3warn(UNDRIVEN, "Signal is not driven: "<prettyNameQ()); + nodep->v3warn(UNDRIVEN, "Signal is not driven: " << nodep->prettyNameQ()); nodep->fileline()->modifyWarnOff(V3ErrorCode::UNDRIVEN, true); // Warn only once } else { // Bits have different dispositions - bool setU=false; bool setD=false; + bool setU = false; + bool setD = false; if (anynotDU && !unusedMatch(nodep)) { nodep->v3warn(UNUSED, "Bits of signal are not driven, nor used: " - <prettyNameQ() - <prettyNameQ() << bitNames(BN_BOTH)); setU = true; } if (anyDnotU && !unusedMatch(nodep)) { - nodep->v3warn(UNUSED, "Bits of signal are not used: "<prettyNameQ() - <v3warn(UNUSED, "Bits of signal are not used: " << nodep->prettyNameQ() + << bitNames(BN_UNUSED)); setU = true; } if (anyUnotD) { - nodep->v3warn(UNDRIVEN, "Bits of signal are not driven: "<prettyNameQ() - <v3warn(UNDRIVEN, "Bits of signal are not driven: " + << nodep->prettyNameQ() << bitNames(BN_UNDRIVEN)); setD = true; } - if (setU) nodep->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true); // Warn only once - if (setD) nodep->fileline()->modifyWarnOff(V3ErrorCode::UNDRIVEN, true); // Warn only once + if (setU) { // Warn only once + nodep->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true); + } + if (setD) { // Warn only once + nodep->fileline()->modifyWarnOff(V3ErrorCode::UNDRIVEN, true); + } } } } @@ -246,17 +249,21 @@ private: VL_DEBUG_FUNC; // Declare debug() UndrivenVarEntry* getEntryp(AstVar* nodep, int which_user) { - if (!(which_user==1 ? nodep->user1p() : nodep->user2p())) { + if (!(which_user == 1 ? nodep->user1p() : nodep->user2p())) { UndrivenVarEntry* entryp = new UndrivenVarEntry(nodep); - //UINFO(9," Associate u="<name()<name()<user1p(entryp); - else if (which_user==2) nodep->user2p(entryp); - else nodep->v3fatalSrc("Bad case"); + if (which_user == 1) { + nodep->user1p(entryp); + } else if (which_user == 2) { + nodep->user2p(entryp); + } else { + nodep->v3fatalSrc("Bad case"); + } return entryp; } else { - UndrivenVarEntry* entryp = reinterpret_cast - (which_user==1 ? nodep->user1p() : nodep->user2p()); + UndrivenVarEntry* entryp = reinterpret_cast( + which_user == 1 ? nodep->user1p() : nodep->user2p()); return entryp; } } @@ -266,35 +273,33 @@ private: if (!varp->isParam() && !varp->isGenVar() && !varp->isUsedLoopIdx() && !m_inBBox // We may have falsely considered a SysIgnore as a driver && !VN_IS(nodep, VarXRef) // Xrefs might point at two different instances - && !varp->fileline()->warnIsOff(V3ErrorCode::ALWCOMBORDER)) { // Warn only once per variable - nodep->v3warn(ALWCOMBORDER, "Always_comb variable driven after use: " - <prettyNameQ()); - varp->fileline()->modifyWarnOff(V3ErrorCode::ALWCOMBORDER, true); // Complain just once for any usage + && !varp->fileline()->warnIsOff( + V3ErrorCode::ALWCOMBORDER)) { // Warn only once per variable + nodep->v3warn(ALWCOMBORDER, + "Always_comb variable driven after use: " << nodep->prettyNameQ()); + varp->fileline()->modifyWarnOff(V3ErrorCode::ALWCOMBORDER, + true); // Complain just once for any usage } } // VISITORS virtual void visit(AstVar* nodep) VL_OVERRIDE { - for (int usr=1; usr<(m_alwaysCombp?3:2); ++usr) { + for (int usr = 1; usr < (m_alwaysCombp ? 3 : 2); ++usr) { // For assigns and non-combo always, do just usr==1, to look // for module-wide undriven etc. // For non-combo always, run both usr==1 for above, and also // usr==2 for always-only checks. UndrivenVarEntry* entryp = getEntryp(nodep, usr); - if (nodep->isNonOutput() - || nodep->isSigPublic() || nodep->isSigUserRWPublic() + if (nodep->isNonOutput() || nodep->isSigPublic() || nodep->isSigUserRWPublic() || (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) { entryp->drivenWhole(); } - if (nodep->isWritable() - || nodep->isSigPublic() || nodep->isSigUserRWPublic() + if (nodep->isWritable() || nodep->isSigPublic() || nodep->isSigUserRWPublic() || nodep->isSigUserRdPublic() || (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) { entryp->usedWhole(); } - if (nodep->valuep()) { - entryp->drivenWhole(); - } + if (nodep->valuep()) entryp->drivenWhole(); } // Discover variables used in bit definitions, etc iterateChildren(nodep); @@ -311,14 +316,14 @@ private: AstNodeVarRef* varrefp = VN_CAST(nodep->fromp(), NodeVarRef); AstConst* constp = VN_CAST(nodep->lsbp(), Const); if (varrefp && constp && !constp->num().isFourState()) { - for (int usr=1; usr<(m_alwaysCombp?3:2); ++usr) { + for (int usr = 1; usr < (m_alwaysCombp ? 3 : 2); ++usr) { UndrivenVarEntry* entryp = getEntryp(varrefp->varp(), usr); int lsb = constp->toUInt(); if (m_inBBox || varrefp->lvalue()) { // Don't warn if already driven earlier as "a=0; if(a) a=1;" is fine. - if (usr==2 && m_alwaysCombp + if (usr == 2 && m_alwaysCombp && entryp->isUsedNotDrivenBit(lsb, nodep->width())) { - UINFO(9," Select. Entryp="<prettyNameQ()); + << " (IEEE 1800-2017 6.5): " + << nodep->prettyNameQ()); } if (m_inContAssign && !nodep->varp()->varType().isContAssignable() && !nodep->fileline()->language().systemVerilog()) { - nodep->v3warn(CONTASSREG, "Continuous assignment to reg, perhaps intended wire" - << " (IEEE 1364-2005 6.1; Verilog only, legal in SV): " - << nodep->prettyNameQ()); + nodep->v3warn(CONTASSREG, + "Continuous assignment to reg, perhaps intended wire" + << " (IEEE 1364-2005 6.1; Verilog only, legal in SV): " + << nodep->prettyNameQ()); } } - for (int usr=1; usr<(m_alwaysCombp?3:2); ++usr) { + for (int usr = 1; usr < (m_alwaysCombp ? 3 : 2); ++usr) { UndrivenVarEntry* entryp = getEntryp(nodep->varp(), usr); - bool fdrv = nodep->lvalue() && nodep->varp()->attrFileDescr(); // FD's are also being read from + bool fdrv = nodep->lvalue() + && nodep->varp()->attrFileDescr(); // FD's are also being read from if (m_inBBox || nodep->lvalue()) { - if (usr==2 && m_alwaysCombp && entryp->isUsedNotDrivenAny()) { - UINFO(9," Full bus. Entryp="<isUsedNotDrivenAny()) { + UINFO(9, " Full bus. Entryp=" << cvtToHex(entryp) << endl); warnAlwCombOrder(nodep); } entryp->drivenWhole(); @@ -398,11 +405,14 @@ private: AstAlways* prevAlwp = m_alwaysCombp; { AstNode::user2ClearTree(); - if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) UINFO(9," "<keyword() == VAlwaysKwd::ALWAYS_COMB) m_alwaysCombp = nodep; - else m_alwaysCombp = NULL; + if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) UINFO(9, " " << nodep << endl); + if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) { + m_alwaysCombp = nodep; + } else { + m_alwaysCombp = NULL; + } iterateChildren(nodep); - if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) UINFO(9," Done "<keyword() == VAlwaysKwd::ALWAYS_COMB) UINFO(9, " Done " << nodep << endl); } m_alwaysCombp = prevAlwp; } @@ -456,6 +466,6 @@ public: // Undriven class functions void V3Undriven::undrivenAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "< bool. Set true if already processed // AstArraySel::user() -> bool. Set true if already processed // AstNode::user2p() -> AstIf* Inserted if assignment for conditional - AstUser1InUse m_inuser1; - AstUser2InUse m_inuser2; + AstUser1InUse m_inuser1; + AstUser2InUse m_inuser2; // STATE - AstNodeModule* m_modp; // Current module - bool m_constXCvt; // Convert X's - VDouble0 m_statUnkVars; // Statistic tracking - AstAssignW* m_assignwp; // Current assignment - AstAssignDly* m_assigndlyp; // Current assignment + AstNodeModule* m_modp; // Current module + bool m_constXCvt; // Convert X's + VDouble0 m_statUnkVars; // Statistic tracking + AstAssignW* m_assignwp; // Current assignment + AstAssignDly* m_assigndlyp; // Current assignment // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -81,7 +81,7 @@ private: if (m_assignwp) { // Wire assigns must become always statements to deal with insertion // of multiple statements. Perhaps someday make all wassigns into always's? - UINFO(5," IM_WireRep "<convertToAlways(); VL_DO_CLEAR(pushDeletep(m_assignwp), m_assignwp = NULL); } @@ -98,8 +98,7 @@ private: AstNode* prep = nodep; // Scan back to put the condlvalue above all selects (IE top of the lvalue) - while (VN_IS(prep->backp(), NodeSel) - || VN_IS(prep->backp(), Sel)) { + while (VN_IS(prep->backp(), NodeSel) || VN_IS(prep->backp(), Sel)) { prep = prep->backp(); } FileLine* fl = nodep->fileline(); @@ -111,30 +110,24 @@ private: UASSERT_OBJ(!needDly, prep, "Should have already converted to non-delay"); AstNRelinker replaceHandle; AstNode* earliercondp = ifp->condp()->unlinkFrBack(&replaceHandle); - AstNode* newp = new AstLogAnd(condp->fileline(), - condp, earliercondp); - UINFO(4, "Edit BOUNDLVALUE "<fileline(), condp, earliercondp); + UINFO(4, "Edit BOUNDLVALUE " << newp << endl); replaceHandle.relink(newp); - } - else { - string name = (string("__Vlvbound")+cvtToStr(m_modp->varNumGetInc())); - AstVar* varp = new AstVar(fl, AstVarType::MODULETEMP, name, - prep->dtypep()); + } else { + string name = (string("__Vlvbound") + cvtToStr(m_modp->varNumGetInc())); + AstVar* varp = new AstVar(fl, AstVarType::MODULETEMP, name, prep->dtypep()); m_modp->addStmtp(varp); AstNode* abovep = prep->backp(); // Grab above point before lose it w/ next replace prep->replaceWith(new AstVarRef(fl, varp, true)); AstIf* newp = new AstIf(fl, condp, - (needDly - ? static_cast - (new AstAssignDly(fl, prep, - new AstVarRef(fl, varp, false))) - : static_cast - (new AstAssign(fl, prep, - new AstVarRef(fl, varp, false)))), + (needDly ? static_cast(new AstAssignDly( + fl, prep, new AstVarRef(fl, varp, false))) + : static_cast(new AstAssign( + fl, prep, new AstVarRef(fl, varp, false)))), NULL); newp->branchPred(VBranchPred::BP_LIKELY); - if (debug()>=9) newp->dumpTree(cout, " _new: "); + if (debug() >= 9) newp->dumpTree(cout, " _new: "); abovep->addNextStmt(newp, abovep); prep->user2p(newp); // Save so we may LogAnd it next time } @@ -142,7 +135,7 @@ private: // VISITORS virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { - UINFO(4," MOD "<EQ "<EQ " << nodep << endl); V3Const::constifyEdit(nodep->lhsp()); // lhsp may change V3Const::constifyEdit(nodep->rhsp()); // rhsp may change if (VN_IS(nodep->lhsp(), Const) && VN_IS(nodep->rhsp(), Const)) { @@ -187,14 +180,16 @@ private: // If we got ==1'bx it can never be true (but 1'bx==1'bx can be!) if (((VN_IS(lhsp, Const) && VN_CAST(lhsp, Const)->num().isFourState()) || (VN_IS(rhsp, Const) && VN_CAST(rhsp, Const)->num().isFourState()))) { - newp = new AstConst(nodep->fileline(), AstConst::WidthedValue(), - 1, (VN_IS(nodep, EqCase) ? 0 : 1)); + newp = new AstConst(nodep->fileline(), AstConst::WidthedValue(), 1, + (VN_IS(nodep, EqCase) ? 0 : 1)); VL_DO_DANGLING(lhsp->deleteTree(), lhsp); VL_DO_DANGLING(rhsp->deleteTree(), rhsp); } else { if (VN_IS(nodep, EqCase)) { newp = new AstEq(nodep->fileline(), lhsp, rhsp); - } else { newp = new AstNeq(nodep->fileline(), lhsp, rhsp); } + } else { + newp = new AstNeq(nodep->fileline(), lhsp, rhsp); + } } nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); @@ -203,7 +198,7 @@ private: } } void visitEqNeqWild(AstNodeBiop* nodep) { - UINFO(4," N/EQWILD->EQ "<EQ " << nodep << endl); V3Const::constifyEdit(nodep->lhsp()); // lhsp may change V3Const::constifyEdit(nodep->rhsp()); // rhsp may change if (VN_IS(nodep->lhsp(), Const) && VN_IS(nodep->rhsp(), Const)) { @@ -215,21 +210,24 @@ private: AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); AstNode* newp; if (!VN_IS(rhsp, Const)) { - nodep->v3error("Unsupported: RHS of ==? or !=? must be constant to be synthesizable"); // Says spec. + nodep->v3error("Unsupported: RHS of ==? or !=? must be " + "constant to be synthesizable"); // Says spec. // Replace with anything that won't cause more errors newp = new AstEq(nodep->fileline(), lhsp, rhsp); } else { // X or Z's become mask, ala case statements. - V3Number nummask (rhsp, rhsp->width()); + V3Number nummask(rhsp, rhsp->width()); nummask.opBitsNonX(VN_CAST(rhsp, Const)->num()); - V3Number numval (rhsp, rhsp->width()); + V3Number numval(rhsp, rhsp->width()); numval.opBitsOne(VN_CAST(rhsp, Const)->num()); AstNode* and1p = new AstAnd(nodep->fileline(), lhsp, new AstConst(nodep->fileline(), nummask)); AstNode* and2p = new AstConst(nodep->fileline(), numval); if (VN_IS(nodep, EqWild)) { - newp = new AstEq(nodep->fileline(), and1p, and2p); - } else { newp = new AstNeq(nodep->fileline(), and1p, and2p); } + newp = new AstEq(nodep->fileline(), and1p, and2p); + } else { + newp = new AstNeq(nodep->fileline(), and1p, and2p); + } VL_DO_DANGLING(rhsp->deleteTree(), rhsp); } nodep->replaceWith(newp); @@ -239,42 +237,33 @@ private: } } - virtual void visit(AstEqCase* nodep) VL_OVERRIDE { - visitEqNeqCase(nodep); - } - virtual void visit(AstNeqCase* nodep) VL_OVERRIDE { - visitEqNeqCase(nodep); - } - virtual void visit(AstEqWild* nodep) VL_OVERRIDE { - visitEqNeqWild(nodep); - } - virtual void visit(AstNeqWild* nodep) VL_OVERRIDE { - visitEqNeqWild(nodep); - } + virtual void visit(AstEqCase* nodep) VL_OVERRIDE { visitEqNeqCase(nodep); } + virtual void visit(AstNeqCase* nodep) VL_OVERRIDE { visitEqNeqCase(nodep); } + virtual void visit(AstEqWild* nodep) VL_OVERRIDE { visitEqNeqWild(nodep); } + virtual void visit(AstNeqWild* nodep) VL_OVERRIDE { visitEqNeqWild(nodep); } virtual void visit(AstIsUnknown* nodep) VL_OVERRIDE { iterateChildren(nodep); // Ahh, we're two state, so this is easy - UINFO(4," ISUNKNOWN->0 "<0 " << nodep << endl); AstConst* newp = new AstConst(nodep->fileline(), AstConst::LogicFalse()); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } virtual void visit(AstConst* nodep) VL_OVERRIDE { - if (m_constXCvt - && nodep->num().isFourState()) { - UINFO(4," CONST4 "<=9) nodep->dumpTree(cout, " Const_old: "); + if (m_constXCvt && nodep->num().isFourState()) { + UINFO(4, " CONST4 " << nodep << endl); + if (debug() >= 9) nodep->dumpTree(cout, " Const_old: "); // CONST(num) -> VARREF(newvarp) // -> VAR(newvarp) // -> INITIAL(VARREF(newvarp, OR(num_No_Xs,AND(random,num_1s_Where_X)) - V3Number numb1 (nodep, nodep->width()); + V3Number numb1(nodep, nodep->width()); numb1.opBitsOne(nodep->num()); - V3Number numbx (nodep, nodep->width()); + V3Number numbx(nodep, nodep->width()); numbx.opBitsXZ(nodep->num()); - if (v3Global.opt.xAssign()!="unique") { + if (v3Global.opt.xAssign() != "unique") { // All X bits just become 0; fastest simulation, but not nice - V3Number numnew (nodep, numb1.width()); - if (v3Global.opt.xAssign()=="1") { + V3Number numnew(nodep, numb1.width()); + if (v3Global.opt.xAssign() == "1") { numnew.opOr(numb1, numbx); } else { numnew.opAssign(numb1); @@ -282,42 +271,36 @@ private: AstConst* newp = new AstConst(nodep->fileline(), numnew); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); - UINFO(4," -> "< " << newp << endl); } else { // Make a Vxrand variable // We use the special XTEMP type so it doesn't break pure functions UASSERT_OBJ(m_modp, nodep, "X number not under module"); - string newvarname = (string("__Vxrand") - +cvtToStr(m_modp->varNumGetInc())); - AstVar* newvarp - = new AstVar(nodep->fileline(), AstVarType::XTEMP, newvarname, - VFlagLogicPacked(), nodep->width()); + string newvarname = (string("__Vxrand") + cvtToStr(m_modp->varNumGetInc())); + AstVar* newvarp = new AstVar(nodep->fileline(), AstVarType::XTEMP, newvarname, + VFlagLogicPacked(), nodep->width()); ++m_statUnkVars; AstNRelinker replaceHandle; nodep->unlinkFrBack(&replaceHandle); AstNodeVarRef* newref1p = new AstVarRef(nodep->fileline(), newvarp, false); replaceHandle.relink(newref1p); // Replace const with varref - AstInitial* newinitp - = new AstInitial( - nodep->fileline(), - new AstAssign( - nodep->fileline(), - new AstVarRef(nodep->fileline(), newvarp, true), - new AstOr(nodep->fileline(), - new AstConst(nodep->fileline(), numb1), - new AstAnd(nodep->fileline(), - new AstConst(nodep->fileline(), numbx), - new AstRand(nodep->fileline(), - nodep->dtypep(), true))))); + AstInitial* newinitp = new AstInitial( + nodep->fileline(), + new AstAssign( + nodep->fileline(), new AstVarRef(nodep->fileline(), newvarp, true), + new AstOr( + nodep->fileline(), new AstConst(nodep->fileline(), numb1), + new AstAnd(nodep->fileline(), new AstConst(nodep->fileline(), numbx), + new AstRand(nodep->fileline(), nodep->dtypep(), true))))); // Add inits in front of other statement. // In the future, we should stuff the initp into the module's constructor. AstNode* afterp = m_modp->stmtsp()->unlinkFrBackWithNext(); m_modp->addStmtp(newvarp); m_modp->addStmtp(newinitp); m_modp->addStmtp(afterp); - if (debug()>=9) newref1p->dumpTree(cout, " _new: "); - if (debug()>=9) newvarp->dumpTree(cout, " _new: "); - if (debug()>=9) newinitp->dumpTree(cout, " _new: "); + if (debug() >= 9) newref1p->dumpTree(cout, " _new: "); + if (debug() >= 9) newvarp->dumpTree(cout, " _new: "); + if (debug() >= 9) newinitp->dumpTree(cout, " _new: "); VL_DO_DANGLING(nodep->deleteTree(), nodep); } } @@ -334,13 +317,12 @@ private: } // Find range of dtype we are selecting from // Similar code in V3Const::warnSelect - int maxmsb = nodep->fromp()->dtypep()->width()-1; - if (debug()>=9) nodep->dumpTree(cout, "sel_old: "); + int maxmsb = nodep->fromp()->dtypep()->width() - 1; + if (debug() >= 9) nodep->dumpTree(cout, "sel_old: "); // If (maxmsb >= selected), we're in bound AstNode* condp = new AstGte(nodep->fileline(), - new AstConst(nodep->fileline(), - AstConst::WidthedValue(), + new AstConst(nodep->fileline(), AstConst::WidthedValue(), nodep->lsbp()->width(), maxmsb), nodep->lsbp()->cloneTree(false)); // See if the condition is constant true (e.g. always in bound due to constant select) @@ -349,24 +331,20 @@ private: if (condp->isOne()) { // We don't need to add a conditional; we know the existing expression is ok VL_DO_DANGLING(condp->deleteTree(), condp); - } - else if (!lvalue) { + } else if (!lvalue) { // SEL(...) -> COND(LTE(bit<=maxmsb), ARRAYSEL(...), {width{1'bx}}) AstNRelinker replaceHandle; nodep->unlinkFrBack(&replaceHandle); - V3Number xnum (nodep, nodep->width()); + V3Number xnum(nodep, nodep->width()); xnum.setAllBitsX(); - AstNode* newp = new AstCondBound(nodep->fileline(), - condp, - nodep, + AstNode* newp = new AstCondBound(nodep->fileline(), condp, nodep, new AstConst(nodep->fileline(), xnum)); - if (debug()>=9) newp->dumpTree(cout, " _new: "); + if (debug() >= 9) newp->dumpTree(cout, " _new: "); // Link in conditional replaceHandle.relink(newp); // Added X's, tristate them too iterate(newp); - } - else { // lvalue + } else { // lvalue replaceBoundLvalue(nodep, condp); } } @@ -378,7 +356,7 @@ private: virtual void visit(AstArraySel* nodep) VL_OVERRIDE { iterateChildren(nodep); if (!nodep->user1SetOnce()) { - if (debug()==9) nodep->dumpTree(cout, "-in: "); + if (debug() == 9) nodep->dumpTree(cout, "-in: "); // Guard against reading/writing past end of arrays AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp()); bool lvalue = false; @@ -396,57 +374,51 @@ private: if (const AstNodeArrayDType* adtypep = VN_CAST(dtypep, NodeArrayDType)) { declElements = adtypep->elementsConst(); } else { - nodep->v3error("Select from non-array "<prettyTypeName()); + nodep->v3error("Select from non-array " << dtypep->prettyTypeName()); } - if (debug()>=9) nodep->dumpTree(cout, "arraysel_old: "); + if (debug() >= 9) nodep->dumpTree(cout, "arraysel_old: "); // See if the condition is constant true AstNode* condp = new AstGte(nodep->fileline(), new AstConst(nodep->fileline(), AstConst::WidthedValue(), - nodep->bitp()->width(), declElements-1), + nodep->bitp()->width(), declElements - 1), nodep->bitp()->cloneTree(false)); // Note below has null backp(); the Edit function knows how to deal with that. condp = V3Const::constifyEdit(condp); if (condp->isOne()) { // We don't need to add a conditional; we know the existing expression is ok VL_DO_DANGLING(condp->deleteTree(), condp); - } - else if (!lvalue - // Making a scalar would break if we're making an array - && !VN_IS(nodep->dtypep()->skipRefp(), NodeArrayDType)) { + } else if (!lvalue + // Making a scalar would break if we're making an array + && !VN_IS(nodep->dtypep()->skipRefp(), NodeArrayDType)) { // ARRAYSEL(...) -> COND(LT(bitunlinkFrBack(&replaceHandle); - V3Number xnum (nodep, nodep->width()); + V3Number xnum(nodep, nodep->width()); if (nodep->isString()) { xnum = V3Number(V3Number::String(), nodep, ""); } else { xnum.setAllBitsX(); } - AstNode* newp = new AstCondBound(nodep->fileline(), - condp, nodep, + AstNode* newp = new AstCondBound(nodep->fileline(), condp, nodep, new AstConst(nodep->fileline(), xnum)); - if (debug()>=9) newp->dumpTree(cout, " _new: "); + if (debug() >= 9) newp->dumpTree(cout, " _new: "); // Link in conditional, can blow away temp xor replaceHandle.relink(newp); // Added X's, tristate them too iterate(newp); - } - else if (!lvalue) { // Mid-multidimension read, just use zero + } else if (!lvalue) { // Mid-multidimension read, just use zero // ARRAYSEL(...) -> ARRAYSEL(COND(LT(bitbitp()->unlinkFrBack(&replaceHandle); - AstNode* newp = new AstCondBound(bitp->fileline(), - condp, bitp, - new AstConst(bitp->fileline(), - AstConst::WidthedValue(), - bitp->width(), 0)); + AstNode* newp = new AstCondBound( + bitp->fileline(), condp, bitp, + new AstConst(bitp->fileline(), AstConst::WidthedValue(), bitp->width(), 0)); // Added X's, tristate them too - if (debug()>=9) newp->dumpTree(cout, " _new: "); + if (debug() >= 9) newp->dumpTree(cout, " _new: "); replaceHandle.relink(newp); iterate(newp); - } - else { // lvalue + } else { // lvalue replaceBoundLvalue(nodep, condp); } } @@ -463,7 +435,7 @@ public: m_constXCvt = false; iterate(nodep); } - virtual ~UnknownVisitor() { + virtual ~UnknownVisitor() { // V3Stats::addStat("Unknowns, variables created", m_statUnkVars); } }; @@ -472,9 +444,7 @@ public: // Unknown class functions void V3Unknown::unknownAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 3); } diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index d09c42540..3a0191190 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -43,35 +43,32 @@ class UnrollVisitor : public AstNVisitor { private: // STATE - AstVar* m_forVarp; // Iterator variable - AstVarScope* m_forVscp; // Iterator variable scope (NULL for generate pass) - AstConst* m_varValuep; // Current value of loop - AstNode* m_ignoreIncp; // Increment node to ignore - bool m_varModeCheck; // Just checking RHS assignments - bool m_varModeReplace; // Replacing varrefs - bool m_varAssignHit; // Assign var hit - bool m_generate; // Expand single generate For loop - string m_beginName; // What name to give begin iterations - VDouble0 m_statLoops; // Statistic tracking - VDouble0 m_statIters; // Statistic tracking + AstVar* m_forVarp; // Iterator variable + AstVarScope* m_forVscp; // Iterator variable scope (NULL for generate pass) + AstConst* m_varValuep; // Current value of loop + AstNode* m_ignoreIncp; // Increment node to ignore + bool m_varModeCheck; // Just checking RHS assignments + bool m_varModeReplace; // Replacing varrefs + bool m_varAssignHit; // Assign var hit + bool m_generate; // Expand single generate For loop + string m_beginName; // What name to give begin iterations + VDouble0 m_statLoops; // Statistic tracking + VDouble0 m_statIters; // Statistic tracking // METHODS VL_DEBUG_FUNC; // Declare debug() // VISITORS bool cantUnroll(AstNode* nodep, const char* reason) { - if (m_generate) { - nodep->v3error("Unsupported: Can't unroll generate for; "<=9) nodep->dumpTree(cout, "-cant-"); - V3Stats::addStatSum(string("Unrolling gave up, ")+reason, 1); + if (m_generate) nodep->v3error("Unsupported: Can't unroll generate for; " << reason); + UINFO(3, " Can't Unroll: " << reason << " :" << nodep << endl); + // if (debug() >= 9) nodep->dumpTree(cout, "-cant-"); + V3Stats::addStatSum(string("Unrolling gave up, ") + reason, 1); return false; } int unrollCount() { - return m_generate ? v3Global.opt.unrollCount()*16 - : v3Global.opt.unrollCount(); + return m_generate ? v3Global.opt.unrollCount() * 16 : v3Global.opt.unrollCount(); } bool bodySizeOverRecurse(AstNode* nodep, int& bodySize, int bodyLimit) { @@ -88,24 +85,27 @@ private: return bodySizeOverRecurse(nodep->nextp(), bodySize, bodyLimit); } - bool forUnrollCheck(AstNode* nodep, - AstNode* initp, // Maybe under nodep (no nextp), or standalone (ignore nextp) - AstNode* precondsp, AstNode* condp, - AstNode* incp, // Maybe under nodep or in bodysp - AstNode* bodysp) { + bool + forUnrollCheck(AstNode* nodep, + AstNode* initp, // Maybe under nodep (no nextp), or standalone (ignore nextp) + AstNode* precondsp, AstNode* condp, + AstNode* incp, // Maybe under nodep or in bodysp + AstNode* bodysp) { // To keep the IF levels low, we return as each test fails. - UINFO(4, " FOR Check "<nextp() && initp->nextp()!=nodep), nodep, + UASSERT_OBJ(!(initp->nextp() && initp->nextp() != nodep), nodep, "initial assignment shouldn't be a list"); - if (!VN_IS(initAssp->lhsp(), VarRef)) return cantUnroll(nodep, "no initial assignment to simple variable"); + if (!VN_IS(initAssp->lhsp(), VarRef)) { + return cantUnroll(nodep, "no initial assignment to simple variable"); + } // // Condition check UASSERT_OBJ(!condp->nextp(), nodep, "conditional shouldn't be a list"); @@ -118,9 +118,9 @@ private: m_forVarp = VN_CAST(initAssp->lhsp(), VarRef)->varp(); m_forVscp = VN_CAST(initAssp->lhsp(), VarRef)->varScopep(); if (VN_IS(nodep, GenFor) && !m_forVarp->isGenVar()) { - nodep->v3error("Non-genvar used in generate for: "<prettyNameQ()<isGenVar()) { + nodep->v3error("Non-genvar used in generate for: " // + << m_forVarp->prettyNameQ() << endl); + } else if (!VN_IS(nodep, GenFor) && m_forVarp->isGenVar()) { nodep->v3error("Genvar not legal in non-generate for (IEEE 1800-2017 27.4): " << m_forVarp->prettyNameQ() << endl << nodep->warnMore() @@ -148,28 +148,33 @@ private: if (m_varAssignHit) return cantUnroll(nodep, "genvar assigned *inside* loop"); // - if (m_forVscp) { UINFO(8, " Loop Variable: "<=9) nodep->dumpTree(cout, "- for: "); - + if (m_forVscp) { + UINFO(8, " Loop Variable: " << m_forVscp << endl); + } else { + UINFO(8, " Loop Variable: " << m_forVarp << endl); + } + if (debug() >= 9) nodep->dumpTree(cout, "- for: "); if (!m_generate) { - AstAssign *incpAssign = VN_CAST(incp, Assign); - if (!canSimulate(incpAssign->rhsp())) return cantUnroll(incp, "Unable to simulate increment"); + AstAssign* incpAssign = VN_CAST(incp, Assign); + if (!canSimulate(incpAssign->rhsp())) { + return cantUnroll(incp, "Unable to simulate increment"); + } if (!canSimulate(condp)) return cantUnroll(condp, "Unable to simulate condition"); // Check whether to we actually want to try and unroll. int loops; - if (!countLoops(initAssp, condp, incp, unrollCount(), loops)) + if (!countLoops(initAssp, condp, incp, unrollCount(), loops)) { return cantUnroll(nodep, "Unable to simulate loop"); + } // Less than 10 statements in the body? int bodySize = 0; int bodyLimit = v3Global.opt.unrollStmts(); - if (loops>0) bodyLimit = v3Global.opt.unrollStmts() / loops; - if (bodySizeOverRecurse(precondsp, bodySize/*ref*/, bodyLimit) - || bodySizeOverRecurse(bodysp, bodySize/*ref*/, bodyLimit) - || bodySizeOverRecurse(incp, bodySize/*ref*/, bodyLimit)) { + if (loops > 0) bodyLimit = v3Global.opt.unrollStmts() / loops; + if (bodySizeOverRecurse(precondsp, bodySize /*ref*/, bodyLimit) + || bodySizeOverRecurse(bodysp, bodySize /*ref*/, bodyLimit) + || bodySizeOverRecurse(incp, bodySize /*ref*/, bodyLimit)) { return cantUnroll(nodep, "too many statements"); } } @@ -182,7 +187,7 @@ private: return true; } - bool canSimulate(AstNode *nodep) { + bool canSimulate(AstNode* nodep) { SimulateVisitor simvis; AstNode* clonep = nodep->cloneTree(true); simvis.mainCheckTree(clonep); @@ -190,8 +195,8 @@ private: return simvis.optimizable(); } - bool simulateTree(AstNode *nodep, const V3Number *loopValue, - AstNode *dtypep, V3Number &outNum) { + bool simulateTree(AstNode* nodep, const V3Number* loopValue, AstNode* dtypep, + V3Number& outNum) { AstNode* clonep = nodep->cloneTree(true); UASSERT_OBJ(clonep, nodep, "Failed to clone tree"); if (loopValue) { @@ -210,7 +215,7 @@ private: simvis.mainParamEmulate(clonep); if (!simvis.optimizable()) { UINFO(3, "Unable to simulate" << endl); - if (debug()>=9) nodep->dumpTree(cout, "- _simtree: "); + if (debug() >= 9) nodep->dumpTree(cout, "- _simtree: "); VL_DO_DANGLING(clonep->deleteTree(), clonep); return false; } @@ -223,7 +228,7 @@ private: } // Patch up datatype if (dtypep) { - AstConst new_con (clonep->fileline(), *res); + AstConst new_con(clonep->fileline(), *res); new_con.dtypeFrom(dtypep); outNum = new_con.num(); VL_DO_DANGLING(clonep->deleteTree(), clonep); @@ -234,20 +239,18 @@ private: return true; } - bool countLoops(AstAssign *initp, AstNode *condp, AstNode *incp, int max, int &outLoopsr) { + bool countLoops(AstAssign* initp, AstNode* condp, AstNode* incp, int max, int& outLoopsr) { outLoopsr = 0; V3Number loopValue = V3Number(initp); - if (!simulateTree(initp->rhsp(), NULL, initp, loopValue)) { + if (!simulateTree(initp->rhsp(), NULL, initp, loopValue)) { // return false; } while (true) { V3Number res = V3Number(initp); - if (!simulateTree(condp, &loopValue, NULL, res)) { + if (!simulateTree(condp, &loopValue, NULL, res)) { // return false; } - if (!res.isEqOne()) { - break; - } + if (!res.isEqOne()) break; outLoopsr++; @@ -258,21 +261,16 @@ private: return false; } loopValue.opAssign(newLoopValue); - if (outLoopsr > max) { - return false; - } + if (outLoopsr > max) return false; } return true; } - bool forUnroller(AstNode* nodep, - AstAssign* initp, - AstNode* condp, - AstNode* precondsp, + bool forUnroller(AstNode* nodep, AstAssign* initp, AstNode* condp, AstNode* precondsp, AstNode* incp, AstNode* bodysp) { - UINFO(9, "forUnroller "<rhsp(), NULL, initp, loopValue)) { + if (!simulateTree(initp->rhsp(), NULL, initp, loopValue)) { // return false; } AstNode* stmtsp = NULL; @@ -301,7 +299,7 @@ private: if (stmtsp) { int times = 0; while (true) { - UINFO(8," Looping "<v3error("Loop unrolling failed."); @@ -309,8 +307,7 @@ private: } if (!res.isEqOne()) { break; // Done with the loop - } - else { + } else { // Replace iterator values with constant. AstNode* oneloopp = stmtsp->cloneTree(true); @@ -318,8 +315,8 @@ private: // Iteration requires a back, so put under temporary node if (oneloopp) { - AstBegin* tempp = new AstBegin(oneloopp->fileline(), - "[EditWrapper]", oneloopp); + AstBegin* tempp + = new AstBegin(oneloopp->fileline(), "[EditWrapper]", oneloopp); m_varModeReplace = true; iterateAndNextNull(tempp->stmtsp()); m_varModeReplace = false; @@ -332,19 +329,23 @@ private: oneloopp = new AstBegin(oneloopp->fileline(), nname, oneloopp, true); } VL_DO_CLEAR(pushDeletep(m_varValuep), m_varValuep = NULL); - if (newbodysp) newbodysp->addNext(oneloopp); - else newbodysp = oneloopp; + if (newbodysp) { + newbodysp->addNext(oneloopp); + } else { + newbodysp = oneloopp; + } ++m_statIters; - if (++times > unrollCount()*3) { - nodep->v3error("Loop unrolling took too long;" - " probably this is an infinite loop, or set --unroll-count above " - < unrollCount() * 3) { + nodep->v3error( + "Loop unrolling took too long;" + " probably this is an infinite loop, or set --unroll-count above " + << unrollCount()); break; } // loopValue += valInc - AstAssign *incpass = VN_CAST(incp, Assign); + AstAssign* incpass = VN_CAST(incp, Assign); V3Number newLoopValue = V3Number(nodep); if (!simulateTree(incpass->rhsp(), &loopValue, incpass, newLoopValue)) { nodep->v3error("Loop unrolling failed"); @@ -359,13 +360,16 @@ private: initp = NULL; } // Replace the FOR() - if (newbodysp) nodep->replaceWith(newbodysp); - else nodep->unlinkFrBack(); + if (newbodysp) { + nodep->replaceWith(newbodysp); + } else { + nodep->unlinkFrBack(); + } if (bodysp) { VL_DO_DANGLING(pushDeletep(bodysp), bodysp); } if (precondsp) { VL_DO_DANGLING(pushDeletep(precondsp), precondsp); } if (initp) { VL_DO_DANGLING(pushDeletep(initp), initp); } if (incp && !incp->backp()) { VL_DO_DANGLING(pushDeletep(incp), incp); } - if (debug()>=9 && newbodysp) newbodysp->dumpTree(cout, "- _new: "); + if (debug() >= 9 && newbodysp) newbodysp->dumpTree(cout, "- _new: "); return true; } @@ -374,7 +378,9 @@ private: if (m_varModeCheck || m_varModeReplace) { } else { // Constify before unroll call, as it may change what is underneath. - if (nodep->precondsp()) V3Const::constifyEdit(nodep->precondsp()); // precondsp may change + if (nodep->precondsp()) { + V3Const::constifyEdit(nodep->precondsp()); // precondsp may change + } if (nodep->condp()) V3Const::constifyEdit(nodep->condp()); // condp may change // Grab initial value AstNode* initp = NULL; // Should be statement before the while. @@ -385,16 +391,17 @@ private: AstNode* incp = NULL; // Should be last statement if (nodep->incsp()) V3Const::constifyEdit(nodep->incsp()); // cppcheck-suppress duplicateCondition - if (nodep->incsp()) incp = nodep->incsp(); - else { + if (nodep->incsp()) { + incp = nodep->incsp(); + } else { + for (incp = nodep->bodysp(); incp && incp->nextp(); incp = incp->nextp()) {} + if (incp) VL_DO_DANGLING(V3Const::constifyEdit(incp), incp); + // Again, as may have changed for (incp = nodep->bodysp(); incp && incp->nextp(); incp = incp->nextp()) {} - if (incp) { VL_DO_DANGLING(V3Const::constifyEdit(incp), incp); } - for (incp = nodep->bodysp(); incp && incp->nextp(); incp = incp->nextp()) {} // Again, as may have changed } // And check it - if (forUnrollCheck(nodep, initp, - nodep->precondsp(), nodep->condp(), - incp, nodep->bodysp())) { + if (forUnrollCheck(nodep, initp, nodep->precondsp(), nodep->condp(), incp, + nodep->bodysp())) { VL_DO_DANGLING(pushDeletep(nodep), nodep); // Did replacement } } @@ -418,9 +425,8 @@ private: // condition, but they'll become while's which can be // deleted by V3Const. VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); - } else if (forUnrollCheck(nodep, nodep->initsp(), - NULL, nodep->condp(), - nodep->incsp(), nodep->bodysp())) { + } else if (forUnrollCheck(nodep, nodep->initsp(), NULL, nodep->condp(), nodep->incsp(), + nodep->bodysp())) { VL_DO_DANGLING(pushDeletep(nodep), nodep); // Did replacement } else { nodep->v3error("For loop doesn't have genvar index, or is malformed"); @@ -436,17 +442,13 @@ private: } virtual void visit(AstVarRef* nodep) VL_OVERRIDE { - if (m_varModeCheck - && nodep->varp() == m_forVarp - && nodep->varScopep() == m_forVscp + if (m_varModeCheck && nodep->varp() == m_forVarp && nodep->varScopep() == m_forVscp && nodep->lvalue()) { - UINFO(8," Itervar assigned to: "<varp() == m_forVarp - && nodep->varScopep() == m_forVscp + if (m_varModeReplace && nodep->varp() == m_forVarp && nodep->varScopep() == m_forVscp && !nodep->lvalue()) { AstNode* newconstp = m_varValuep->cloneTree(false); nodep->replaceWith(newconstp); @@ -492,20 +494,19 @@ public: //###################################################################### // Unroll class functions -UnrollStateful::UnrollStateful() : m_unrollerp(new UnrollVisitor) { } +UnrollStateful::UnrollStateful() + : m_unrollerp(new UnrollVisitor) {} UnrollStateful::~UnrollStateful() { delete m_unrollerp; } void UnrollStateful::unrollGen(AstNodeFor* nodep, const string& beginName) { - UINFO(5,__FUNCTION__<<": "<process(nodep, true, beginName); } -void UnrollStateful::unrollAll(AstNetlist* nodep) { - m_unrollerp->process(nodep, false, ""); -} +void UnrollStateful::unrollAll(AstNetlist* nodep) { m_unrollerp->process(nodep, false, ""); } void V3Unroll::unrollAll(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<=prelim, <1>=final std::ostream& operator<<(std::ostream& str, const Stage& rhs) { - return str<<("-PFB"[static_cast(rhs)]); + return str << ("-PFB"[static_cast(rhs)]); } enum Determ { - SELF, // Self-determined - CONTEXT, // Context-determined - ASSIGN // Assignment-like where sign comes from RHS only + SELF, // Self-determined + CONTEXT, // Context-determined + ASSIGN // Assignment-like where sign comes from RHS only }; std::ostream& operator<<(std::ostream& str, const Determ& rhs) { static const char* const s_det[] = {"SELF", "CNTX", "ASSN"}; - return str<op4p()) clearWidthRecurse(nodep->op4p()); } } + public: // CONSTRUCTORS - explicit WidthClearVisitor(AstNetlist* nodep) { - clearWidthRecurse(nodep); - } + explicit WidthClearVisitor(AstNetlist* nodep) { clearWidthRecurse(nodep); } virtual ~WidthClearVisitor() {} }; @@ -179,27 +181,27 @@ public: class WidthVisitor : public AstNVisitor { private: // TYPES - typedef std::map, AstVar*> TableMap; - typedef std::map PatVecMap; + typedef std::map, AstVar*> TableMap; + typedef std::map PatVecMap; // STATE - WidthVP* m_vup; // Current node state - bool m_paramsOnly; // Computing parameter value; limit operation - AstRange* m_cellRangep; // Range for arrayed instantiations, NULL for normal instantiations - AstNodeFTask* m_ftaskp; // Current function/task - AstFunc* m_funcp; // Current function - AstInitial* m_initialp; // Current initial block - AstAttrOf* m_attrp; // Current attribute - bool m_doGenerate; // Do errors later inside generate statement - int m_dtTables; // Number of created data type tables - TableMap m_tableMap; // Created tables so can remove duplicates + WidthVP* m_vup; // Current node state + bool m_paramsOnly; // Computing parameter value; limit operation + AstRange* m_cellRangep; // Range for arrayed instantiations, NULL for normal instantiations + AstNodeFTask* m_ftaskp; // Current function/task + AstFunc* m_funcp; // Current function + AstInitial* m_initialp; // Current initial block + AstAttrOf* m_attrp; // Current attribute + bool m_doGenerate; // Do errors later inside generate statement + int m_dtTables; // Number of created data type tables + TableMap m_tableMap; // Created tables so can remove duplicates // ENUMS enum ExtendRule { - EXTEND_EXP, // Extend if expect sign and node signed, e.g. node=y in ADD(x,y), "x + y" - EXTEND_ZERO, // Extend with zeros. e.g. node=y in EQ(x,y), "x == y" - EXTEND_LHS, // Extend with sign if node signed. e.g. node=y in ASSIGN(y,x), "x = y" - EXTEND_OFF // No extension + EXTEND_EXP, // Extend if expect sign and node signed, e.g. node=y in ADD(x,y), "x + y" + EXTEND_ZERO, // Extend with zeros. e.g. node=y in EQ(x,y), "x == y" + EXTEND_LHS, // Extend with sign if node signed. e.g. node=y in ASSIGN(y,x), "x = y" + EXTEND_OFF // No extension }; // METHODS @@ -216,110 +218,122 @@ private: // _Ox=anything // Widths: 1 bit out, lhs 1 bit; Real: converts via compare with 0 - virtual void visit(AstLogNot* nodep) VL_OVERRIDE { visit_log_not(nodep); } + virtual void visit(AstLogNot* nodep) VL_OVERRIDE { visit_log_not(nodep); } // Widths: 1 bit out, lhs 1 bit, rhs 1 bit; Real: converts via compare with 0 - virtual void visit(AstLogAnd* nodep) VL_OVERRIDE { visit_log_and_or(nodep); } - virtual void visit(AstLogOr* nodep) VL_OVERRIDE { visit_log_and_or(nodep); } - virtual void visit(AstLogEq* nodep) VL_OVERRIDE { visit_log_and_or(nodep); } // Conversion from real not in IEEE, but a fallout - virtual void visit(AstLogIf* nodep) VL_OVERRIDE { visit_log_and_or(nodep); } // Conversion from real not in IEEE, but a fallout + virtual void visit(AstLogAnd* nodep) VL_OVERRIDE { visit_log_and_or(nodep); } + virtual void visit(AstLogOr* nodep) VL_OVERRIDE { visit_log_and_or(nodep); } + virtual void visit(AstLogEq* nodep) VL_OVERRIDE { + // Conversion from real not in IEEE, but a fallout + visit_log_and_or(nodep); + } + virtual void visit(AstLogIf* nodep) VL_OVERRIDE { + // Conversion from real not in IEEE, but a fallout + visit_log_and_or(nodep); + } // Widths: 1 bit out, Any width lhs - virtual void visit(AstRedAnd* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } - virtual void visit(AstRedOr* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } - virtual void visit(AstRedXnor* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } - virtual void visit(AstRedXor* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } - virtual void visit(AstOneHot* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } - virtual void visit(AstOneHot0* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } - virtual void visit(AstIsUnknown* nodep) VL_OVERRIDE { visit_red_unknown(nodep); } // Allow real + virtual void visit(AstRedAnd* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } + virtual void visit(AstRedOr* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } + virtual void visit(AstRedXnor* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } + virtual void visit(AstRedXor* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } + virtual void visit(AstOneHot* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } + virtual void visit(AstOneHot0* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } + virtual void visit(AstIsUnknown* nodep) VL_OVERRIDE { + visit_red_unknown(nodep); // Allow real + } // These have different node types, as they operate differently // Must add to case statement below, // Widths: 1 bit out, lhs width == rhs width. real if lhs|rhs real - virtual void visit(AstEq* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstNeq* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstGt* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstGte* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstLt* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstLte* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstGtS* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstGteS* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstLtS* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstLteS* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstEqCase* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstNeqCase* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstEq* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstNeq* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstGt* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstGte* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstLt* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstLte* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstGtS* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstGteS* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstLtS* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstLteS* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstEqCase* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstNeqCase* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } // ... These comparisons don't allow reals - virtual void visit(AstEqWild* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, false); } - virtual void visit(AstNeqWild* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, false); } + virtual void visit(AstEqWild* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, false); } + virtual void visit(AstNeqWild* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, false); } // ... Real compares - virtual void visit(AstEqD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } - virtual void visit(AstNeqD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } - virtual void visit(AstLtD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } - virtual void visit(AstLteD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } - virtual void visit(AstGtD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } - virtual void visit(AstGteD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } + virtual void visit(AstEqD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } + virtual void visit(AstNeqD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } + virtual void visit(AstLtD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } + virtual void visit(AstLteD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } + virtual void visit(AstGtD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } + virtual void visit(AstGteD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } // ... String compares - virtual void visit(AstEqN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } - virtual void visit(AstNeqN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } - virtual void visit(AstLtN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } - virtual void visit(AstLteN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } - virtual void visit(AstGtN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } - virtual void visit(AstGteN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } + virtual void visit(AstEqN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } + virtual void visit(AstNeqN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } + virtual void visit(AstLtN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } + virtual void visit(AstLteN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } + virtual void visit(AstGtN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } + virtual void visit(AstGteN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } // Widths: out width = lhs width = rhs width // Signed: Output signed iff LHS & RHS signed. // Real: Not allowed - virtual void visit(AstAnd* nodep) VL_OVERRIDE { visit_boolmath_and_or(nodep); } - virtual void visit(AstOr* nodep) VL_OVERRIDE { visit_boolmath_and_or(nodep); } - virtual void visit(AstXnor* nodep) VL_OVERRIDE { visit_boolmath_and_or(nodep); } - virtual void visit(AstXor* nodep) VL_OVERRIDE { visit_boolmath_and_or(nodep); } - virtual void visit(AstBufIf1* nodep) VL_OVERRIDE { visit_boolmath_and_or(nodep); } // Signed behavior changing in 3.814 + virtual void visit(AstAnd* nodep) VL_OVERRIDE { visit_boolmath_and_or(nodep); } + virtual void visit(AstOr* nodep) VL_OVERRIDE { visit_boolmath_and_or(nodep); } + virtual void visit(AstXnor* nodep) VL_OVERRIDE { visit_boolmath_and_or(nodep); } + virtual void visit(AstXor* nodep) VL_OVERRIDE { visit_boolmath_and_or(nodep); } + virtual void visit(AstBufIf1* nodep) VL_OVERRIDE { + visit_boolmath_and_or(nodep); + } // Signed behavior changing in 3.814 // Width: Max(Lhs,Rhs) sort of. // Real: If either side real // Signed: If both sides real - virtual void visit(AstAdd* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, true); } - virtual void visit(AstSub* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, true); } - virtual void visit(AstDiv* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, true); } - virtual void visit(AstMul* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, true); } + virtual void visit(AstAdd* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, true); } + virtual void visit(AstSub* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, true); } + virtual void visit(AstDiv* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, true); } + virtual void visit(AstMul* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, true); } // These can't promote to real - virtual void visit(AstModDiv* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, false); } - virtual void visit(AstModDivS* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, false); } - virtual void visit(AstMulS* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, false); } - virtual void visit(AstDivS* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, false); } + virtual void visit(AstModDiv* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, false); } + virtual void visit(AstModDivS* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, false); } + virtual void visit(AstMulS* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, false); } + virtual void visit(AstDivS* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, false); } // Widths: out width = lhs width, but upper matters // Signed: Output signed iff LHS signed; unary operator // Unary promote to real - virtual void visit(AstNegate* nodep) VL_OVERRIDE { visit_negate_not(nodep, true); } + virtual void visit(AstNegate* nodep) VL_OVERRIDE { visit_negate_not(nodep, true); } // Unary never real - virtual void visit(AstNot* nodep) VL_OVERRIDE { visit_negate_not(nodep, false); } + virtual void visit(AstNot* nodep) VL_OVERRIDE { visit_negate_not(nodep, false); } // Real: inputs and output real - virtual void visit(AstAddD* nodep) VL_OVERRIDE { visit_real_add_sub(nodep); } - virtual void visit(AstSubD* nodep) VL_OVERRIDE { visit_real_add_sub(nodep); } - virtual void visit(AstDivD* nodep) VL_OVERRIDE { visit_real_add_sub(nodep); } - virtual void visit(AstMulD* nodep) VL_OVERRIDE { visit_real_add_sub(nodep); } - virtual void visit(AstPowD* nodep) VL_OVERRIDE { visit_real_add_sub(nodep); } + virtual void visit(AstAddD* nodep) VL_OVERRIDE { visit_real_add_sub(nodep); } + virtual void visit(AstSubD* nodep) VL_OVERRIDE { visit_real_add_sub(nodep); } + virtual void visit(AstDivD* nodep) VL_OVERRIDE { visit_real_add_sub(nodep); } + virtual void visit(AstMulD* nodep) VL_OVERRIDE { visit_real_add_sub(nodep); } + virtual void visit(AstPowD* nodep) VL_OVERRIDE { visit_real_add_sub(nodep); } virtual void visit(AstNodeSystemBiop* nodep) VL_OVERRIDE { visit_real_add_sub(nodep); } // Real: Output real - virtual void visit(AstNegateD* nodep) VL_OVERRIDE { visit_real_neg_ceil(nodep); } + virtual void visit(AstNegateD* nodep) VL_OVERRIDE { visit_real_neg_ceil(nodep); } virtual void visit(AstNodeSystemUniop* nodep) VL_OVERRIDE { visit_real_neg_ceil(nodep); } // Widths: out signed/unsigned width = lhs width, input un|signed virtual void visit(AstSigned* nodep) VL_OVERRIDE { - visit_signed_unsigned(nodep, AstNumeric::SIGNED); } + visit_signed_unsigned(nodep, AstNumeric::SIGNED); + } virtual void visit(AstUnsigned* nodep) VL_OVERRIDE { - visit_signed_unsigned(nodep, AstNumeric::UNSIGNED); } + visit_signed_unsigned(nodep, AstNumeric::UNSIGNED); + } // Widths: Output width from lhs, rhs<33 bits // Signed: If lhs signed - virtual void visit(AstShiftL* nodep) VL_OVERRIDE { visit_shift(nodep); } - virtual void visit(AstShiftR* nodep) VL_OVERRIDE { visit_shift(nodep); } + virtual void visit(AstShiftL* nodep) VL_OVERRIDE { visit_shift(nodep); } + virtual void visit(AstShiftR* nodep) VL_OVERRIDE { visit_shift(nodep); } // ShiftRS converts to ShiftR, but not vice-versa - virtual void visit(AstShiftRS* nodep) VL_OVERRIDE { visit_shift(nodep); } + virtual void visit(AstShiftRS* nodep) VL_OVERRIDE { visit_shift(nodep); } //======== // Widths: Output real, input integer signed virtual void visit(AstBitsToRealD* nodep) VL_OVERRIDE { visit_Or_Lu64(nodep); } - virtual void visit(AstIToRD* nodep) VL_OVERRIDE { visit_Or_Ls32(nodep); } + virtual void visit(AstIToRD* nodep) VL_OVERRIDE { visit_Or_Ls32(nodep); } // Widths: Output integer signed, input real virtual void visit(AstRToIS* nodep) VL_OVERRIDE { visit_Os32_Lr(nodep); } @@ -344,7 +358,8 @@ private: iterateCheckString(nodep, "LHS", nodep->lhsp(), BOTH); iterateCheckSigned32(nodep, "RHS", nodep->rhsp(), BOTH); iterateCheckSigned32(nodep, "THS", nodep->thsp(), BOTH); - nodep->dtypeSetString(); //AstPutcN returns the new string to be assigned by AstAssign + nodep->dtypeSetString(); // AstPutcN returns the new string to be assigned by + // AstAssign } } virtual void visit(AstGetcN* nodep) VL_OVERRIDE { @@ -407,7 +422,9 @@ private: virtual void visit(AstTime* nodep) VL_OVERRIDE { nodep->dtypeSetUInt64(); } virtual void visit(AstTimeD* nodep) VL_OVERRIDE { nodep->dtypeSetDouble(); } virtual void visit(AstTestPlusArgs* nodep) VL_OVERRIDE { nodep->dtypeSetSigned32(); } - virtual void visit(AstScopeName* nodep) VL_OVERRIDE { nodep->dtypeSetUInt64(); } // A pointer, but not that it matters + virtual void visit(AstScopeName* nodep) VL_OVERRIDE { + nodep->dtypeSetUInt64(); // A pointer, but not that it matters + } // Special cases. So many.... virtual void visit(AstNodeCond* nodep) VL_OVERRIDE { @@ -434,7 +451,7 @@ private: } else if (nodep->expr1p()->isString() || nodep->expr2p()->isString()) { nodep->dtypeSetString(); } else { - int width = std::max(nodep->expr1p()->width(), nodep->expr2p()->width()); + int width = std::max(nodep->expr1p()->width(), nodep->expr2p()->width()); int mwidth = std::max(nodep->expr1p()->widthMin(), nodep->expr2p()->widthMin()); bool issigned = nodep->expr1p()->isSigned() && nodep->expr2p()->isSigned(); nodep->dtypeSetLogicUnsized(width, mwidth, AstNumeric::fromBool(issigned)); @@ -445,8 +462,10 @@ private: AstNodeDType* subDTypep = expDTypep; nodep->dtypeFrom(expDTypep); // Error report and change sizes for suboperands of this node. - iterateCheck(nodep, "Conditional True", nodep->expr1p(), CONTEXT, FINAL, subDTypep, EXTEND_EXP); - iterateCheck(nodep, "Conditional False", nodep->expr2p(), CONTEXT, FINAL, subDTypep, EXTEND_EXP); + iterateCheck(nodep, "Conditional True", nodep->expr1p(), CONTEXT, FINAL, subDTypep, + EXTEND_EXP); + iterateCheck(nodep, "Conditional False", nodep->expr2p(), CONTEXT, FINAL, subDTypep, + EXTEND_EXP); } } virtual void visit(AstConcat* nodep) VL_OVERRIDE { @@ -458,11 +477,12 @@ private: // width: LHS + RHS if (m_vup->prelim()) { AstNodeDType* vdtypep = m_vup->dtypeNullp(); - if (vdtypep && (VN_IS(vdtypep, AssocArrayDType) - || VN_IS(vdtypep, DynArrayDType) - || VN_IS(vdtypep, QueueDType))) { - nodep->v3error("Unsupported: Concatenation to form " - << vdtypep->prettyDTypeNameQ() << "data type"); + if (vdtypep + && (VN_IS(vdtypep, AssocArrayDType) // + || VN_IS(vdtypep, DynArrayDType) // + || VN_IS(vdtypep, QueueDType))) { + nodep->v3error("Unsupported: Concatenation to form " << vdtypep->prettyDTypeNameQ() + << "data type"); } iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH); @@ -473,21 +493,20 @@ private: // Cleanup zero width Verilog2001 {x,{0{foo}}} now, // otherwise having width(0) will cause later assertions to fire if (AstReplicate* repp = VN_CAST(nodep->lhsp(), Replicate)) { - if (repp->width()==0) { // Keep rhs + if (repp->width() == 0) { // Keep rhs nodep->replaceWith(nodep->rhsp()->unlinkFrBack()); VL_DO_DANGLING(pushDeletep(nodep), nodep); return; } } if (AstReplicate* repp = VN_CAST(nodep->rhsp(), Replicate)) { - if (repp->width()==0) { // Keep lhs + if (repp->width() == 0) { // Keep lhs nodep->replaceWith(nodep->lhsp()->unlinkFrBack()); VL_DO_DANGLING(pushDeletep(nodep), nodep); return; } } - if (nodep->lhsp()->isString() - || nodep->rhsp()->isString()) { + if (nodep->lhsp()->isString() || nodep->rhsp()->isString()) { AstNode* newp = new AstConcatN(nodep->fileline(), nodep->lhsp()->unlinkFrBack(), nodep->rhsp()->unlinkFrBack()); nodep->replaceWith(newp); @@ -498,8 +517,8 @@ private: if (m_vup->final()) { if (!nodep->dtypep()->widthSized()) { // See also error in V3Number - nodeForUnsizedWarning(nodep) - ->v3warn(WIDTHCONCAT, "Unsized numbers/parameters not allowed in concatenations."); + nodeForUnsizedWarning(nodep)->v3warn( + WIDTHCONCAT, "Unsized numbers/parameters not allowed in concatenations."); } } } @@ -514,8 +533,8 @@ private: if (m_vup->final()) { if (!nodep->dtypep()->widthSized()) { // See also error in V3Number - nodeForUnsizedWarning(nodep) - ->v3warn(WIDTHCONCAT, "Unsized numbers/parameters not allowed in concatenations."); + nodeForUnsizedWarning(nodep)->v3warn( + WIDTHCONCAT, "Unsized numbers/parameters not allowed in concatenations."); } } } @@ -538,21 +557,24 @@ private: if (m_vup->prelim()) { AstNodeDType* vdtypep = m_vup->dtypeNullp(); if (vdtypep - && (VN_IS(vdtypep, AssocArrayDType) - || VN_IS(vdtypep, DynArrayDType) - || VN_IS(vdtypep, QueueDType) - || VN_IS(vdtypep, UnpackArrayDType))) { + && (VN_IS(vdtypep, AssocArrayDType) || VN_IS(vdtypep, DynArrayDType) + || VN_IS(vdtypep, QueueDType) || VN_IS(vdtypep, UnpackArrayDType))) { nodep->v3error("Unsupported: Replication to form " << vdtypep->prettyDTypeNameQ() - << " data type"); + << " data type"); } iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH); iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH); V3Const::constifyParamsEdit(nodep->rhsp()); // rhsp may change const AstConst* constp = VN_CAST(nodep->rhsp(), Const); - if (!constp) { nodep->v3error("Replication value isn't a constant."); return; } + if (!constp) { + nodep->v3error("Replication value isn't a constant."); + return; + } uint32_t times = constp->toUInt(); - if (times==0 && !VN_IS(nodep->backp(), Concat)) { // Concat Visitor will clean it up. - nodep->v3error("Replication value of 0 is only legal under a concatenation (IEEE 1800-2017 11.4.12.1)"); + if (times == 0 + && !VN_IS(nodep->backp(), Concat)) { // Concat Visitor will clean it up. + nodep->v3error("Replication value of 0 is only legal under a concatenation (IEEE " + "1800-2017 11.4.12.1)"); times = 1; } if (nodep->lhsp()->isString()) { @@ -570,8 +592,8 @@ private: if (m_vup->final()) { if (!nodep->dtypep()->widthSized()) { // See also error in V3Number - nodeForUnsizedWarning(nodep) - ->v3warn(WIDTHCONCAT, "Unsized numbers/parameters not allowed in replications."); + nodeForUnsizedWarning(nodep)->v3warn( + WIDTHCONCAT, "Unsized numbers/parameters not allowed in replications."); } } } @@ -582,18 +604,23 @@ private: iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH); V3Const::constifyParamsEdit(nodep->rhsp()); // rhsp may change const AstConst* constp = VN_CAST(nodep->rhsp(), Const); - if (!constp) { nodep->v3error("Replication value isn't a constant."); return; } + if (!constp) { + nodep->v3error("Replication value isn't a constant."); + return; + } uint32_t times = constp->toUInt(); - if (times==0 && !VN_IS(nodep->backp(), Concat)) { // Concat Visitor will clean it up. - nodep->v3error("Replication value of 0 is only legal under a concatenation (IEEE 1800-2017 11.4.12.1)"); + if (times == 0 + && !VN_IS(nodep->backp(), Concat)) { // Concat Visitor will clean it up. + nodep->v3error("Replication value of 0 is only legal under a concatenation (IEEE " + "1800-2017 11.4.12.1)"); } nodep->dtypeSetString(); } if (m_vup->final()) { if (!nodep->dtypep()->widthSized()) { // See also error in V3Number - nodeForUnsizedWarning(nodep) - ->v3warn(WIDTHCONCAT, "Unsized numbers/parameters not allowed in replications."); + nodeForUnsizedWarning(nodep)->v3warn( + WIDTHCONCAT, "Unsized numbers/parameters not allowed in replications."); } } } @@ -604,24 +631,29 @@ private: V3Const::constifyParamsEdit(nodep->rhsp()); // rhsp may change const AstConst* constp = VN_CAST(nodep->rhsp(), Const); AstBasicDType* basicp = VN_CAST(nodep->rhsp(), BasicDType); - if (!constp && !basicp) { nodep->v3error("Slice size isn't a constant or basic data type."); return; } + if (!constp && !basicp) { + nodep->v3error("Slice size isn't a constant or basic data type."); + return; + } if (basicp) { // Convert data type to a constant size AstConst* newp = new AstConst(basicp->fileline(), basicp->width()); nodep->rhsp()->replaceWith(newp); pushDeletep(basicp); } else { uint32_t sliceSize = constp->toUInt(); - if (!sliceSize) { nodep->v3error("Slice size cannot be zero."); return; } + if (!sliceSize) { + nodep->v3error("Slice size cannot be zero."); + return; + } } - nodep->dtypeSetLogicUnsized(nodep->lhsp()->width(), - nodep->lhsp()->widthMin(), + nodep->dtypeSetLogicUnsized(nodep->lhsp()->width(), nodep->lhsp()->widthMin(), AstNumeric::UNSIGNED); } if (m_vup->final()) { if (!nodep->dtypep()->widthSized()) { // See also error in V3Number - nodeForUnsizedWarning(nodep) - ->v3warn(WIDTHCONCAT, "Unsized numbers/parameters not allowed in streams."); + nodeForUnsizedWarning(nodep)->v3warn( + WIDTHCONCAT, "Unsized numbers/parameters not allowed in streams."); } } } @@ -629,14 +661,14 @@ private: // Real: Not allowed // Signed: unsigned output, input either // Convert all range values to constants - UINFO(6,"RANGE "<msbp()); // May relink pointed to node V3Const::constifyParamsEdit(nodep->lsbp()); // May relink pointed to node checkConstantOrReplace(nodep->msbp(), "MSB of bit range isn't a constant"); checkConstantOrReplace(nodep->lsbp(), "LSB of bit range isn't a constant"); int msb = nodep->msbConst(); int lsb = nodep->lsbConst(); - if (msblittleEndian(!nodep->littleEndian()); @@ -648,13 +680,15 @@ private: if (m_vup->prelim()) { // Don't need to iterate because V3Const already constified int width = nodep->elementsConst(); - if (width > (1<<28)) nodep->v3error("Width of bit range is huge; vector of over 1billion bits: 0x" - < (1 << 28)) { + nodep->v3error("Width of bit range is huge; vector of over 1billion bits: 0x" + << std::hex << width); + } // Note width() not set on range; use elementsConst() if (nodep->littleEndian() && !VN_IS(nodep->backp(), UnpackArrayDType) && !VN_IS(nodep->backp(), Cell)) { // For cells we warn in V3Inst nodep->v3warn(LITENDIAN, "Little bit endian vector: MSB < LSB of bit range: " - <lsbConst()<<":"<msbConst()); + << nodep->lsbConst() << ":" << nodep->msbConst()); } } } @@ -666,7 +700,7 @@ private: if (nodep->didWidth()) return; UASSERT_OBJ(m_vup, nodep, "Select under an unexpected context"); if (m_vup->prelim()) { - if (debug()>=9) nodep->dumpTree(cout, "-selWidth: "); + if (debug() >= 9) nodep->dumpTree(cout, "-selWidth: "); userIterateAndNext(nodep->fromp(), WidthVP(CONTEXT, PRELIM).p()); userIterateAndNext(nodep->lsbp(), WidthVP(SELF, PRELIM).p()); checkCvtUS(nodep->fromp()); @@ -676,28 +710,28 @@ private: AstConst* widthConstp = VN_CAST(nodep->widthp(), Const); if (!widthConstp) { nodep->v3error("Width of bit extract isn't a constant"); - nodep->dtypeSetLogicBool(); return; + nodep->dtypeSetLogicBool(); + return; } int width = nodep->widthConst(); UASSERT_OBJ(nodep->dtypep(), nodep, "dtype wasn't set"); // by V3WidthSel - if (VN_IS(nodep->lsbp(), Const) - && nodep->msbConst() < nodep->lsbConst()) { + if (VN_IS(nodep->lsbp(), Const) && nodep->msbConst() < nodep->lsbConst()) { nodep->v3error("Unsupported: MSB < LSB of bit extract: " - <msbConst()<<"<"<lsbConst()); + << nodep->msbConst() << "<" << nodep->lsbConst()); width = (nodep->lsbConst() - nodep->msbConst() + 1); nodep->dtypeSetLogicSized(width, AstNumeric::UNSIGNED); - nodep->widthp()->replaceWith(new AstConst(nodep->widthp()->fileline(), - width)); + nodep->widthp()->replaceWith(new AstConst(nodep->widthp()->fileline(), width)); nodep->lsbp()->replaceWith(new AstConst(nodep->lsbp()->fileline(), 0)); } // We're extracting, so just make sure the expression is at least wide enough. if (nodep->fromp()->width() < width) { - nodep->v3error("Extracting "<fromp()->width()<<" bit number"); + nodep->v3error("Extracting " << width << " bits from only " + << nodep->fromp()->width() << " bit number"); // Extend it. AstNodeDType* subDTypep = nodep->findLogicDType(width, width, nodep->fromp()->dtypep()->numeric()); - widthCheckSized(nodep, "errorless...", nodep->fromp(), subDTypep, EXTEND_EXP, false/*noerror*/); + widthCheckSized(nodep, "errorless...", nodep->fromp(), subDTypep, EXTEND_EXP, + false /*noerror*/); } // Check bit indexes. // What is the MSB? We want the true MSB, not one starting at @@ -707,27 +741,29 @@ private: int fromlsb = 0; int elw = nodep->declElWidth(); // Must adjust to tell user bit ranges if (nodep->declRange().ranged()) { - frommsb = nodep->declRange().hiMaxSelect()*elw + (elw-1); // Corrected for negative lsb - fromlsb = nodep->declRange().lo()*elw; + frommsb = nodep->declRange().hiMaxSelect() * elw + + (elw - 1); // Corrected for negative lsb + fromlsb = nodep->declRange().lo() * elw; } else { - //nodep->v3fatalSrc("Should have been declRanged in V3WidthSel"); + // nodep->v3fatalSrc("Should have been declRanged in V3WidthSel"); } - int selwidth = V3Number::log2b(frommsb+1-1)+1; // Width to address a bit + int selwidth = V3Number::log2b(frommsb + 1 - 1) + 1; // Width to address a bit AstNodeDType* selwidthDTypep = nodep->findLogicDType(selwidth, selwidth, nodep->lsbp()->dtypep()->numeric()); userIterateAndNext(nodep->fromp(), WidthVP(SELF, FINAL).p()); userIterateAndNext(nodep->lsbp(), WidthVP(SELF, FINAL).p()); - if (widthBad(nodep->lsbp(), selwidthDTypep) - && nodep->lsbp()->width()!=32) { + if (widthBad(nodep->lsbp(), selwidthDTypep) && nodep->lsbp()->width() != 32) { if (!nodep->fileline()->warnIsOff(V3ErrorCode::WIDTH)) { - nodep->v3warn(WIDTH, "Bit extraction of var[" - <<(frommsb/elw)<<":"<<(fromlsb/elw)<<"] requires " - <<(selwidth/elw)<<" bit index, not " - <<(nodep->lsbp()->width()/elw) - <<(nodep->lsbp()->width()!=nodep->lsbp()->widthMin() - ?" or "+cvtToStr(nodep->lsbp()->widthMin()/elw):"") - <<" bits."); - UINFO(1," Related node: "<v3warn(WIDTH, + "Bit extraction of var[" + << (frommsb / elw) << ":" << (fromlsb / elw) << "] requires " + << (selwidth / elw) << " bit index, not " + << (nodep->lsbp()->width() / elw) + << (nodep->lsbp()->width() != nodep->lsbp()->widthMin() + ? " or " + cvtToStr(nodep->lsbp()->widthMin() / elw) + : "") + << " bits."); + UINFO(1, " Related node: " << nodep << endl); } } if (VN_IS(nodep->lsbp(), Const) && nodep->msbConst() > frommsb) { @@ -740,12 +776,12 @@ private: // should only trigger the error if the out-of-range access is // actually generated. if (m_doGenerate) { - UINFO(5, "Selection index out of range inside generate."<v3warn(SELRANGE, "Selection index out of range: " - <msbConst()<<":"<lsbConst() - <<" outside "<msbConst() << ":" << nodep->lsbConst() + << " outside " << frommsb << ":" << fromlsb); + UINFO(1, " Related node: " << nodep << endl); } } // iterate FINAL is two blocks above @@ -758,8 +794,8 @@ private: // we want the select to be truncated to fit within the // maximum select range, e.g. turn Xs outside of the select // into something fast which pulls from within the array. - widthCheckSized(nodep, "Extract Range", - nodep->lsbp(), selwidthDTypep, EXTEND_EXP, false/*NOWARN*/); + widthCheckSized(nodep, "Extract Range", nodep->lsbp(), selwidthDTypep, EXTEND_EXP, + false /*NOWARN*/); } } } @@ -778,47 +814,50 @@ private: if (const AstUnpackArrayDType* adtypep = VN_CAST(fromDtp, UnpackArrayDType)) { frommsb = adtypep->msb(); fromlsb = adtypep->lsb(); - if (fromlsb>frommsb) {int t = frommsb; frommsb = fromlsb; fromlsb = t; } + if (fromlsb > frommsb) { + int t = frommsb; + frommsb = fromlsb; + fromlsb = t; + } // However, if the lsb<0 we may go negative, so need more bits! if (fromlsb < 0) frommsb += -fromlsb; nodep->dtypeFrom(adtypep->subDTypep()); // Need to strip off array reference - } - else { + } else { // Note PackArrayDType doesn't use an ArraySel but a normal Sel. - UINFO(1," Related dtype: "<v3fatalSrc("Array reference exceeds dimension of array"); frommsb = fromlsb = 0; } - int selwidth = V3Number::log2b(frommsb+1-1)+1; // Width to address a bit + int selwidth = V3Number::log2b(frommsb + 1 - 1) + 1; // Width to address a bit AstNodeDType* selwidthDTypep = nodep->findLogicDType(selwidth, selwidth, nodep->bitp()->dtypep()->numeric()); - if (widthBad(nodep->bitp(), selwidthDTypep) - && nodep->bitp()->width()!=32) { + if (widthBad(nodep->bitp(), selwidthDTypep) && nodep->bitp()->width() != 32) { nodep->v3warn(WIDTH, "Bit extraction of array[" - <bitp()->width() - <<(nodep->bitp()->width()!=nodep->bitp()->widthMin() - ?" or "+cvtToStr(nodep->bitp()->widthMin()):"") - <<" bits."); + << frommsb << ":" << fromlsb << "] requires " << selwidth + << " bit index, not " << nodep->bitp()->width() + << (nodep->bitp()->width() != nodep->bitp()->widthMin() + ? " or " + cvtToStr(nodep->bitp()->widthMin()) + : "") + << " bits."); if (!nodep->fileline()->warnIsOff(V3ErrorCode::WIDTH)) { - UINFO(1," Related node: "<dtypep()<dtypep() << endl); } } if (!m_doGenerate) { // Must check bounds before adding a select that truncates the bound // Note we've already subtracted off LSB if (VN_IS(nodep->bitp(), Const) - && (VN_CAST(nodep->bitp(), Const)->toSInt() > (frommsb-fromlsb) + && (VN_CAST(nodep->bitp(), Const)->toSInt() > (frommsb - fromlsb) || VN_CAST(nodep->bitp(), Const)->toSInt() < 0)) { - nodep->v3warn(SELRANGE, "Selection index out of range: " - <<(VN_CAST(nodep->bitp(), Const)->toSInt()+fromlsb) - <<" outside "<v3warn(SELRANGE, + "Selection index out of range: " + << (VN_CAST(nodep->bitp(), Const)->toSInt() + fromlsb) + << " outside " << frommsb << ":" << fromlsb); + UINFO(1, " Related node: " << nodep << endl); } - widthCheckSized(nodep, "Extract Range", - nodep->bitp(), selwidthDTypep, EXTEND_EXP, false/*NOWARN*/); + widthCheckSized(nodep, "Extract Range", nodep->bitp(), selwidthDTypep, EXTEND_EXP, + false /*NOWARN*/); } } } @@ -829,10 +868,11 @@ private: AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefp(); AstAssocArrayDType* adtypep = VN_CAST(fromDtp, AssocArrayDType); if (!adtypep) { - UINFO(1," Related dtype: "<v3fatalSrc("Associative array reference is not to associative array"); } - iterateCheckTyped(nodep, "Associative select", nodep->bitp(), adtypep->keyDTypep(), BOTH); + iterateCheckTyped(nodep, "Associative select", nodep->bitp(), adtypep->keyDTypep(), + BOTH); nodep->dtypeFrom(adtypep->subDTypep()); } } @@ -846,14 +886,13 @@ private: AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefp(); AstUnpackArrayDType* adtypep = VN_CAST(fromDtp, UnpackArrayDType); if (!adtypep) { - UINFO(1," Related dtype: "<v3fatalSrc("Packed array reference exceeds dimension of array"); } // Build new array Dtype based on the original's base type, but with new bounds - AstNodeDType* newDtp = new AstUnpackArrayDType(nodep->fileline(), - adtypep->subDTypep(), - new AstRange(nodep->fileline(), - nodep->declRange())); + AstNodeDType* newDtp + = new AstUnpackArrayDType(nodep->fileline(), adtypep->subDTypep(), + new AstRange(nodep->fileline(), nodep->declRange())); v3Global.rootp()->typeTablep()->addTypesp(newDtp); nodep->dtypeFrom(newDtp); @@ -863,15 +902,16 @@ private: if ((nodep->declRange().hi() > adtypep->declRange().hi()) || nodep->declRange().lo() < adtypep->declRange().lo()) { // Other simulators warn too - nodep->v3error("Slice selection index '"<< nodep->declRange() << "'" - <<" outside data type's '"<< adtypep->declRange() << "'"); - } - else if ((nodep->declRange().littleEndian() - != adtypep->declRange().littleEndian()) - && nodep->declRange().hi() != nodep->declRange().lo()) { - nodep->v3error("Slice selection '"<< nodep->declRange() << "'" - <<" has backward indexing versus data type's '" - <declRange() << "'"); + nodep->v3error("Slice selection index '" << nodep->declRange() << "'" + << " outside data type's '" + << adtypep->declRange() << "'"); + } else if ((nodep->declRange().littleEndian() + != adtypep->declRange().littleEndian()) + && nodep->declRange().hi() != nodep->declRange().lo()) { + nodep->v3error("Slice selection '" + << nodep->declRange() << "'" + << " has backward indexing versus data type's '" + << adtypep->declRange() << "'"); } } } @@ -884,7 +924,11 @@ private: userIterateAndNext(nodep->thsp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->attrp(), WidthVP(SELF, BOTH).p()); AstNode* selp = V3Width::widthSelNoIterEdit(nodep); - if (selp!=nodep) { nodep = NULL; userIterate(selp, m_vup); return; } + if (selp != nodep) { + nodep = NULL; + userIterate(selp, m_vup); + return; + } nodep->v3fatalSrc("AstSelBit should disappear after widthSel"); } virtual void visit(AstSelExtract* nodep) VL_OVERRIDE { @@ -894,7 +938,11 @@ private: userIterateAndNext(nodep->thsp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->attrp(), WidthVP(SELF, BOTH).p()); AstNode* selp = V3Width::widthSelNoIterEdit(nodep); - if (selp!=nodep) { nodep = NULL; userIterate(selp, m_vup); return; } + if (selp != nodep) { + nodep = NULL; + userIterate(selp, m_vup); + return; + } nodep->v3fatalSrc("AstSelExtract should disappear after widthSel"); } virtual void visit(AstSelPlus* nodep) VL_OVERRIDE { @@ -903,7 +951,11 @@ private: userIterateAndNext(nodep->thsp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->attrp(), WidthVP(SELF, BOTH).p()); AstNode* selp = V3Width::widthSelNoIterEdit(nodep); - if (selp!=nodep) { nodep = NULL; userIterate(selp, m_vup); return; } + if (selp != nodep) { + nodep = NULL; + userIterate(selp, m_vup); + return; + } nodep->v3fatalSrc("AstSelPlus should disappear after widthSel"); } virtual void visit(AstSelMinus* nodep) VL_OVERRIDE { @@ -912,7 +964,11 @@ private: userIterateAndNext(nodep->thsp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->attrp(), WidthVP(SELF, BOTH).p()); AstNode* selp = V3Width::widthSelNoIterEdit(nodep); - if (selp!=nodep) { nodep = NULL; userIterate(selp, m_vup); return; } + if (selp != nodep) { + nodep = NULL; + userIterate(selp, m_vup); + return; + } nodep->v3fatalSrc("AstSelMinus should disappear after widthSel"); } @@ -954,8 +1010,9 @@ private: nodep->ticksp()->unlinkFrBack()->deleteTree(); } else { if (constp->toSInt() > 10) { - constp->v3warn(TICKCOUNT, "$past tick value of "<toSInt() - <<" may have a large performance cost"); + constp->v3warn(TICKCOUNT, "$past tick value of " + << constp->toSInt() + << " may have a large performance cost"); } } } @@ -985,7 +1042,9 @@ private: if (m_vup->final()) { AstNodeDType* expDTypep = m_vup->dtypeOverridep(nodep->dtypep()); nodep->dtypeFrom(expDTypep); // Assume user knows the rules; go with the flow - if (nodep->width()>64) nodep->v3error("Unsupported: $c can't generate wider than 64 bits"); + if (nodep->width() > 64) { + nodep->v3error("Unsupported: $c can't generate wider than 64 bits"); + } } } virtual void visit(AstCLog2* nodep) VL_OVERRIDE { @@ -1032,8 +1091,8 @@ private: } if (newp) { newp->dtypeFrom(nodep); - UINFO(9,"powOld "<replaceWith(newp), nodep); } } @@ -1060,8 +1119,9 @@ private: if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH); // If it's a 32 bit number, we need a 6 bit number as we need to return '32'. - int selwidth = V3Number::log2b(nodep->lhsp()->width())+1; - nodep->dtypeSetLogicSized(selwidth, AstNumeric::UNSIGNED); // Spec doesn't indicate if an integer + int selwidth = V3Number::log2b(nodep->lhsp()->width()) + 1; + nodep->dtypeSetLogicSized( + selwidth, AstNumeric::UNSIGNED); // Spec doesn't indicate if an integer } } virtual void visit(AstCvtPackString* nodep) VL_OVERRIDE { @@ -1083,11 +1143,11 @@ private: break; case AstAttrType::DIM_DIMENSIONS: case AstAttrType::DIM_UNPK_DIMENSIONS: { - UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep, - "Unsized expression"); - std::pair dim = nodep->fromp()->dtypep()->dimensions(true); - int val = (nodep->attrType()==AstAttrType::DIM_UNPK_DIMENSIONS - ? dim.second : (dim.first+dim.second)); + UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep, "Unsized expression"); + std::pair dim = nodep->fromp()->dtypep()->dimensions(true); + int val = (nodep->attrType() == AstAttrType::DIM_UNPK_DIMENSIONS + ? dim.second + : (dim.first + dim.second)); nodep->replaceWith(new AstConst(nodep->fileline(), AstConst::Signed32(), val)); VL_DO_DANGLING(nodep->deleteTree(), nodep); break; @@ -1108,13 +1168,15 @@ private: newp->dtypeSetSigned32(); newp->didWidth(true); newp->protect(false); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); break; } case AstAttrType::DIM_LEFT: case AstAttrType::DIM_LOW: { AstNode* newp = new AstConst(nodep->fileline(), AstConst::Signed32(), 0); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); break; } case AstAttrType::DIM_RIGHT: @@ -1127,12 +1189,14 @@ private: AstNode* newp = new AstSub(nodep->fileline(), sizep, new AstConst(nodep->fileline(), AstConst::Signed32(), 1)); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); break; } case AstAttrType::DIM_INCREMENT: { AstNode* newp = new AstConst(nodep->fileline(), AstConst::Signed32(), -1); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); break; } case AstAttrType::DIM_BITS: { @@ -1149,14 +1213,15 @@ private: int dim = 1; AstConst* newp = dimensionValue(nodep->fileline(), nodep->fromp()->dtypep(), nodep->attrType(), dim); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } else if (VN_IS(nodep->dimp(), Const)) { int dim = VN_CAST(nodep->dimp(), Const)->toSInt(); AstConst* newp = dimensionValue(nodep->fileline(), nodep->fromp()->dtypep(), nodep->attrType(), dim); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); - } - else { // Need a runtime lookup table. Yuk. + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); + } else { // Need a runtime lookup table. Yuk. UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep, "Unsized expression"); AstVar* varp @@ -1165,7 +1230,8 @@ private: AstVarRef* varrefp = new AstVarRef(nodep->fileline(), varp, false); varrefp->packagep(v3Global.rootp()->dollarUnitPkgAddp()); AstNode* newp = new AstArraySel(nodep->fileline(), varrefp, dimp); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } } break; @@ -1174,13 +1240,14 @@ private: UASSERT_OBJ(nodep->fromp(), nodep, "Unprovided expression"); string result = nodep->fromp()->dtypep()->prettyDTypeName(); AstNode* newp = new AstConst(nodep->fileline(), AstConst::String(), result); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); break; } default: { // Everything else resolved earlier nodep->dtypeSetLogicUnsized(32, 1, AstNumeric::UNSIGNED); // Approximation, unsized 32 - UINFO(1,"Missing ATTR type case node: "<v3fatalSrc("Missing ATTR type case"); break; } @@ -1211,17 +1278,19 @@ private: int width = nodep->subDTypep()->width() * nodep->rangep()->elementsConst(); nodep->widthForce(width, width); } - UINFO(4,"dtWidthed "<didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed if (nodep->childDTypep()) nodep->refDTypep(moveChildDTypeEdit(nodep)); - if (nodep->keyChildDTypep()) nodep->keyDTypep(moveDTypeEdit(nodep, nodep->keyChildDTypep())); + if (nodep->keyChildDTypep()) { + nodep->keyDTypep(moveDTypeEdit(nodep, nodep->keyChildDTypep())); + } // Iterate into subDTypep() to resolve that type and update pointer. nodep->refDTypep(iterateEditDTypep(nodep, nodep->subDTypep())); nodep->keyDTypep(iterateEditDTypep(nodep, nodep->keyDTypep())); nodep->dtypep(nodep); // The array itself, not subDtype - UINFO(4,"dtWidthed "<didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed @@ -1229,7 +1298,7 @@ private: // Iterate into subDTypep() to resolve that type and update pointer. nodep->refDTypep(iterateEditDTypep(nodep, nodep->subDTypep())); nodep->dtypep(nodep); // The array itself, not subDtype - UINFO(4,"dtWidthed "<didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed @@ -1240,7 +1309,7 @@ private: if (VN_IS(nodep->boundp(), Unbounded)) { nodep->boundp()->unlinkFrBack()->deleteTree(); // NULL will represent unbounded } - UINFO(4,"dtWidthed "<didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed @@ -1249,7 +1318,7 @@ private: nodep->refDTypep(iterateEditDTypep(nodep, nodep->subDTypep())); // Cleanup array size nodep->dtypep(nodep); // The array itself, not subDtype - UINFO(4,"dtWidthed "<didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed @@ -1261,20 +1330,18 @@ private: // Furthermore the width() calculation would return identical // values. Therefore we can directly replace the width nodep->widthForce(nodep->rangep()->elementsConst(), nodep->rangep()->elementsConst()); - } - else if (nodep->isRanged()) { + } else if (nodep->isRanged()) { nodep->widthForce(nodep->nrange().elements(), nodep->nrange().elements()); - } - else if (nodep->implicit()) { + } else if (nodep->implicit()) { // Parameters may notice implicitness and change to different dtype nodep->widthForce(1, 1); } // else width in node is correct; it was set based on keyword().width() // at construction time. Ditto signed, so "unsigned byte" etc works right. nodep->cvtRangeConst(); - // TODO: If BasicDType now looks like a generic type, we can convert to a real generic dtype - // Instead for now doing this in V3WidthCommit - UINFO(4,"dtWidthed "<didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed @@ -1287,11 +1354,11 @@ private: userIterateChildren(nodep, NULL); nodep->dtypep(nodep); // Should already be set, but be clear it's not the subDType nodep->widthFromSub(nodep->subDTypep()); - UINFO(4,"dtWidthed "<doingWidth()) { // Early exit if have circular parameter definition - nodep->v3error("Typedef's type is circular: "<prettyName()); + nodep->v3error("Typedef's type is circular: " << nodep->prettyName()); nodep->dtypeSetLogicBool(); nodep->doingWidth(false); return; @@ -1315,7 +1382,7 @@ private: nodep->dtypeFrom(nodep->defp()); userIterate(nodep->defp(), NULL); nodep->widthFromSub(nodep->subDTypep()); - UINFO(4,"dtWidthed "<doingWidth(false); } virtual void visit(AstTypedef* nodep) VL_OVERRIDE { @@ -1337,20 +1404,20 @@ private: V3Const::constifyParamsEdit(nodep->dtp()); // itemp may change if (AstConst* constp = VN_CAST(nodep->dtp(), Const)) { constp->unlinkFrBack(); - AstNode* newp = new AstCastSize(nodep->fileline(), - nodep->lhsp()->unlinkFrBack(), constp); + AstNode* newp + = new AstCastSize(nodep->fileline(), nodep->lhsp()->unlinkFrBack(), constp); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); userIterate(newp, m_vup); } else { - nodep->v3error("Unsupported: Cast to "<dtp()->prettyTypeName()); + nodep->v3error("Unsupported: Cast to " << nodep->dtp()->prettyTypeName()); nodep->replaceWith(nodep->lhsp()->unlinkFrBack()); } } virtual void visit(AstCast* nodep) VL_OVERRIDE { if (nodep->childDTypep()) nodep->dtypep(moveChildDTypeEdit(nodep)); nodep->dtypep(iterateEditDTypep(nodep, nodep->dtypep())); - //if (debug()) nodep->dumpTree(cout, " CastPre: "); + // if (debug()) nodep->dumpTree(cout, " CastPre: "); userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); // When more general casts are supported, the cast elimination will be done later. // For now, replace it ASAP, so widthing can propagate easily @@ -1373,34 +1440,33 @@ private: if (basicp->isSigned()) { newp = new AstRToIRoundS(nodep->fileline(), newp); } else { - newp = new AstUnsigned(nodep->fileline(), - new AstRToIS(nodep->fileline(), newp)); + newp = new AstUnsigned(nodep->fileline(), new AstRToIS(nodep->fileline(), newp)); } } else if (basicp->isSigned() && !newp->isSigned()) { newp = new AstSigned(nodep->fileline(), newp); } else if (!basicp->isSigned() && newp->isSigned()) { newp = new AstUnsigned(nodep->fileline(), newp); } else { - //newp = newp; // Can just remove cast + // newp = newp; // Can just remove cast } nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - //if (debug()) newp->dumpTree(cout, " CastOut: "); + // if (debug()) newp->dumpTree(cout, " CastOut: "); } virtual void visit(AstCastSize* nodep) VL_OVERRIDE { // IEEE: Signedness of result is same as self-determined signedness // However, the result is same as BITSEL, so we do not sign extend the LHS - UASSERT_OBJ(VN_IS(nodep->rhsp(), Const), nodep, - "Unsupported: Non-const cast of size"); - //if (debug()) nodep->dumpTree(cout, " CastSizePre: "); + UASSERT_OBJ(VN_IS(nodep->rhsp(), Const), nodep, "Unsupported: Non-const cast of size"); + // if (debug()) nodep->dumpTree(cout, " CastSizePre: "); if (m_vup->prelim()) { int width = VN_CAST(nodep->rhsp(), Const)->toSInt(); - if (width < 1) { nodep->v3error("Size-changing cast to zero or negative size"); width=1; } + if (width < 1) { + nodep->v3error("Size-changing cast to zero or negative size"); + width = 1; + } userIterateAndNext(nodep->lhsp(), WidthVP(SELF, PRELIM).p()); AstBasicDType* underDtp = VN_CAST(nodep->lhsp()->dtypep(), BasicDType); - if (!underDtp) { - underDtp = nodep->lhsp()->dtypep()->basicp(); - } + if (!underDtp) underDtp = nodep->lhsp()->dtypep()->basicp(); if (!underDtp) { nodep->v3error("Unsupported: Size-changing cast on non-basic data type"); underDtp = VN_CAST(nodep->findLogicBoolDType(), BasicDType); @@ -1411,19 +1477,22 @@ private: // So two steps, first do the calculation's width (max of the two widths) { int calcWidth = std::max(width, underDtp->width()); - AstNodeDType* calcDtp = (underDtp->isFourstate() - ? nodep->findLogicDType(calcWidth, calcWidth, underDtp->numeric()) - : nodep->findBitDType(calcWidth, calcWidth, underDtp->numeric())); + AstNodeDType* calcDtp + = (underDtp->isFourstate() + ? nodep->findLogicDType(calcWidth, calcWidth, underDtp->numeric()) + : nodep->findBitDType(calcWidth, calcWidth, underDtp->numeric())); nodep->dtypep(calcDtp); // We ignore warnings as that is sort of the point of a cast - iterateCheck(nodep, "Cast expr", nodep->lhsp(), CONTEXT, FINAL, calcDtp, EXTEND_EXP, false); + iterateCheck(nodep, "Cast expr", nodep->lhsp(), CONTEXT, FINAL, calcDtp, + EXTEND_EXP, false); } - //if (debug()) nodep->dumpTree(cout, " CastSizeClc: "); + // if (debug()) nodep->dumpTree(cout, " CastSizeClc: "); // Next step, make the proper output width { - AstNodeDType* outDtp = (underDtp->isFourstate() - ? nodep->findLogicDType(width, width, underDtp->numeric()) - : nodep->findBitDType(width, width, underDtp->numeric())); + AstNodeDType* outDtp + = (underDtp->isFourstate() + ? nodep->findLogicDType(width, width, underDtp->numeric()) + : nodep->findBitDType(width, width, underDtp->numeric())); nodep->dtypep(outDtp); // We ignore warnings as that is sort of the point of a cast widthCheckSized(nodep, "Cast expr", nodep->lhsp(), outDtp, EXTEND_EXP, false); @@ -1435,17 +1504,17 @@ private: nodep->replaceWith(underp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - //if (debug()) nodep->dumpTree(cout, " CastSizeOut: "); + // if (debug()) nodep->dumpTree(cout, " CastSizeOut: "); } virtual void visit(AstVar* nodep) VL_OVERRIDE { - //if (debug()) nodep->dumpTree(cout, " InitPre: "); + // if (debug()) nodep->dumpTree(cout, " InitPre: "); // Must have deterministic constant width // We can't skip this step when width()!=0, as creating a AstVar // with non-constant range gets size 1, not size 0. So use didWidth(). if (nodep->didWidth()) return; if (nodep->doingWidth()) { // Early exit if have circular parameter definition UASSERT_OBJ(nodep->valuep(), nodep, "circular, but without value"); - nodep->v3error("Variable's initial value is circular: "<prettyNameQ()); + nodep->v3error("Variable's initial value is circular: " << nodep->prettyNameQ()); pushDeletep(nodep->valuep()->unlinkFrBack()); nodep->valuep(new AstConst(nodep->fileline(), AstConst::LogicTrue())); nodep->dtypeFrom(nodep->valuep()); @@ -1465,15 +1534,13 @@ private: nodep->dtypep(newp); v3Global.rootp()->typeTablep()->addTypesp(newp); } - } - else if (nodep->isIO() && !(VN_IS(nodep->dtypeSkipRefp(), BasicDType) - || VN_IS(nodep->dtypeSkipRefp(), NodeArrayDType) - || VN_IS(nodep->dtypeSkipRefp(), NodeUOrStructDType))) { + } else if (nodep->isIO() + && !(VN_IS(nodep->dtypeSkipRefp(), BasicDType) + || VN_IS(nodep->dtypeSkipRefp(), NodeArrayDType) + || VN_IS(nodep->dtypeSkipRefp(), NodeUOrStructDType))) { nodep->v3error("Unsupported: Inputs and outputs must be simple data types"); } - if (VN_IS(nodep->dtypep()->skipRefToConstp(), ConstDType)) { - nodep->isConst(true); - } + if (VN_IS(nodep->dtypep()->skipRefToConstp(), ConstDType)) nodep->isConst(true); // Parameters if implicit untyped inherit from what they are assigned to AstBasicDType* bdtypep = VN_CAST(nodep->dtypep(), BasicDType); bool didchk = false; @@ -1481,64 +1548,70 @@ private: if (implicitParam) { if (nodep->valuep()) { userIterateAndNext(nodep->valuep(), WidthVP(nodep->dtypep(), PRELIM).p()); - UINFO(9,"implicitParamPRELIMIV "<valuep()<valuep() << endl); // Although nodep will get a different width for parameters // just below, we want the init numbers to retain their // width/minwidth until parameters are replaced. // This prevents width warnings at the location the parameter is substituted in if (nodep->valuep()->isDouble()) { - nodep->dtypeSetDouble(); VL_DANGLING(bdtypep); + nodep->dtypeSetDouble(); + VL_DANGLING(bdtypep); } else { int width = 0; AstBasicDType* valueBdtypep = nodep->valuep()->dtypep()->basicp(); bool issigned = false; if (bdtypep->isNosign()) { if (valueBdtypep && valueBdtypep->isSigned()) issigned = true; - } else issigned = bdtypep->isSigned(); + } else { + issigned = bdtypep->isSigned(); + } if (nodep->valuep()->dtypep()->widthSized()) { width = nodep->valuep()->width(); } else { - if (nodep->valuep()->width()>32) { - nodep->valuep()->v3warn(WIDTH, "Assigning >32 bit to unranged parameter (defaults to 32 bits)"); + if (nodep->valuep()->width() > 32) { + nodep->valuep()->v3warn( + WIDTH, + "Assigning >32 bit to unranged parameter (defaults to 32 bits)"); } width = 32; } // Can't just inherit valuep()->dtypep() as mwidth might not equal width - if (width==1) { + if (width == 1) { // one bit parameter is same as "parameter [0] foo", // not "parameter logic foo" as you can extract // "foo[0]" from a parameter but not a wire nodep->dtypeChgWidthSigned(width, nodep->valuep()->widthMin(), AstNumeric::fromBool(issigned)); - nodep->dtypep(nodep->findLogicRangeDType - (VNumRange(0, 0, false), - nodep->valuep()->widthMin(), - AstNumeric::fromBool(issigned))); + nodep->dtypep(nodep->findLogicRangeDType(VNumRange(0, 0, false), + nodep->valuep()->widthMin(), + AstNumeric::fromBool(issigned))); } else { nodep->dtypeChgWidthSigned(width, nodep->valuep()->widthMin(), AstNumeric::fromBool(issigned)); } didchk = true; } - iterateCheckAssign(nodep, "Initial value", nodep->valuep(), FINAL, nodep->dtypep()); - UINFO(9,"implicitParamFromIV "<valuep()<valuep(), FINAL, + nodep->dtypep()); + UINFO(9, "implicitParamFromIV " << nodep->valuep() << endl); + // UINFO below will print variable nodep } else { // Or, if nothing assigned, they're integral - nodep->dtypeSetSigned32(); VL_DANGLING(bdtypep); + nodep->dtypeSetSigned32(); + VL_DANGLING(bdtypep); } - } - else if (bdtypep && bdtypep->implicit()) { // Implicits get converted to size 1 - nodep->dtypeSetLogicSized(1, bdtypep->numeric()); VL_DANGLING(bdtypep); + } else if (bdtypep && bdtypep->implicit()) { // Implicits get converted to size 1 + nodep->dtypeSetLogicSized(1, bdtypep->numeric()); + VL_DANGLING(bdtypep); } if (nodep->valuep() && !didchk) { - //if (debug()) nodep->dumpTree(cout, " final: "); + // if (debug()) nodep->dumpTree(cout, " final: "); // AstPattern requires assignments to pass datatype on PRELIM userIterateAndNext(nodep->valuep(), WidthVP(nodep->dtypep(), PRELIM).p()); iterateCheckAssign(nodep, "Initial value", nodep->valuep(), FINAL, nodep->dtypep()); } - UINFO(4,"varWidthed "<dumpTree(cout, " InitOut: "); + UINFO(4, "varWidthed " << nodep << endl); + // if (debug()) nodep->dumpTree(cout, " InitOut: "); nodep->didWidth(true); nodep->doingWidth(false); } @@ -1546,8 +1619,10 @@ private: if (nodep->didWidth()) return; if (!nodep->varp()) { if (m_paramsOnly && VN_IS(nodep, VarXRef)) { - checkConstantOrReplace(nodep, "Parameter-resolved constants must not use dotted references: " - +nodep->prettyNameQ()); VL_DANGLING(nodep); + checkConstantOrReplace( + nodep, "Parameter-resolved constants must not use dotted references: " + + nodep->prettyNameQ()); + VL_DANGLING(nodep); return; } else { nodep->v3fatalSrc("Unlinked varref"); @@ -1557,28 +1632,27 @@ private: // Var hasn't been widthed, so make it so. userIterate(nodep->varp(), NULL); } - //if (debug()>=9) { nodep->dumpTree(cout, " VRin "); nodep->varp()->dumpTree(cout, " forvar "); } + // if (debug()>=9) { nodep->dumpTree(cout, " VRin "); + // nodep->varp()->dumpTree(cout, " forvar "); } // Note genvar's are also entered as integers nodep->dtypeFrom(nodep->varp()); if (VN_IS(nodep->backp(), NodeAssign) && nodep->lvalue()) { // On LHS UASSERT_OBJ(nodep->dtypep(), nodep, "LHS var should be dtype completed"); } - //if (debug()>=9) nodep->dumpTree(cout, " VRout "); + // if (debug() >= 9) nodep->dumpTree(cout, " VRout "); if (nodep->lvalue() && nodep->varp()->direction() == VDirection::CONSTREF) { - nodep->v3error("Assigning to const ref variable: "<prettyNameQ()); - } - else if (nodep->lvalue() && nodep->varp()->isConst() - && !m_paramsOnly - && !m_initialp) { // Too loose, but need to allow our generated first assignment - // // Move this to a property of the AstInitial block - nodep->v3error("Assigning to const variable: "<prettyNameQ()); + nodep->v3error("Assigning to const ref variable: " << nodep->prettyNameQ()); + } else if (nodep->lvalue() && nodep->varp()->isConst() && !m_paramsOnly && !m_initialp) { + // Too loose, but need to allow our generated first assignment + // Move this to a property of the AstInitial block + nodep->v3error("Assigning to const variable: " << nodep->prettyNameQ()); } nodep->didWidth(true); } virtual void visit(AstEnumDType* nodep) VL_OVERRIDE { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed - UINFO(5," ENUMDTYPE "<childDTypep()) nodep->refDTypep(moveChildDTypeEdit(nodep)); nodep->refDTypep(iterateEditDTypep(nodep, nodep->subDTypep())); nodep->dtypep(nodep); @@ -1586,14 +1660,16 @@ private: // Assign widths userIterateAndNext(nodep->itemsp(), WidthVP(nodep->dtypep(), BOTH).p()); // Assign missing values - V3Number num (nodep, nodep->width(), 0); - V3Number one (nodep, nodep->width(), 1); - std::map inits; - for (AstEnumItem* itemp = nodep->itemsp(); - itemp; itemp = VN_CAST(itemp->nextp(), EnumItem)) { + V3Number num(nodep, nodep->width(), 0); + V3Number one(nodep, nodep->width(), 1); + std::map inits; + for (AstEnumItem* itemp = nodep->itemsp(); itemp; + itemp = VN_CAST(itemp->nextp(), EnumItem)) { if (itemp->valuep()) { - if (debug()>=9) { UINFO(0,"EnumInit "<valuep()->dumpTree(cout, "-EnumInit: "); } + if (debug() >= 9) { + UINFO(0, "EnumInit " << itemp << endl); + itemp->valuep()->dumpTree(cout, "-EnumInit: "); + } V3Const::constifyParamsEdit(itemp->valuep()); // itemp may change if (!VN_IS(itemp->valuep(), Const)) { itemp->valuep()->v3error("Enum value isn't a constant"); @@ -1606,7 +1682,8 @@ private: if (num.isEqZero() && itemp != nodep->itemsp()) itemp->v3error("Enum value illegally wrapped around (IEEE 1800-2017 6.19)"); if (num.isFourState()) - itemp->v3error("Enum value that is unassigned cannot follow value with X/Zs (IEEE 1800-2017 6.19)"); + itemp->v3error("Enum value that is unassigned cannot follow value with X/Zs " + "(IEEE 1800-2017 6.19)"); if (!nodep->dtypep()->basicp() && !nodep->dtypep()->basicp()->keyword().isIntNumeric()) { itemp->v3error("Enum names without values only allowed on numeric types"); @@ -1618,16 +1695,17 @@ private: AstConst* constp = VN_CAST(itemp->valuep(), Const); if (constp->num().isFourState() && nodep->dtypep()->basicp() && !nodep->dtypep()->basicp()->isFourstate()) - itemp->v3error("Enum value with X/Zs cannot be assigned to non-fourstate type (IEEE 1800-2017 6.19)"); + itemp->v3error("Enum value with X/Zs cannot be assigned to non-fourstate type " + "(IEEE 1800-2017 6.19)"); num.opAssign(constp->num()); // Look for duplicates if (inits.find(num) != inits.end()) { // IEEE says illegal AstNode* otherp = inits.find(num)->second; - itemp->v3error("Overlapping enumeration value: "<prettyNameQ()<warnContextPrimary()<warnOther() - <<"... Location of original declaration\n" - <warnContextSecondary()); + itemp->v3error("Overlapping enumeration value: " + << itemp->prettyNameQ() << endl + << itemp->warnContextPrimary() << endl + << otherp->warnOther() << "... Location of original declaration\n" + << otherp->warnContextSecondary()); } else { inits.insert(make_pair(num, itemp)); } @@ -1635,7 +1713,7 @@ private: } } virtual void visit(AstEnumItem* nodep) VL_OVERRIDE { - UINFO(5," ENUMITEM "<dtypep(); UASSERT_OBJ(vdtypep, nodep, "ENUMITEM not under ENUM"); nodep->dtypep(vdtypep); @@ -1644,7 +1722,8 @@ private: userIterateAndNext(nodep->valuep(), WidthVP(CONTEXT, PRELIM).p()); // Minwidth does not come from value, as spec says set based on parent // and if we keep minwidth we'll consider it unsized which is incorrect - iterateCheck(nodep, "Enum value", nodep->valuep(), CONTEXT, FINAL, nodep->dtypep(), EXTEND_EXP); + iterateCheck(nodep, "Enum value", nodep->valuep(), CONTEXT, FINAL, nodep->dtypep(), + EXTEND_EXP); } } virtual void visit(AstEnumItemRef* nodep) VL_OVERRIDE { @@ -1652,7 +1731,7 @@ private: // We need to do the whole enum en-mass AstNode* enump = nodep->itemp(); UASSERT_OBJ(enump, nodep, "EnumItemRef not linked"); - for (; enump; enump=enump->backp()) { + for (; enump; enump = enump->backp()) { if (VN_IS(enump, EnumDType)) break; } UASSERT_OBJ(enump, nodep, "EnumItemRef can't deref back to an Enum"); @@ -1660,7 +1739,7 @@ private: } nodep->dtypeFrom(nodep->itemp()); } - virtual void visit(AstInitItem* nodep) VL_OVERRIDE { + virtual void visit(AstInitItem* nodep) VL_OVERRIDE { // userIterateChildren(nodep, m_vup); } virtual void visit(AstInitArray* nodep) VL_OVERRIDE { @@ -1678,29 +1757,30 @@ private: } virtual void visit(AstInside* nodep) VL_OVERRIDE { userIterateAndNext(nodep->exprp(), WidthVP(CONTEXT, PRELIM).p()); - for (AstNode* nextip, *itemp = nodep->itemsp(); itemp; itemp=nextip) { + for (AstNode *nextip, *itemp = nodep->itemsp(); itemp; itemp = nextip) { nextip = itemp->nextp(); // Prelim may cause the node to get replaced VL_DO_DANGLING(userIterate(itemp, WidthVP(CONTEXT, PRELIM).p()), itemp); } // Take width as maximum across all items int width = nodep->exprp()->width(); int mwidth = nodep->exprp()->widthMin(); - for (AstNode* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()) { + for (AstNode* itemp = nodep->itemsp(); itemp; itemp = itemp->nextp()) { width = std::max(width, itemp->width()); mwidth = std::max(mwidth, itemp->widthMin()); } // Apply width AstNodeDType* subDTypep = nodep->findLogicDType(width, mwidth, nodep->exprp()->dtypep()->numeric()); - iterateCheck(nodep, "Inside expression", nodep->exprp(), CONTEXT, FINAL, subDTypep, EXTEND_EXP); - for (AstNode* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()) { + iterateCheck(nodep, "Inside expression", nodep->exprp(), CONTEXT, FINAL, subDTypep, + EXTEND_EXP); + for (AstNode* itemp = nodep->itemsp(); itemp; itemp = itemp->nextp()) { iterateCheck(nodep, "Inside Item", itemp, CONTEXT, FINAL, subDTypep, EXTEND_EXP); } nodep->dtypeSetLogicBool(); - if (debug()>=9) nodep->dumpTree(cout, "-inside-in: "); + if (debug() >= 9) nodep->dumpTree(cout, "-inside-in: "); // Now rip out the inside and replace with simple math AstNode* newp = NULL; - for (AstNode* nextip, *itemp = nodep->itemsp(); itemp; itemp=nextip) { + for (AstNode *nextip, *itemp = nodep->itemsp(); itemp; itemp = nextip) { nextip = itemp->nextp(); // Will be unlinking AstNode* inewp; if (AstInsideRange* irangep = VN_CAST(itemp, InsideRange)) { @@ -1708,16 +1788,19 @@ private: inewp = irangep->newAndFromInside(nodep->exprp(), irangep->lhsp()->unlinkFrBack(), irangep->rhsp()->unlinkFrBack()); } else { - inewp = new AstEqWild(itemp->fileline(), - nodep->exprp()->cloneTree(true), + inewp = new AstEqWild(itemp->fileline(), nodep->exprp()->cloneTree(true), itemp->unlinkFrBack()); } - if (newp) newp = new AstOr(nodep->fileline(), newp, inewp); - else newp = inewp; + if (newp) { + newp = new AstOr(nodep->fileline(), newp, inewp); + } else { + newp = inewp; + } } if (!newp) newp = new AstConst(nodep->fileline(), AstConst::LogicFalse()); - if (debug()>=9) newp->dumpTree(cout, "-inside-out: "); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); + if (debug() >= 9) newp->dumpTree(cout, "-inside-out: "); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); } virtual void visit(AstInsideRange* nodep) VL_OVERRIDE { // Just do each side; AstInside will rip these nodes out later @@ -1728,16 +1811,16 @@ private: virtual void visit(AstIfaceRefDType* nodep) VL_OVERRIDE { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed - UINFO(5," IFACEREF "<dtypep(nodep); nodep->widthForce(1, 1); // Not really relevant - UINFO(4,"dtWidthed "<didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed - UINFO(5," NODECLASS "<=9) nodep->dumpTree("-class-in--"); + UINFO(5, " NODECLASS " << nodep << endl); + // if (debug() >= 9) nodep->dumpTree("-class-in--"); if (!nodep->packed()) { nodep->v3warn(UNPACKED, "Unsupported: Unpacked struct/union"); if (!v3Global.opt.structsPacked()) { @@ -1753,9 +1836,9 @@ private: nodep->isFourstate(false); // MSB is first, so go backwards AstMemberDType* itemp; - for (itemp = nodep->membersp(); - itemp && itemp->nextp(); itemp=VN_CAST(itemp->nextp(), MemberDType)) ; - for (AstMemberDType* backip; itemp; itemp=backip) { + for (itemp = nodep->membersp(); itemp && itemp->nextp(); + itemp = VN_CAST(itemp->nextp(), MemberDType)) {} + for (AstMemberDType* backip; itemp; itemp = backip) { if (itemp->isFourstate()) nodep->isFourstate(true); backip = VN_CAST(itemp->backp(), MemberDType); itemp->lsb(lsb); @@ -1767,7 +1850,7 @@ private: } } nodep->widthForce(width, width); // Signing stays as-is, as parsed from declaration - //if (debug()>=9) nodep->dumpTree("-class-out-"); + // if (debug() >= 9) nodep->dumpTree("-class-out-"); } virtual void visit(AstClass* nodep) VL_OVERRIDE { if (nodep->didWidthAndSet()) return; @@ -1791,14 +1874,14 @@ private: nodep->widthFromSub(nodep->subDTypep()); } virtual void visit(AstMemberSel* nodep) VL_OVERRIDE { - UINFO(5," MEMBERSEL "<=9) nodep->dumpTree("-mbs-in: "); + UINFO(5, " MEMBERSEL " << nodep << endl); + if (debug() >= 9) nodep->dumpTree("-mbs-in: "); userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); - if (debug()>=9) nodep->dumpTree("-mbs-ic: "); + if (debug() >= 9) nodep->dumpTree("-mbs-ic: "); // Find the fromp dtype - should be a class if (!nodep->fromp()->dtypep()) nodep->fromp()->v3fatalSrc("Unlinked data type"); AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefToEnump(); - UINFO(9," from dt "<warnOther() << "... Location of found object\n" << foundp->warnContextSecondary()); } - } else if (VN_IS(fromDtp, EnumDType) - || VN_IS(fromDtp, AssocArrayDType) - || VN_IS(fromDtp, DynArrayDType) - || VN_IS(fromDtp, QueueDType) + } else if (VN_IS(fromDtp, EnumDType) // + || VN_IS(fromDtp, AssocArrayDType) // + || VN_IS(fromDtp, DynArrayDType) // + || VN_IS(fromDtp, QueueDType) // || VN_IS(fromDtp, BasicDType)) { // Method call on enum without following parenthesis, e.g. "ENUM.next" // Convert this into a method call, and let that visitor figure out what to do next @@ -1859,9 +1942,10 @@ private: classp = classp->extendsp() ? classp->extendsp()->classp() : NULL; } string suggest = speller.bestCandidateMsg(nodep->prettyName()); - nodep->v3error("Member "<prettyNameQ()<<" not found in class " - <prettyNameQ()<<"\n" - <<(suggest.empty() ? "" : nodep->fileline()->warnMore()+suggest)); + nodep->v3error( + "Member " << nodep->prettyNameQ() << " not found in class " + << first_classp->prettyNameQ() << "\n" + << (suggest.empty() ? "" : nodep->fileline()->warnMore() + suggest)); return NULL; // Caller handles error } bool memberSelStruct(AstMemberSel* nodep, AstNodeUOrStructDType* adtypep) { @@ -1879,7 +1963,8 @@ private: newp->didWidth(true); // Don't replace dtype with basic type UINFO(9, " MEMBERSEL -> " << newp << endl); UINFO(9, " dt-> " << newp->dtypep() << endl); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); // Should be able to treat it as a normal-ish nodesel - maybe. // The lhsp() will be strange until this stage; create the number here? } @@ -1897,44 +1982,36 @@ private: virtual void visit(AstMethodCall* nodep) VL_OVERRIDE { UINFO(5, " METHODCALL " << nodep << endl); if (nodep->didWidth()) return; - if (debug()>=9) nodep->dumpTree("-mts-in: "); + if (debug() >= 9) nodep->dumpTree("-mts-in: "); // Should check types the method requires, but at present we don't do much userIterate(nodep->fromp(), WidthVP(SELF, BOTH).p()); - for (AstArg* argp = VN_CAST(nodep->pinsp(), Arg); - argp; argp = VN_CAST(argp->nextp(), Arg)) { + for (AstArg* argp = VN_CAST(nodep->pinsp(), Arg); argp; + argp = VN_CAST(argp->nextp(), Arg)) { if (argp->exprp()) userIterate(argp->exprp(), WidthVP(SELF, BOTH).p()); } // Find the fromp dtype - should be a class - UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep, - "Unsized expression"); + UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep, "Unsized expression"); AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefToEnump(); AstBasicDType* basicp = fromDtp ? fromDtp->basicp() : NULL; - UINFO(9," from dt "<isString()) { + } else if (basicp && basicp->isString()) { methodCallString(nodep, basicp); - } - else { + } else { nodep->v3error("Unsupported: Member call on object '" - <fromp()->prettyTypeName() - <<"' which is a '"<fromp()->dtypep()->prettyTypeName()<<"'"); + << nodep->fromp()->prettyTypeName() << "' which is a '" + << nodep->fromp()->dtypep()->prettyTypeName() << "'"); } } void methodOkArguments(AstMethodCall* nodep, int minArg, int maxArg) { @@ -1945,19 +2022,20 @@ private: } bool ok = (narg >= minArg) && (narg <= maxArg); if (!ok) { - nodep->v3error("The "<prettyName() - <<" method does not match its requiring "<v3error("The " << narg << " arguments passed to ." << nodep->prettyName() + << " method does not match its requiring " << cvtToStr(minArg) + << (minArg == maxArg ? "" : " to " + cvtToStr(maxArg)) + << " arguments"); // Adjust to required argument counts, very bogus, but avoids core dump for (; narg < minArg; ++narg) { - nodep->addPinsp(new AstArg(nodep->fileline(), "", - new AstConst(nodep->fileline(), 0))); + nodep->addPinsp( + new AstArg(nodep->fileline(), "", new AstConst(nodep->fileline(), 0))); } for (; narg > maxArg; --narg) { AstNode* argp = nodep->pinsp(); while (argp->nextp()) argp = argp->nextp(); - argp->unlinkFrBack(); VL_DO_DANGLING(argp->deleteTree(), argp); + argp->unlinkFrBack(); + VL_DO_DANGLING(argp->deleteTree(), argp); } } } @@ -1966,8 +2044,8 @@ private: // Method call on enum without following parenthesis, e.g. "ENUM.next" // Convert this into a method call, and let that visitor figure out what to do next if (adtypep) {} - if (nodep->name() == "num" - || nodep->name() == "first" + if (nodep->name() == "num" // + || nodep->name() == "first" // || nodep->name() == "last") { // Constant value AstConst* newp = NULL; @@ -1978,33 +2056,42 @@ private: newp = new AstConst(nodep->fileline(), AstConst::Signed32(), items); } else if (nodep->name() == "first") { AstEnumItem* itemp = adtypep->itemsp(); - if (!itemp) newp = new AstConst(nodep->fileline(), AstConst::Signed32(), - 0); // Spec doesn't say what to do - else newp = VN_CAST(itemp->valuep()->cloneTree(false), Const); // A const + if (!itemp) { + newp = new AstConst(nodep->fileline(), AstConst::Signed32(), + 0); // Spec doesn't say what to do + } else { + newp = VN_CAST(itemp->valuep()->cloneTree(false), Const); // A const + } } else if (nodep->name() == "last") { AstEnumItem* itemp = adtypep->itemsp(); while (itemp && itemp->nextp()) itemp = VN_CAST(itemp->nextp(), EnumItem); - if (!itemp) newp = new AstConst(nodep->fileline(), AstConst::Signed32(), - 0); // Spec doesn't say what to do - else newp = VN_CAST(itemp->valuep()->cloneTree(false), Const); // A const + if (!itemp) { + newp = new AstConst(nodep->fileline(), AstConst::Signed32(), + 0); // Spec doesn't say what to do + } else { + newp = VN_CAST(itemp->valuep()->cloneTree(false), Const); // A const + } } UASSERT_OBJ(newp, nodep, "Enum method (perhaps enum item) not const"); newp->fileline(nodep->fileline()); // Use method's filename/line number to be clearer; // may have warning disables - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } else if (nodep->name() == "name" - || nodep->name() == "next" - || nodep->name() == "prev") { + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } else if (nodep->name() == "name" || nodep->name() == "next" || nodep->name() == "prev") { AstAttrType attrType; - if (nodep->name() == "name") attrType = AstAttrType::ENUM_NAME; - else if (nodep->name() == "next") attrType = AstAttrType::ENUM_NEXT; - else if (nodep->name() == "prev") attrType = AstAttrType::ENUM_PREV; - else nodep->v3fatalSrc("Bad case"); + if (nodep->name() == "name") { + attrType = AstAttrType::ENUM_NAME; + } else if (nodep->name() == "next") { + attrType = AstAttrType::ENUM_NEXT; + } else if (nodep->name() == "prev") { + attrType = AstAttrType::ENUM_PREV; + } else { + nodep->v3fatalSrc("Bad case"); + } if (nodep->name() == "name") { methodOkArguments(nodep, 0, 0); - } else if (nodep->pinsp() - && !(VN_IS(VN_CAST(nodep->pinsp(), Arg)->exprp(), Const))) { + } else if (nodep->pinsp() && !(VN_IS(VN_CAST(nodep->pinsp(), Arg)->exprp(), Const))) { nodep->pinsp()->v3fatalSrc("Unsupported: enum next/prev with non-const argument"); } else if (nodep->pinsp() && !(VN_IS(VN_CAST(nodep->pinsp(), Arg)->exprp(), Const) @@ -2013,11 +2100,12 @@ private: // Unroll of enumVar.next(k) to enumVar.next(1).next(k - 1) AstMethodCall* clonep = nodep->cloneTree(false); VN_CAST(VN_CAST(clonep->pinsp(), Arg)->exprp(), Const)->num().setLong(1); - uint32_t stepWidth = VN_CAST(VN_CAST(nodep->pinsp(), Arg)->exprp(), Const)->toUInt(); + uint32_t stepWidth + = VN_CAST(VN_CAST(nodep->pinsp(), Arg)->exprp(), Const)->toUInt(); AstConst* constp = new AstConst(nodep->fileline(), stepWidth - 1); AstArg* argp = new AstArg(nodep->fileline(), "", constp); - AstMethodCall* newp = new AstMethodCall(nodep->fileline(), clonep, - nodep->name(), argp); + AstMethodCall* newp + = new AstMethodCall(nodep->fileline(), clonep, nodep->name(), argp); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); return; @@ -2050,7 +2138,8 @@ private: // Select in case widths are // off due to msblen!=width new AstSel(nodep->fileline(), nodep->fromp()->unlinkFrBack(), 0, selwidth)); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } else { nodep->v3error("Unknown built-in enum method " << nodep->prettyNameQ()); } @@ -2060,20 +2149,18 @@ private: if (nodep->name() == "num" // function int num() || nodep->name() == "size") { methodOkArguments(nodep, 0, 0); - newp = new AstCMethodHard(nodep->fileline(), - nodep->fromp()->unlinkFrBack(), - "size", NULL); // So don't need num() + newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", + NULL); // So don't need num() newp->dtypeSetSigned32(); newp->didWidth(true); newp->protect(false); } else if (nodep->name() == "first" // function int first(ref index) - || nodep->name() == "last" - || nodep->name() == "next" + || nodep->name() == "last" // + || nodep->name() == "next" // || nodep->name() == "prev") { methodOkArguments(nodep, 1, 1); AstNode* index_exprp = methodCallAssocIndexExpr(nodep, adtypep); - newp = new AstCMethodHard(nodep->fileline(), - nodep->fromp()->unlinkFrBack(), + newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), nodep->name(), // first/last/next/prev index_exprp->unlinkFrBack()); newp->dtypeSetSigned32(); @@ -2083,9 +2170,8 @@ private: // IEEE really should have made this a "bit" return methodOkArguments(nodep, 1, 1); AstNode* index_exprp = methodCallAssocIndexExpr(nodep, adtypep); - newp = new AstCMethodHard(nodep->fileline(), - nodep->fromp()->unlinkFrBack(), - "exists", index_exprp->unlinkFrBack()); + newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "exists", + index_exprp->unlinkFrBack()); newp->dtypeSetSigned32(); newp->pure(true); newp->protect(false); @@ -2094,32 +2180,30 @@ private: methodOkArguments(nodep, 0, 1); methodCallLValue(nodep, nodep->fromp(), true); if (!nodep->pinsp()) { - newp = new AstCMethodHard(nodep->fileline(), - nodep->fromp()->unlinkFrBack(), + newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "clear", NULL); newp->protect(false); newp->makeStatement(); } else { AstNode* index_exprp = methodCallAssocIndexExpr(nodep, adtypep); - newp = new AstCMethodHard(nodep->fileline(), - nodep->fromp()->unlinkFrBack(), - "erase", - index_exprp->unlinkFrBack()); + newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), + "erase", index_exprp->unlinkFrBack()); newp->protect(false); newp->makeStatement(); } } else { - nodep->v3error("Unknown built-in associative array method "<prettyNameQ()); + nodep->v3error("Unknown built-in associative array method " << nodep->prettyNameQ()); } if (newp) { newp->didWidth(true); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } } AstNode* methodCallAssocIndexExpr(AstMethodCall* nodep, AstAssocArrayDType* adtypep) { AstNode* index_exprp = VN_CAST(nodep->pinsp(), Arg)->exprp(); - iterateCheck(nodep, "index", index_exprp, CONTEXT, FINAL, - adtypep->keyDTypep(), EXTEND_EXP); + iterateCheck(nodep, "index", index_exprp, CONTEXT, FINAL, adtypep->keyDTypep(), + EXTEND_EXP); VL_DANGLING(index_exprp); // May have been edited return VN_CAST(nodep->pinsp(), Arg)->exprp(); } @@ -2127,7 +2211,7 @@ private: AstNodeVarRef* varrefp = VN_CAST(childp, NodeVarRef); if (!varrefp) { nodep->v3error("Unsupported: Non-variable on LHS of built-in method '" - <prettyName()<<"'"); + << nodep->prettyName() << "'"); } else { if (lvalue) varrefp->lvalue(true); } @@ -2137,26 +2221,23 @@ private: if (nodep->name() == "at") { // Created internally for [] methodOkArguments(nodep, 1, 1); methodCallLValue(nodep, nodep->fromp(), true); - newp = new AstCMethodHard(nodep->fileline(), - nodep->fromp()->unlinkFrBack(), - "at", NULL); + newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "at", + NULL); newp->dtypeFrom(adtypep->subDTypep()); newp->protect(false); newp->didWidth(true); } else if (nodep->name() == "size") { methodOkArguments(nodep, 0, 0); - newp = new AstCMethodHard(nodep->fileline(), - nodep->fromp()->unlinkFrBack(), - "size", NULL); + newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", + NULL); newp->dtypeSetSigned32(); newp->didWidth(true); newp->protect(false); } else if (nodep->name() == "delete") { // function void delete() methodOkArguments(nodep, 0, 0); methodCallLValue(nodep, nodep->fromp(), true); - newp = new AstCMethodHard(nodep->fileline(), - nodep->fromp()->unlinkFrBack(), - "clear", NULL); + newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "clear", + NULL); newp->makeStatement(); } else { nodep->v3error("Unsupported/unknown built-in dynamic array method " @@ -2164,7 +2245,8 @@ private: } if (newp) { newp->didWidth(true); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } } void methodCallQueue(AstMethodCall* nodep, AstQueueDType* adtypep) { @@ -2172,18 +2254,16 @@ private: if (nodep->name() == "at") { // Created internally for [] methodOkArguments(nodep, 1, 1); methodCallLValue(nodep, nodep->fromp(), true); - newp = new AstCMethodHard(nodep->fileline(), - nodep->fromp()->unlinkFrBack(), - "at", NULL); + newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "at", + NULL); newp->dtypeFrom(adtypep->subDTypep()); newp->protect(false); newp->didWidth(true); } else if (nodep->name() == "num" // function int num() - || nodep->name() == "size") { + || nodep->name() == "size") { methodOkArguments(nodep, 0, 0); - newp = new AstCMethodHard(nodep->fileline(), - nodep->fromp()->unlinkFrBack(), - "size", NULL); + newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", + NULL); newp->dtypeSetSigned32(); newp->didWidth(true); newp->protect(false); @@ -2191,25 +2271,23 @@ private: methodOkArguments(nodep, 0, 1); methodCallLValue(nodep, nodep->fromp(), true); if (!nodep->pinsp()) { - newp = new AstCMethodHard(nodep->fileline(), - nodep->fromp()->unlinkFrBack(), + newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "clear", NULL); newp->protect(false); newp->makeStatement(); } else { AstNode* index_exprp = methodCallQueueIndexExpr(nodep); if (index_exprp->isZero()) { // delete(0) is a pop_front - newp = new AstCMethodHard(nodep->fileline(), - nodep->fromp()->unlinkFrBack(), + newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "pop_front", NULL); newp->dtypeFrom(adtypep->subDTypep()); newp->protect(false); newp->didWidth(true); newp->makeStatement(); } else { - nodep->v3error("Unsupported: Queue .delete(index) method, as is O(n) complexity and slow."); - newp = new AstCMethodHard(nodep->fileline(), - nodep->fromp()->unlinkFrBack(), + nodep->v3error("Unsupported: Queue .delete(index) method, as is O(n) " + "complexity and slow."); + newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "erase", index_exprp->unlinkFrBack()); newp->protect(false); newp->makeStatement(); @@ -2222,51 +2300,45 @@ private: AstArg* argp = VN_CAST(nodep->pinsp()->nextp(), Arg); iterateCheckTyped(nodep, "insert value", argp->exprp(), adtypep->subDTypep(), BOTH); if (index_exprp->isZero()) { // insert(0, ...) is a push_front - newp = new AstCMethodHard(nodep->fileline(), - nodep->fromp()->unlinkFrBack(), + newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "push_front", argp->exprp()->unlinkFrBack()); newp->protect(false); newp->makeStatement(); } else { - nodep->v3error("Unsupported: Queue .insert method, as is O(n) complexity and slow."); - newp = new AstCMethodHard(nodep->fileline(), - nodep->fromp()->unlinkFrBack(), - nodep->name(), - index_exprp->unlinkFrBack()); + nodep->v3error( + "Unsupported: Queue .insert method, as is O(n) complexity and slow."); + newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), + nodep->name(), index_exprp->unlinkFrBack()); newp->addPinsp(argp->exprp()->unlinkFrBack()); newp->protect(false); newp->makeStatement(); } - } else if (nodep->name() == "pop_front" - || nodep->name() == "pop_back") { + } else if (nodep->name() == "pop_front" || nodep->name() == "pop_back") { methodOkArguments(nodep, 0, 0); methodCallLValue(nodep, nodep->fromp(), true); - newp = new AstCMethodHard(nodep->fileline(), - nodep->fromp()->unlinkFrBack(), + newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), nodep->name(), NULL); newp->dtypeFrom(adtypep->subDTypep()); newp->protect(false); newp->didWidth(true); - if (!nodep->firstAbovep()) { - newp->makeStatement(); - } - } else if (nodep->name() == "push_back" - || nodep->name() == "push_front") { + if (!nodep->firstAbovep()) { newp->makeStatement(); } + } else if (nodep->name() == "push_back" || nodep->name() == "push_front") { methodOkArguments(nodep, 1, 1); methodCallLValue(nodep, nodep->fromp(), true); AstArg* argp = VN_CAST(nodep->pinsp(), Arg); iterateCheckTyped(nodep, "push value", argp->exprp(), adtypep->subDTypep(), BOTH); - newp = new AstCMethodHard(nodep->fileline(), - nodep->fromp()->unlinkFrBack(), + newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), nodep->name(), argp->exprp()->unlinkFrBack()); newp->protect(false); newp->makeStatement(); } else { - nodep->v3error("Unsupported/unknown built-in associative array method "<prettyNameQ()); + nodep->v3error("Unsupported/unknown built-in associative array method " + << nodep->prettyNameQ()); } if (newp) { newp->didWidth(true); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } } AstNode* methodCallQueueIndexExpr(AstMethodCall* nodep) { @@ -2308,9 +2380,13 @@ private: enum { UNKNOWN = 0, ARRAY_OR, ARRAY_AND, ARRAY_XOR } methodId; methodId = UNKNOWN; - if (nodep->name() == "or") methodId = ARRAY_OR; - else if (nodep->name() == "and") methodId = ARRAY_AND; - else if (nodep->name() == "xor") methodId = ARRAY_XOR; + if (nodep->name() == "or") { + methodId = ARRAY_OR; + } else if (nodep->name() == "and") { + methodId = ARRAY_AND; + } else if (nodep->name() == "xor") { + methodId = ARRAY_XOR; + } if (methodId) { methodOkArguments(nodep, 0, 0); @@ -2362,11 +2438,13 @@ private: } else if (nodep->name() == "tolower") { methodOkArguments(nodep, 0, 0); AstNode* newp = new AstToLowerN(nodep->fileline(), nodep->fromp()->unlinkFrBack()); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } else if (nodep->name() == "toupper") { methodOkArguments(nodep, 0, 0); AstNode* newp = new AstToUpperN(nodep->fileline(), nodep->fromp()->unlinkFrBack()); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } else if (nodep->name() == "compare" || nodep->name() == "icompare") { const bool ignoreCase = nodep->name()[0] == 'i'; methodOkArguments(nodep, 1, 1); @@ -2374,8 +2452,9 @@ private: AstNode* lhs = nodep->fromp()->unlinkFrBack(); AstNode* rhs = argp->exprp()->unlinkFrBack(); AstNode* newp = new AstCompareNN(nodep->fileline(), lhs, rhs, ignoreCase); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); - } else if (nodep->name() == "putc" ) { + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); + } else if (nodep->name() == "putc") { methodOkArguments(nodep, 2, 2); AstArg* arg0p = VN_CAST(nodep->pinsp(), Arg); AstArg* arg1p = VN_CAST(arg0p->nextp(), Arg); @@ -2386,14 +2465,16 @@ private: AstNode* newp = new AstAssign(nodep->fileline(), fromp, new AstPutcN(nodep->fileline(), varrefp, rhsp, thsp)); fromp->lvalue(true); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } else if (nodep->name() == "getc") { methodOkArguments(nodep, 1, 1); AstArg* arg0p = VN_CAST(nodep->pinsp(), Arg); AstNode* lhsp = nodep->fromp()->unlinkFrBack(); AstNode* rhsp = arg0p->exprp()->unlinkFrBack(); AstNode* newp = new AstGetcN(nodep->fileline(), lhsp, rhsp); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } else if (nodep->name() == "substr") { methodOkArguments(nodep, 2, 2); AstArg* arg0p = VN_CAST(nodep->pinsp(), Arg); @@ -2402,24 +2483,32 @@ private: AstNode* rhsp = arg0p->exprp()->unlinkFrBack(); AstNode* thsp = arg1p->exprp()->unlinkFrBack(); AstNode* newp = new AstSubstrN(nodep->fileline(), lhsp, rhsp, thsp); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); - } else if (nodep->name() == "atobin" - || nodep->name() == "atohex" - || nodep->name() == "atoi" - || nodep->name() == "atooct" + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); + } else if (nodep->name() == "atobin" || nodep->name() == "atohex" + || nodep->name() == "atoi" || nodep->name() == "atooct" || nodep->name() == "atoreal") { AstAtoN::FmtType fmt; - if (nodep->name() == "atobin") fmt = AstAtoN::ATOBIN; - else if (nodep->name() == "atohex") fmt = AstAtoN::ATOHEX; - else if (nodep->name() == "atoi") fmt = AstAtoN::ATOI; - else if (nodep->name() == "atooct") fmt = AstAtoN::ATOOCT; - else if (nodep->name() == "atoreal") fmt = AstAtoN::ATOREAL; - else { V3ERROR_NA; fmt = AstAtoN::ATOI; } // dummy assignment to suppress compiler warning + if (nodep->name() == "atobin") { + fmt = AstAtoN::ATOBIN; + } else if (nodep->name() == "atohex") { + fmt = AstAtoN::ATOHEX; + } else if (nodep->name() == "atoi") { + fmt = AstAtoN::ATOI; + } else if (nodep->name() == "atooct") { + fmt = AstAtoN::ATOOCT; + } else if (nodep->name() == "atoreal") { + fmt = AstAtoN::ATOREAL; + } else { + V3ERROR_NA; + fmt = AstAtoN::ATOI; + } // dummy assignment to suppress compiler warning methodOkArguments(nodep, 0, 0); AstNode* newp = new AstAtoN(nodep->fileline(), nodep->fromp()->unlinkFrBack(), fmt); - nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); } else { - nodep->v3error("Unknown built-in string method "<prettyNameQ()); + nodep->v3error("Unknown built-in string method " << nodep->prettyNameQ()); } } @@ -2465,13 +2554,15 @@ private: if (nodep->didWidthAndSet()) return; AstDynArrayDType* adtypep = VN_CAST(m_vup->dtypeNullp(), DynArrayDType); if (!adtypep) { // e.g. int a = new; - nodep->v3error("dynamic new() not expected in this context (data type must be dynamic array)"); + nodep->v3error( + "dynamic new() not expected in this context (data type must be dynamic array)"); return; } // The AstNodeAssign visitor will be soon be replacing this node, make sure it gets it if (!VN_IS(nodep->backp(), NodeAssign)) { if (adtypep) UINFO(1, "Got backp " << nodep->backp() << endl); - nodep->v3error("dynamic new() not expected in this context (expected under an assign)"); + nodep->v3error( + "dynamic new() not expected in this context (expected under an assign)"); return; } nodep->dtypep(adtypep); @@ -2486,8 +2577,9 @@ private: virtual void visit(AstPattern* nodep) VL_OVERRIDE { if (nodep->didWidthAndSet()) return; - UINFO(9,"PATTERN "<childDTypep()) nodep->dtypep(moveChildDTypeEdit(nodep)); // data_type '{ pattern } + UINFO(9, "PATTERN " << nodep << endl); + if (nodep->childDTypep()) + nodep->dtypep(moveChildDTypeEdit(nodep)); // data_type '{ pattern } if (!nodep->dtypep() && m_vup->dtypeNullp()) { // Get it from parent assignment/pin/etc nodep->dtypep(m_vup->dtypep()); } @@ -2495,28 +2587,28 @@ private: if (!dtypep) { nodep->v3error("Unsupported/Illegal: Assignment pattern" " member not underneath a supported construct: " - <backp()->prettyTypeName()); + << nodep->backp()->prettyTypeName()); return; } { dtypep = dtypep->skipRefp(); nodep->dtypep(dtypep); - UINFO(9," dtypep "<dtypep(dtypep); // Determine replication count, and replicate initial value as // widths need to be individually determined - for (AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember); - patp; patp = VN_CAST(patp->nextp(), PatMember)) { + for (AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember); patp; + patp = VN_CAST(patp->nextp(), PatMember)) { int times = visitPatMemberRep(patp); - for (int i=1; icloneTree(false); patp->addNextHere(newp); // This loop will see the new elements as part of nextp() } } // Convert any PatMember with multiple items to multiple PatMembers - for (AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember); - patp; patp = VN_CAST(patp->nextp(), PatMember)) { + for (AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember); patp; + patp = VN_CAST(patp->nextp(), PatMember)) { if (patp->lhssp()->nextp()) { // Can't just addNext, as would add to end of all members. // So detach, add next and reattach @@ -2534,8 +2626,8 @@ private: } } AstPatMember* defaultp = NULL; - for (AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember); - patp; patp = VN_CAST(patp->nextp(), PatMember)) { + for (AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember); patp; + patp = VN_CAST(patp->nextp(), PatMember)) { if (patp->isDefault()) { if (defaultp) nodep->v3error("Multiple '{ default: } clauses"); defaultp = patp; @@ -2547,16 +2639,14 @@ private: } if (AstNodeUOrStructDType* vdtypep = VN_CAST(dtypep, NodeUOrStructDType)) { VL_DO_DANGLING(patternUOrStruct(nodep, vdtypep, defaultp), nodep); - } - else if (AstNodeArrayDType* vdtypep = VN_CAST(dtypep, NodeArrayDType)) { + } else if (AstNodeArrayDType* vdtypep = VN_CAST(dtypep, NodeArrayDType)) { VL_DO_DANGLING(patternArray(nodep, vdtypep, defaultp), nodep); - } - else if (VN_IS(dtypep, BasicDType) - && VN_CAST(dtypep, BasicDType)->isRanged()) { + } else if (VN_IS(dtypep, BasicDType) && VN_CAST(dtypep, BasicDType)->isRanged()) { VL_DO_DANGLING(patternBasic(nodep, dtypep, defaultp), nodep); } else { - nodep->v3error("Unsupported: Assignment pattern applies against non struct/union data type: " - << dtypep->prettyDTypeNameQ()); + nodep->v3error( + "Unsupported: Assignment pattern applies against non struct/union data type: " + << dtypep->prettyDTypeNameQ()); } } } @@ -2566,36 +2656,40 @@ private: // which member each AstPatMember corresponds to before we can // determine the dtypep for that PatMember's value, and then // width the initial value appropriately. - typedef std::map PatMap; + typedef std::map PatMap; PatMap patmap; { AstMemberDType* memp = vdtypep->membersp(); AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember); - for (; memp || patp; ) { + for (; memp || patp;) { do { if (patp) { if (patp->keyp()) { if (AstText* textp = VN_CAST(patp->keyp(), Text)) { memp = vdtypep->findMember(textp->text()); if (!memp) { - patp->keyp()->v3error( - "Assignment pattern key '" - <text()<<"' not found as member"); + patp->keyp()->v3error("Assignment pattern key '" + << textp->text() + << "' not found as member"); break; } } else { patp->keyp()->v3error( "Assignment pattern key not supported/understood: " - <keyp()->prettyTypeName()); + << patp->keyp()->prettyTypeName()); } } } if (memp && !patp) { // Missing init elements, warn below - memp = NULL; patp = NULL; break; + memp = NULL; + patp = NULL; + break; } else if (!memp && patp) { patp->v3error("Assignment pattern contains too many elements"); - memp = NULL; patp = NULL; break; + memp = NULL; + patp = NULL; + break; } else { std::pair ret = patmap.insert(make_pair(memp, patp)); @@ -2611,8 +2705,8 @@ private: } } AstNode* newp = NULL; - for (AstMemberDType* memp = vdtypep->membersp(); - memp; memp = VN_CAST(memp->nextp(), MemberDType)) { + for (AstMemberDType* memp = vdtypep->membersp(); memp; + memp = VN_CAST(memp->nextp(), MemberDType)) { PatMap::iterator it = patmap.find(memp); AstPatMember* newpatp = NULL; AstPatMember* patp = NULL; @@ -2620,11 +2714,10 @@ private: if (defaultp) { newpatp = defaultp->cloneTree(false); patp = newpatp; - } - else { + } else { if (!VN_IS(vdtypep, UnionDType)) { nodep->v3error("Assignment pattern missed initializing elements: " - <prettyTypeName()); + << memp->prettyTypeName()); } } } else { @@ -2634,28 +2727,31 @@ private: // Determine initial values patp->dtypep(memp); AstNode* valuep = patternMemberValueIterate(patp); - if (!newp) newp = valuep; - else { + if (!newp) { + newp = valuep; + } else { AstConcat* concatp = new AstConcat(patp->fileline(), newp, valuep); newp = concatp; - newp->dtypeSetLogicSized( - concatp->lhsp()->width() + concatp->rhsp()->width(), - nodep->dtypep()->numeric()); + newp->dtypeSetLogicSized(concatp->lhsp()->width() + concatp->rhsp()->width(), + nodep->dtypep()->numeric()); } } if (newpatp) { VL_DO_DANGLING(pushDeletep(newpatp), newpatp); } } - if (newp) nodep->replaceWith(newp); - else nodep->v3error("Assignment pattern with no members"); + if (newp) { + nodep->replaceWith(newp); + } else { + nodep->v3error("Assignment pattern with no members"); + } VL_DO_DANGLING(pushDeletep(nodep), nodep); // Deletes defaultp also, if present } void patternArray(AstPattern* nodep, AstNodeArrayDType* vdtypep, AstPatMember* defaultp) { AstNodeArrayDType* arrayp = VN_CAST(vdtypep, NodeArrayDType); VNumRange range = arrayp->declRange(); PatVecMap patmap = patVectorMap(nodep, range); - UINFO(9,"ent "<=range.lo(); --ent) { + for (int ent = range.hi(); ent >= range.lo(); --ent) { AstPatMember* newpatp = NULL; AstPatMember* patp = NULL; PatVecMap::iterator it = patmap.find(ent); @@ -2663,10 +2759,8 @@ private: if (defaultp) { newpatp = defaultp->cloneTree(false); patp = newpatp; - } - else { - nodep->v3error("Assignment pattern missed initializing elements: " - <v3error("Assignment pattern missed initializing elements: " << ent); } } else { patp = it->second; @@ -2679,37 +2773,40 @@ private: AstNode* valuep = patternMemberValueIterate(patp); if (VN_IS(arrayp, UnpackArrayDType)) { if (!newp) { - AstInitArray* newap - = new AstInitArray(nodep->fileline(), arrayp, NULL); + AstInitArray* newap = new AstInitArray(nodep->fileline(), arrayp, NULL); newp = newap; } VN_CAST(newp, InitArray)->addIndexValuep(ent - range.lo(), valuep); } else { // Packed. Convert to concat for now. - if (!newp) newp = valuep; - else { + if (!newp) { + newp = valuep; + } else { AstConcat* concatp = new AstConcat(patp->fileline(), newp, valuep); newp = concatp; - newp->dtypeSetLogicSized( - concatp->lhsp()->width()+concatp->rhsp()->width(), - nodep->dtypep()->numeric()); + newp->dtypeSetLogicSized(concatp->lhsp()->width() + + concatp->rhsp()->width(), + nodep->dtypep()->numeric()); } } } if (newpatp) { VL_DO_DANGLING(pushDeletep(newpatp), newpatp); } } if (!patmap.empty()) nodep->v3error("Assignment pattern with too many elements"); - if (newp) nodep->replaceWith(newp); - else nodep->v3error("Assignment pattern with no members"); - //if (debug()>=9) newp->dumpTree("-apat-out: "); + if (newp) { + nodep->replaceWith(newp); + } else { + nodep->v3error("Assignment pattern with no members"); + } + // if (debug() >= 9) newp->dumpTree("-apat-out: "); VL_DO_DANGLING(pushDeletep(nodep), nodep); // Deletes defaultp also, if present } void patternBasic(AstPattern* nodep, AstNodeDType* vdtypep, AstPatMember* defaultp) { AstBasicDType* bdtypep = VN_CAST(vdtypep, BasicDType); VNumRange range = bdtypep->declRange(); PatVecMap patmap = patVectorMap(nodep, range); - UINFO(9,"ent "<=range.lo(); --ent) { + for (int ent = range.hi(); ent >= range.lo(); --ent) { AstPatMember* newpatp = NULL; AstPatMember* patp = NULL; PatVecMap::iterator it = patmap.find(ent); @@ -2717,10 +2814,8 @@ private: if (defaultp) { newpatp = defaultp->cloneTree(false); patp = newpatp; - } - else { - nodep->v3error("Assignment pattern missed initializing elements: " - <v3error("Assignment pattern missed initializing elements: " << ent); } } else { patp = it->second; @@ -2732,22 +2827,26 @@ private: patp->dtypep(vdtypep); AstNode* valuep = patternMemberValueIterate(patp); { // Packed. Convert to concat for now. - if (!newp) newp = valuep; + if (!newp) + newp = valuep; else { AstConcat* concatp = new AstConcat(patp->fileline(), newp, valuep); newp = concatp; - newp->dtypeSetLogicSized( - concatp->lhsp()->width()+concatp->rhsp()->width(), - nodep->dtypep()->numeric()); + newp->dtypeSetLogicSized(concatp->lhsp()->width() + + concatp->rhsp()->width(), + nodep->dtypep()->numeric()); } } } if (newpatp) { VL_DO_DANGLING(pushDeletep(newpatp), newpatp); } } if (!patmap.empty()) nodep->v3error("Assignment pattern with too many elements"); - if (newp) nodep->replaceWith(newp); - else nodep->v3error("Assignment pattern with no members"); - //if (debug()>=9) newp->dumpTree("-apat-out: "); + if (newp) { + nodep->replaceWith(newp); + } else { + nodep->v3error("Assignment pattern with no members"); + } + // if (debug() >= 9) newp->dumpTree("-apat-out: "); VL_DO_DANGLING(pushDeletep(nodep), nodep); // Deletes defaultp also, if present } AstNode* patternMemberValueIterate(AstPatMember* patp) { @@ -2770,7 +2869,7 @@ private: AstNodeDType* vdtypep = m_vup->dtypeNullp(); UASSERT_OBJ(vdtypep, nodep, "Pattern member type not assigned by AstPattern visitor"); nodep->dtypep(vdtypep); - UINFO(9," PATMEMBER "<lhssp()->nextp(), nodep, "PatMember value should be singular w/replicates removed"); // Need to propagate assignment type downwards, even on prelim @@ -2783,10 +2882,19 @@ private: iterateCheckSizedSelf(nodep, "LHS", nodep->repp(), SELF, BOTH); V3Const::constifyParamsEdit(nodep->repp()); // repp may change const AstConst* constp = VN_CAST(nodep->repp(), Const); - if (!constp) { nodep->v3error("Replication value isn't a constant."); times = 0; } - else times = constp->toUInt(); - if (times==0) { nodep->v3error("Pattern replication value of 0 is not legal."); times=1; } - nodep->repp()->unlinkFrBackWithNext()->deleteTree(); // Done with replicate before cloning + if (!constp) { + nodep->v3error("Replication value isn't a constant."); + times = 0; + } else { + times = constp->toUInt(); + } + if (times == 0) { + nodep->v3error("Pattern replication value of 0 is not legal."); + times = 1; + } + nodep->repp() + ->unlinkFrBackWithNext() + ->deleteTree(); // Done with replicate before cloning } return times; } @@ -2796,7 +2904,8 @@ private: iterateCheckBool(nodep, "Property", nodep->propp(), BOTH); userIterateAndNext(nodep->sensesp(), NULL); if (nodep->disablep()) { - iterateCheckBool(nodep, "Disable", nodep->disablep(), BOTH); // it's like an if() condition. + iterateCheckBool(nodep, "Disable", nodep->disablep(), + BOTH); // it's like an if() condition. } nodep->dtypeSetLogicBool(); } @@ -2811,10 +2920,11 @@ private: // Signed: Only if expr, and all items signed assertAtStatement(nodep); userIterateAndNext(nodep->exprp(), WidthVP(CONTEXT, PRELIM).p()); - for (AstCaseItem* nextip, *itemp = nodep->itemsp(); itemp; itemp=nextip) { - nextip = VN_CAST(itemp->nextp(), CaseItem); // Prelim may cause the node to get replaced + for (AstCaseItem *nextip, *itemp = nodep->itemsp(); itemp; itemp = nextip) { + nextip + = VN_CAST(itemp->nextp(), CaseItem); // Prelim may cause the node to get replaced if (!VN_IS(nodep, GenCase)) userIterateAndNext(itemp->bodysp(), NULL); - for (AstNode* nextcp, *condp = itemp->condsp(); condp; condp=nextcp) { + for (AstNode *nextcp, *condp = itemp->condsp(); condp; condp = nextcp) { nextcp = condp->nextp(); // Prelim may cause the node to get replaced VL_DO_DANGLING(userIterate(condp, WidthVP(CONTEXT, PRELIM).p()), condp); } @@ -2822,25 +2932,28 @@ private: // Take width as maximum across all items, if any is real whole thing is real AstNodeDType* subDTypep = nodep->exprp()->dtypep(); - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { - for (AstNode* condp = itemp->condsp(); condp; condp=condp->nextp()) { + for (AstCaseItem* itemp = nodep->itemsp(); itemp; + itemp = VN_CAST(itemp->nextp(), CaseItem)) { + for (AstNode* condp = itemp->condsp(); condp; condp = condp->nextp()) { if (condp->dtypep() != subDTypep) { if (condp->dtypep()->isDouble()) { subDTypep = nodep->findDoubleDType(); } else { - int width = std::max(subDTypep->width(), condp->width()); + int width = std::max(subDTypep->width(), condp->width()); int mwidth = std::max(subDTypep->widthMin(), condp->widthMin()); bool issigned = subDTypep->isSigned() && condp->isSigned(); - subDTypep = nodep->findLogicDType(width, mwidth, - AstNumeric::fromBool(issigned)); + subDTypep + = nodep->findLogicDType(width, mwidth, AstNumeric::fromBool(issigned)); } } } } // Apply width - iterateCheck(nodep, "Case expression", nodep->exprp(), CONTEXT, FINAL, subDTypep, EXTEND_LHS); - for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=VN_CAST(itemp->nextp(), CaseItem)) { - for (AstNode* nextcp, *condp = itemp->condsp(); condp; condp=nextcp) { + iterateCheck(nodep, "Case expression", nodep->exprp(), CONTEXT, FINAL, subDTypep, + EXTEND_LHS); + for (AstCaseItem* itemp = nodep->itemsp(); itemp; + itemp = VN_CAST(itemp->nextp(), CaseItem)) { + for (AstNode *nextcp, *condp = itemp->condsp(); condp; condp = nextcp) { nextcp = condp->nextp(); // Final may cause the node to get replaced iterateCheck(nodep, "Case Item", condp, CONTEXT, FINAL, subDTypep, EXTEND_LHS); } @@ -2849,10 +2962,10 @@ private: virtual void visit(AstNodeFor* nodep) VL_OVERRIDE { assertAtStatement(nodep); userIterateAndNext(nodep->initsp(), NULL); - iterateCheckBool(nodep, "For Test Condition", nodep->condp(), BOTH); // it's like an if() condition. + iterateCheckBool(nodep, "For Test Condition", nodep->condp(), + BOTH); // it's like an if() condition. if (!VN_IS(nodep, GenFor)) userIterateAndNext(nodep->bodysp(), NULL); userIterateAndNext(nodep->incsp(), NULL); - } virtual void visit(AstRepeat* nodep) VL_OVERRIDE { assertAtStatement(nodep); @@ -2862,19 +2975,20 @@ private: virtual void visit(AstWhile* nodep) VL_OVERRIDE { assertAtStatement(nodep); userIterateAndNext(nodep->precondsp(), NULL); - iterateCheckBool(nodep, "For Test Condition", nodep->condp(), BOTH); // it's like an if() condition. + iterateCheckBool(nodep, "For Test Condition", nodep->condp(), + BOTH); // it's like an if() condition. userIterateAndNext(nodep->bodysp(), NULL); userIterateAndNext(nodep->incsp(), NULL); } virtual void visit(AstNodeIf* nodep) VL_OVERRIDE { assertAtStatement(nodep); - //if (debug()) nodep->dumpTree(cout, " IfPre: "); + // if (debug()) nodep->dumpTree(cout, " IfPre: "); if (!VN_IS(nodep, GenIf)) { // for m_paramsOnly userIterateAndNext(nodep->ifsp(), NULL); userIterateAndNext(nodep->elsesp(), NULL); } iterateCheckBool(nodep, "If", nodep->condp(), BOTH); // it's like an if() condition. - //if (debug()) nodep->dumpTree(cout, " IfOut: "); + // if (debug()) nodep->dumpTree(cout, " IfOut: "); } virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { @@ -2886,22 +3000,22 @@ private: // handled in each visitor. // Then LHS sign-extends only if *RHS* is signed assertAtStatement(nodep); - //if (debug()) nodep->dumpTree(cout, " AssignPre: "); + // if (debug()) nodep->dumpTree(cout, " AssignPre: "); { - //if (debug()) nodep->dumpTree(cout, "- assin: "); + // if (debug()) nodep->dumpTree(cout, "- assin: "); userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); UASSERT_OBJ(nodep->lhsp()->dtypep(), nodep, "How can LHS be untyped?"); - UASSERT_OBJ(nodep->lhsp()->dtypep()->widthSized(), nodep, - "How can LHS be unsized?"); + UASSERT_OBJ(nodep->lhsp()->dtypep()->widthSized(), nodep, "How can LHS be unsized?"); nodep->dtypeFrom(nodep->lhsp()); // // AstPattern needs to know the proposed data type of the lhs, so pass on the prelim userIterateAndNext(nodep->rhsp(), WidthVP(nodep->dtypep(), PRELIM).p()); // - //if (debug()) nodep->dumpTree(cout, "- assign: "); - AstNodeDType* lhsDTypep = nodep->lhsp()->dtypep(); // Note we use rhsp for context determined + // if (debug()) nodep->dumpTree(cout, "- assign: "); + AstNodeDType* lhsDTypep + = nodep->lhsp()->dtypep(); // Note we use rhsp for context determined iterateCheckAssign(nodep, "Assign RHS", nodep->rhsp(), FINAL, lhsDTypep); - //if (debug()) nodep->dumpTree(cout, " AssignOut: "); + // if (debug()) nodep->dumpTree(cout, " AssignOut: "); } if (AstNewDynamic* dynp = VN_CAST(nodep->rhsp(), NewDynamic)) { UINFO(9, "= new[] -> .resize(): " << nodep); @@ -2928,18 +3042,18 @@ private: // Just let all arguments seek their natural sizes userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); // - UINFO(9," Display in "<text()<text() << endl); string newFormat; bool inPct = false; AstNode* argp = nodep->exprsp(); string txt = nodep->text(); string fmt; - for (string::const_iterator it = txt.begin(); it!=txt.end(); ++it) { + for (string::const_iterator it = txt.begin(); it != txt.end(); ++it) { char ch = *it; - if (!inPct && ch=='%') { + if (!inPct && ch == '%') { inPct = true; fmt = ch; - } else if (inPct && (isdigit(ch) || ch=='.' || ch=='-')) { + } else if (inPct && (isdigit(ch) || ch == '.' || ch == '-')) { fmt += ch; } else if (tolower(inPct)) { inPct = false; @@ -2954,8 +3068,7 @@ private: if (argp->isDouble()) { spliceCvtS(argp, true, 64); ch = '~'; - } - else if (argp->isSigned()) { // Convert it + } else if (argp->isSigned()) { // Convert it ch = '~'; } argp = nextp; @@ -2971,16 +3084,15 @@ private: } else if (basicp && basicp->isDouble()) { added = true; newFormat += "%g"; - } else if (VN_IS(dtypep, AssocArrayDType) - || VN_IS(dtypep, ClassRefDType) - || VN_IS(dtypep, DynArrayDType) + } else if (VN_IS(dtypep, AssocArrayDType) // + || VN_IS(dtypep, ClassRefDType) // + || VN_IS(dtypep, DynArrayDType) // || VN_IS(dtypep, QueueDType)) { added = true; newFormat += "%@"; AstNRelinker handle; argp->unlinkFrBack(&handle); - AstCMath* newp = new AstCMath( - nodep->fileline(), "VL_TO_STRING(", 0, true); + AstCMath* newp = new AstCMath(nodep->fileline(), "VL_TO_STRING(", 0, true); newp->addBodysp(argp); newp->addBodysp(new AstText(nodep->fileline(), ")")); newp->dtypeSetString(); @@ -2989,8 +3101,11 @@ private: handle.relink(newp); } else { added = true; - if (fmt == "%0") newFormat += "'h%0h"; // IEEE our choice - else newFormat += "%d"; + if (fmt == "%0") { + newFormat += "'h%0h"; // IEEE our choice + } else { + newFormat += "%d"; + } } if (argp) argp = argp->nextp(); break; @@ -3045,13 +3160,11 @@ private: } } nodep->text(newFormat); - UINFO(9," Display out "<text()<text() << endl); } virtual void visit(AstDisplay* nodep) VL_OVERRIDE { assertAtStatement(nodep); - if (nodep->filep()) { - iterateCheckFileDesc(nodep, nodep->filep(), BOTH); - } + if (nodep->filep()) iterateCheckFileDesc(nodep, nodep->filep(), BOTH); // Just let all arguments seek their natural sizes userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); } @@ -3062,18 +3175,10 @@ private: if (!m_paramsOnly) { V3Const::constifyParamsEdit(nodep->fmtp()); // fmtp may change switch (nodep->displayType()) { - case AstDisplayType::DT_INFO: - nodep->v3warn(USERINFO, nodep->fmtp()->text()); - break; - case AstDisplayType::DT_ERROR: - nodep->v3warn(USERERROR, nodep->fmtp()->text()); - break; - case AstDisplayType::DT_WARNING: - nodep->v3warn(USERWARN, nodep->fmtp()->text()); - break; - case AstDisplayType::DT_FATAL: - nodep->v3warn(USERFATAL, nodep->fmtp()->text()); - break; + case AstDisplayType::DT_INFO: nodep->v3warn(USERINFO, nodep->fmtp()->text()); break; + case AstDisplayType::DT_ERROR: nodep->v3warn(USERERROR, nodep->fmtp()->text()); break; + case AstDisplayType::DT_WARNING: nodep->v3warn(USERWARN, nodep->fmtp()->text()); break; + case AstDisplayType::DT_FATAL: nodep->v3warn(USERFATAL, nodep->fmtp()->text()); break; default: UASSERT_OBJ(false, nodep, "Unexpected elaboration display type"); } VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); @@ -3111,9 +3216,7 @@ private: } virtual void visit(AstFFlush* nodep) VL_OVERRIDE { assertAtStatement(nodep); - if (nodep->filep()) { - iterateCheckFileDesc(nodep, nodep->filep(), BOTH); - } + if (nodep->filep()) iterateCheckFileDesc(nodep, nodep->filep(), BOTH); } virtual void visit(AstFRewind* nodep) VL_OVERRIDE { iterateCheckFileDesc(nodep, nodep->filep(), BOTH); @@ -3214,10 +3317,11 @@ private: << nodep->verilogKwd() << " into other than unpacked or associative array"); } - if (subp && (!subp->skipRefp()->basicp() - || !subp->skipRefp()->basicp()->keyword().isIntNumeric())) { + if (subp + && (!subp->skipRefp()->basicp() + || !subp->skipRefp()->basicp()->keyword().isIntNumeric())) { nodep->memp()->v3error("Unsupported: " << nodep->verilogKwd() - << " array values must be integral"); + << " array values must be integral"); } userIterateAndNext(nodep->lsbp(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->msbp(), WidthVP(SELF, BOTH).p()); @@ -3250,7 +3354,7 @@ private: iterateCheckBool(nodep, "Property", nodep->propp(), BOTH); // it's like an if() condition. } virtual void visit(AstPin* nodep) VL_OVERRIDE { - //if (debug()) nodep->dumpTree(cout, "- PinPre: "); + // if (debug()) nodep->dumpTree(cout, "- PinPre: "); // TOP LEVEL NODE if (nodep->modVarp() && nodep->modVarp()->isGParam()) { // Widthing handled as special init() case @@ -3275,84 +3379,89 @@ private: if (conDTypep == pinDTypep // If match, we're golden || similarDTypeRecurse(conDTypep, pinDTypep)) { userIterateAndNext(nodep->exprp(), WidthVP(subDTypep, FINAL).p()); - } - else if (m_cellRangep) { + } else if (m_cellRangep) { int numInsts = m_cellRangep->elementsConst(); if (conwidth == pinwidth) { // Arrayed instants: widths match so connect to each instance subDTypep = conDTypep; // = same expr dtype - } else if (conwidth == numInsts*pinwidth) { + } else if (conwidth == numInsts * pinwidth) { // Arrayed instants: one bit for each of the instants (each // assign is 1 pinwidth wide) subDTypep = conDTypep; // = same expr dtype (but numInst*pin_dtype) } else { // Must be a error according to spec // (Because we need to know if to connect to one or all instants) - nodep->v3error(ucfirst(nodep->prettyOperatorName())<<" as part of a module instance array" - <<" requires "<exprp()->prettyTypeName() - <<" generates "<v3error(ucfirst(nodep->prettyOperatorName()) + << " as part of a module instance array" + << " requires " << pinwidth << " or " << pinwidth * numInsts + << " bits, but connection's " + << nodep->exprp()->prettyTypeName() << " generates " << conwidth + << " bits."); subDTypep = conDTypep; // = same expr dtype } userIterateAndNext(nodep->exprp(), WidthVP(subDTypep, FINAL).p()); } else { if (nodep->modVarp()->direction() == VDirection::REF) { - nodep->v3error("Ref connection "<modVarp()->prettyNameQ() - <<" requires matching types;" - <<" ref requires "<prettyDTypeNameQ() - <<" data type but connection is " - <prettyDTypeNameQ()<<" data type."<v3error("Ref connection " + << nodep->modVarp()->prettyNameQ() + << " requires matching types;" + << " ref requires " << pinDTypep->prettyDTypeNameQ() + << " data type but connection is " + << conDTypep->prettyDTypeNameQ() << " data type." << endl); } else if (nodep->modVarp()->isTristate()) { if (pinwidth != conwidth) { - nodep->v3error("Unsupported: "<prettyOperatorName()) - <<" to inout signal requires "<exprp()->prettyTypeName() - <<" generates "<v3error("Unsupported: " << ucfirst(nodep->prettyOperatorName()) + << " to inout signal requires " << pinwidth + << " bits, but connection's " + << nodep->exprp()->prettyTypeName() + << " generates " << conwidth << " bits."); // otherwise would need some mess to force both sides to proper size } } // Check if an interface is connected to a non-interface and vice versa AstNodeDType* modDTypep = nodep->modVarp()->dtypep(); AstNodeDType* exprDTypep = nodep->exprp()->dtypep(); - if ((VN_IS(modDTypep, IfaceRefDType) && !VN_IS(exprDTypep, IfaceRefDType)) || - (VN_IS(exprDTypep, IfaceRefDType) && !VN_IS(modDTypep, IfaceRefDType))) { - nodep->v3error("Illegal "<prettyOperatorName()<<"," - <<" mismatch between port which is" - <<(VN_CAST(modDTypep, IfaceRefDType)?"":" not") - <<" an interface," - <<" and expression which is" - <<(VN_CAST(exprDTypep, IfaceRefDType)?"":" not") - <<" an interface."); + if ((VN_IS(modDTypep, IfaceRefDType) && !VN_IS(exprDTypep, IfaceRefDType)) + || (VN_IS(exprDTypep, IfaceRefDType) && !VN_IS(modDTypep, IfaceRefDType))) { + nodep->v3error("Illegal " << nodep->prettyOperatorName() << "," + << " mismatch between port which is" + << (VN_CAST(modDTypep, IfaceRefDType) ? "" : " not") + << " an interface," + << " and expression which is" + << (VN_CAST(exprDTypep, IfaceRefDType) ? "" : " not") + << " an interface."); } // TODO Simple dtype checking, should be a more general check AstNodeArrayDType* exprArrayp = VN_CAST(exprDTypep->skipRefp(), UnpackArrayDType); - AstNodeArrayDType* modArrayp = VN_CAST(modDTypep->skipRefp(), UnpackArrayDType); + AstNodeArrayDType* modArrayp = VN_CAST(modDTypep->skipRefp(), UnpackArrayDType); if (exprArrayp && modArrayp && VN_IS(exprArrayp->subDTypep()->skipRefp(), IfaceRefDType) && exprArrayp->declRange().elements() != modArrayp->declRange().elements()) { int exprSize = exprArrayp->declRange().elements(); int modSize = modArrayp->declRange().elements(); - nodep->v3error("Illegal "<prettyOperatorName()<<"," - <<" mismatch between port which is an interface array of size " - <skipRefp()<skipRefp()<v3error("Illegal " + << nodep->prettyOperatorName() << "," + << " mismatch between port which is an interface array of size " + << modSize << "," + << " and expression which is an interface array of size " + << exprSize << "."); + UINFO(1, " Related lo: " << modDTypep->skipRefp() << endl); + UINFO(1, " Related hi: " << exprDTypep->skipRefp() << endl); } else if ((exprArrayp && !modArrayp && pinwidth != conwidth) || (!exprArrayp && modArrayp && pinwidth != conwidth)) { - nodep->v3error("Illegal "<prettyOperatorName()<<"," - <<" mismatch between port which is"<<(modArrayp?"":" not")<<" an array," - <<" and expression which is"<<(exprArrayp?"":" not")<<" an array."); - UINFO(1," Related lo: "<skipRefp()<skipRefp()<v3error("Illegal " << nodep->prettyOperatorName() << "," + << " mismatch between port which is" + << (modArrayp ? "" : " not") << " an array," + << " and expression which is" + << (exprArrayp ? "" : " not") << " an array."); + UINFO(1, " Related lo: " << modDTypep->skipRefp() << endl); + UINFO(1, " Related hi: " << exprDTypep->skipRefp() << endl); } iterateCheckAssign(nodep, "pin connection", nodep->exprp(), FINAL, subDTypep); } } - //if (debug()) nodep->dumpTree(cout, "- PinOut: "); + // if (debug()) nodep->dumpTree(cout, "- PinOut: "); } virtual void visit(AstCell* nodep) VL_OVERRIDE { if (!m_paramsOnly) { @@ -3360,8 +3469,8 @@ private: // We've resolved parameters and hit a module that we couldn't resolve. It's // finally time to report it. // Note only here in V3Width as this is first visitor after V3Dead. - nodep->modNameFileline() - ->v3error("Cannot find file containing module: '"<modName()<<"'"); + nodep->modNameFileline()->v3error("Cannot find file containing module: '" + << nodep->modName() << "'"); v3Global.opt.filePathLookedMsg(nodep->modNameFileline(), nodep->modName()); } if (nodep->rangep()) { @@ -3386,12 +3495,10 @@ private: if (conwidth == 1 && pinwidth > 1) { // Multiple connections AstNodeDType* subDTypep = nodep->findLogicDType(1, 1, conDTypep->numeric()); userIterateAndNext(nodep->exprp(), WidthVP(subDTypep, FINAL).p()); - AstNode* newp = new AstReplicate(nodep->fileline(), - nodep->exprp()->unlinkFrBack(), + AstNode* newp = new AstReplicate(nodep->fileline(), nodep->exprp()->unlinkFrBack(), numInsts); nodep->replaceWith(newp); - } - else { + } else { // Eliminating so pass down all of vup userIterateAndNext(nodep->exprp(), m_vup); nodep->replaceWith(nodep->exprp()->unlinkFrBack()); @@ -3409,7 +3516,8 @@ private: return; } // Function hasn't been widthed, so make it so. - nodep->doingWidth(true); // Would use user1 etc, but V3Width called from too many places to spend a user + // Would use user1 etc, but V3Width called from too many places to spend a user + nodep->doingWidth(true); m_ftaskp = nodep; userIterateChildren(nodep, NULL); if (nodep->isConstructor()) { @@ -3424,10 +3532,9 @@ private: nodep->doingWidth(false); m_funcp = NULL; m_ftaskp = NULL; - if (nodep->dpiImport() - && !nodep->dpiOpenParent() - && markHasOpenArray(nodep)) { - nodep->dpiOpenParentInc(); // Mark so V3Task will wait for a child to build calling func + if (nodep->dpiImport() && !nodep->dpiOpenParent() && markHasOpenArray(nodep)) { + nodep->dpiOpenParentInc(); // Mark so V3Task will wait for a child to build calling + // func } } virtual void visit(AstReturn* nodep) VL_OVERRIDE { @@ -3451,7 +3558,7 @@ private: virtual void visit(AstFuncRef* nodep) VL_OVERRIDE { visit(VN_CAST(nodep, NodeFTaskRef)); nodep->dtypeFrom(nodep->taskp()); - //if (debug()) nodep->dumpTree(cout, " FuncOut: "); + // if (debug()) nodep->dumpTree(cout, " FuncOut: "); } void processFTaskRefArgs(AstNodeFTaskRef* nodep) { // For arguments, is assignment-like context; see IEEE rules in AstNodeAssign @@ -3500,8 +3607,7 @@ private: // Connection list is now incorrect (has extra args in it). goto reloop; // so exit early; next loop will correct it } // - else if (portp->basicp() - && portp->basicp()->keyword() == AstBasicDTypeKwd::STRING + else if (portp->basicp() && portp->basicp()->keyword() == AstBasicDTypeKwd::STRING && !VN_IS(pinp, CvtPackString) && !VN_IS(pinp, SFormatF) // Already generates a string && !(VN_IS(pinp, VarRef) @@ -3601,15 +3707,15 @@ private: // Default virtual void visit(AstNodeMath* nodep) VL_OVERRIDE { if (!nodep->didWidth()) { - nodep->v3fatalSrc("Visit function missing? Widthed function missing for math node: " - <v3fatalSrc( + "Visit function missing? Widthed function missing for math node: " << nodep); } userIterateChildren(nodep, NULL); } virtual void visit(AstNode* nodep) VL_OVERRIDE { // Default: Just iterate UASSERT_OBJ(!m_vup, nodep, - "Visit function missing? Widthed expectation for this node: "<rhsp(), WidthVP(CONTEXT, PRELIM).p()); if (nodep->lhsp()->isDouble() || nodep->rhsp()->isDouble()) { if (!realok) nodep->v3error("Real not allowed as operand to in ?== operator"); - if (AstNodeBiop* newp = replaceWithDVersion(nodep)) { VL_DANGLING(nodep); + if (AstNodeBiop* newp = replaceWithDVersion(nodep)) { + VL_DANGLING(nodep); nodep = newp; // Process new node instead iterateCheckReal(nodep, "LHS", nodep->lhsp(), FINAL); iterateCheckReal(nodep, "RHS", nodep->rhsp(), FINAL); } } else if (nodep->lhsp()->isString() || nodep->rhsp()->isString()) { - if (AstNodeBiop* newp = replaceWithNVersion(nodep)) { VL_DANGLING(nodep); + if (AstNodeBiop* newp = replaceWithNVersion(nodep)) { + VL_DANGLING(nodep); nodep = newp; // Process new node instead iterateCheckString(nodep, "LHS", nodep->lhsp(), FINAL); iterateCheckString(nodep, "RHS", nodep->rhsp(), FINAL); } } else { bool signedFl = nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned(); - if (AstNodeBiop* newp = replaceWithUOrSVersion(nodep, signedFl)) { VL_DANGLING(nodep); + if (AstNodeBiop* newp = replaceWithUOrSVersion(nodep, signedFl)) { + VL_DANGLING(nodep); nodep = newp; // Process new node instead } - int width = std::max(nodep->lhsp()->width(), nodep->rhsp()->width()); + int width = std::max(nodep->lhsp()->width(), nodep->rhsp()->width()); int ewidth = std::max(nodep->lhsp()->widthMin(), nodep->rhsp()->widthMin()); - AstNodeDType* subDTypep = nodep->findLogicDType(width, ewidth, - AstNumeric::fromBool(signedFl)); + AstNodeDType* subDTypep + = nodep->findLogicDType(width, ewidth, AstNumeric::fromBool(signedFl)); bool warnOn = true; if (!signedFl && width == 32) { // Waive on unsigned < or <= if RHS is narrower, since can't give wrong answer @@ -3825,7 +3934,8 @@ private: } if (real_ok && nodep->lhsp()->isDouble()) { spliceCvtD(nodep->lhsp()); - if (AstNodeUniop* newp = replaceWithDVersion(nodep)) { VL_DANGLING(nodep); + if (AstNodeUniop* newp = replaceWithDVersion(nodep)) { + VL_DANGLING(nodep); nodep = newp; // Process new node instead iterateCheckReal(nodep, "LHS", nodep->lhsp(), BOTH); nodep->dtypeSetDouble(); @@ -3835,9 +3945,7 @@ private: // Note there aren't yet uniops that need version changes // So no need to call replaceWithUOrSVersion(nodep, nodep->isSigned()) } - if (m_vup->prelim()) { - nodep->dtypeFrom(nodep->lhsp()); - } + if (m_vup->prelim()) nodep->dtypeFrom(nodep->lhsp()); if (m_vup->final()) { AstNodeDType* expDTypep = m_vup->dtypeOverridep(nodep->dtypep()); nodep->dtypep(expDTypep); // Propagate expression type to negation @@ -3866,7 +3974,7 @@ private: } } - void visit_shift(AstNodeBiop* nodep) { + void visit_shift(AstNodeBiop* nodep) { // CALLER: ShiftL, ShiftR, ShiftRS // Widths: Output width from lhs, rhs<33 bits // Signed: Output signed iff LHS signed; unary operator @@ -3874,10 +3982,11 @@ private: // RHS is self-determined. RHS is always treated as unsigned, has no effect on result. iterate_shift_prelim(nodep); nodep->dtypeChgSigned(nodep->lhsp()->isSigned()); - AstNodeBiop* newp = iterate_shift_final(nodep); VL_DANGLING(nodep); + AstNodeBiop* newp = iterate_shift_final(nodep); + VL_DANGLING(nodep); if (newp) {} // Ununused } - void iterate_shift_prelim(AstNodeBiop* nodep) { + void iterate_shift_prelim(AstNodeBiop* nodep) { // Shifts // See IEEE-2012 11.4.10 and Table 11-21. // RHS is self-determined. RHS is always treated as unsigned, has no effect on result. @@ -3888,7 +3997,7 @@ private: nodep->dtypeFrom(nodep->lhsp()); } } - AstNodeBiop* iterate_shift_final(AstNodeBiop* nodep) { + AstNodeBiop* iterate_shift_final(AstNodeBiop* nodep) { // Nodep maybe edited if (m_vup->final()) { AstNodeDType* expDTypep = m_vup->dtypeOverridep(nodep->dtypep()); @@ -3896,19 +4005,22 @@ private: nodep->dtypeFrom(expDTypep); // ShiftRS converts to ShiftR, but not vice-versa if (VN_IS(nodep, ShiftRS)) { - if (AstNodeBiop* newp = replaceWithUOrSVersion(nodep, nodep->isSigned())) { VL_DANGLING(nodep); + if (AstNodeBiop* newp = replaceWithUOrSVersion(nodep, nodep->isSigned())) { + VL_DANGLING(nodep); nodep = newp; // Process new node instead } } bool warnOn = true; // No warning if "X = 1'b1<lhsp()->isOne() && VN_IS(nodep->backp(), NodeAssign)) warnOn = false; - iterateCheck(nodep, "LHS", nodep->lhsp(), CONTEXT, FINAL, subDTypep, EXTEND_EXP, warnOn); - if (nodep->rhsp()->width()>32) { + iterateCheck(nodep, "LHS", nodep->lhsp(), CONTEXT, FINAL, subDTypep, EXTEND_EXP, + warnOn); + if (nodep->rhsp()->width() > 32) { AstConst* shiftp = VN_CAST(nodep->rhsp(), Const); if (shiftp && shiftp->num().mostSetBitP1() <= 32) { // If (number)<<96'h1, then make it into (number)<<32'h1 - V3Number num (shiftp, 32, 0); num.opAssign(shiftp->num()); + V3Number num(shiftp, 32, 0); + num.opAssign(shiftp->num()); AstNode* shiftrhsp = nodep->rhsp(); nodep->rhsp()->replaceWith(new AstConst(shiftrhsp->fileline(), num)); VL_DO_DANGLING(shiftrhsp->deleteTree(), shiftrhsp); @@ -3934,7 +4046,7 @@ private: userIterateAndNext(nodep->rhsp(), WidthVP(CONTEXT, PRELIM).p()); checkCvtUS(nodep->lhsp()); checkCvtUS(nodep->rhsp()); - int width = std::max(nodep->lhsp()->width(), nodep->rhsp()->width()); + int width = std::max(nodep->lhsp()->width(), nodep->rhsp()->width()); int mwidth = std::max(nodep->lhsp()->widthMin(), nodep->rhsp()->widthMin()); bool expSigned = (nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned()); nodep->dtypeChgWidthSigned(width, mwidth, AstNumeric::fromBool(expSigned)); @@ -3961,7 +4073,7 @@ private: // because the rhs could be larger, and we need to have proper editing to get the widths // to be the same for our operations. // - //if (debug()>=9) { UINFO(0,"-rus "<dumpTree(cout, "-rusin-"); } + // if (debug() >= 9) { UINFO(0,"-rus "<dumpTree(cout, "-rusin-"); } if (m_vup->prelim()) { // First stage evaluation // Determine expression widths only relying on what's in the subops userIterateAndNext(nodep->lhsp(), WidthVP(CONTEXT, PRELIM).p()); @@ -3973,7 +4085,8 @@ private: if (nodep->lhsp()->isDouble() || nodep->rhsp()->isDouble()) { spliceCvtD(nodep->lhsp()); spliceCvtD(nodep->rhsp()); - if (AstNodeBiop* newp = replaceWithDVersion(nodep)) { VL_DANGLING(nodep); + if (AstNodeBiop* newp = replaceWithDVersion(nodep)) { + VL_DANGLING(nodep); nodep = newp; // Process new node instead } nodep->dtypeSetDouble(); @@ -3981,7 +4094,7 @@ private: iterateCheckReal(nodep, "RHS", nodep->rhsp(), FINAL); return; } else { - int width = std::max(nodep->lhsp()->width(), nodep->rhsp()->width()); + int width = std::max(nodep->lhsp()->width(), nodep->rhsp()->width()); int mwidth = std::max(nodep->lhsp()->widthMin(), nodep->rhsp()->widthMin()); bool expSigned = (nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned()); nodep->dtypeChgWidthSigned(width, mwidth, AstNumeric::fromBool(expSigned)); @@ -3993,25 +4106,30 @@ private: AstNodeDType* subDTypep = expDTypep; nodep->dtypeFrom(expDTypep); // We don't use LHS && RHS -- unspecified language corner, see t_math_signed5 test - //bool expSigned = (nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned()); - if (AstNodeBiop* newp = replaceWithUOrSVersion(nodep, expDTypep->isSigned())) { VL_DANGLING(nodep); + // bool expSigned = (nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned()); + if (AstNodeBiop* newp = replaceWithUOrSVersion(nodep, expDTypep->isSigned())) { + VL_DANGLING(nodep); nodep = newp; // Process new node instead } // Some warning suppressions - bool lhsWarn = true; bool rhsWarn = true; + bool lhsWarn = true; + bool rhsWarn = true; if (VN_IS(nodep, Add) || VN_IS(nodep, Sub)) { - if (subDTypep->widthMin() == (nodep->lhsp()->widthMin()+1)) lhsWarn = false; // Warn if user wants extra bit from carry - if (subDTypep->widthMin() == (nodep->rhsp()->widthMin()+1)) rhsWarn = false; // Warn if user wants extra bit from carry + // Warn if user wants extra bit from carry + if (subDTypep->widthMin() == (nodep->lhsp()->widthMin() + 1)) lhsWarn = false; + if (subDTypep->widthMin() == (nodep->rhsp()->widthMin() + 1)) rhsWarn = false; } else if (VN_IS(nodep, Mul) || VN_IS(nodep, MulS)) { if (subDTypep->widthMin() >= (nodep->lhsp()->widthMin())) lhsWarn = false; if (subDTypep->widthMin() >= (nodep->rhsp()->widthMin())) rhsWarn = false; } // Final call, so make sure children check their sizes // Error report and change sizes for suboperands of this node. - iterateCheck(nodep, "LHS", nodep->lhsp(), CONTEXT, FINAL, subDTypep, EXTEND_EXP, lhsWarn); - iterateCheck(nodep, "RHS", nodep->rhsp(), CONTEXT, FINAL, subDTypep, EXTEND_EXP, rhsWarn); + iterateCheck(nodep, "LHS", nodep->lhsp(), CONTEXT, FINAL, subDTypep, EXTEND_EXP, + lhsWarn); + iterateCheck(nodep, "RHS", nodep->rhsp(), CONTEXT, FINAL, subDTypep, EXTEND_EXP, + rhsWarn); } - //if (debug()>=9) nodep->dumpTree(cout, "-rusou-"); + // if (debug() >= 9) nodep->dumpTree(cout, "-rusou-"); } void visit_real_add_sub(AstNodeBiop* nodep) { // CALLER: AddD, MulD, ... @@ -4038,17 +4156,17 @@ private: int expWidth = expDTypep->width(); int expWidthMin = expDTypep->widthMin(); UASSERT_OBJ(nodep->dtypep(), nodep, - "Under node "<prettyTypeName() - <<" has no dtype?? Missing Visitor func?"); + "Under node " << nodep->prettyTypeName() + << " has no dtype?? Missing Visitor func?"); UASSERT_OBJ(nodep->width() != 0, nodep, - "Under node "<prettyTypeName() - <<" has no expected width?? Missing Visitor func?"); + "Under node " << nodep->prettyTypeName() + << " has no expected width?? Missing Visitor func?"); UASSERT_OBJ(expWidth != 0, nodep, - "Node "<prettyTypeName() - <<" has no expected width?? Missing Visitor func?"); - if (expWidthMin==0) expWidthMin = expWidth; + "Node " << nodep->prettyTypeName() + << " has no expected width?? Missing Visitor func?"); + if (expWidthMin == 0) expWidthMin = expWidth; if (nodep->dtypep()->width() == expWidth) return false; - if (nodep->dtypep()->widthSized() && nodep->width() != expWidthMin) return true; + if (nodep->dtypep()->widthSized() && nodep->width() != expWidthMin) return true; if (!nodep->dtypep()->widthSized() && nodep->widthMin() > expWidthMin) return true; return false; } @@ -4064,20 +4182,21 @@ private: // node, while the output dtype is the *expected* sign. // It is reasonable to have sign extension with unsigned output, // for example $unsigned(a)+$signed(b), the SIGNED(B) will be unsigned dtype out - UINFO(4," widthExtend_(r="<width(); if (constp && !constp->num().isNegative()) { // Save later constant propagation work, just right-size it. - V3Number num (nodep, expWidth); + V3Number num(nodep, expWidth); num.opAssign(constp->num()); num.isSigned(false); AstNode* newp = new AstConst(nodep->fileline(), num); constp->replaceWith(newp); - VL_DO_DANGLING(pushDeletep(constp), constp); VL_DANGLING(nodep); + VL_DO_DANGLING(pushDeletep(constp), constp); + VL_DANGLING(nodep); nodep = newp; - } else if (expWidthwidth()) { + } else if (expWidth < nodep->width()) { // Trunc - Extract AstNRelinker linker; nodep->unlinkFrBack(&linker); @@ -4092,13 +4211,13 @@ private: bool doSigned = false; switch (extendRule) { case EXTEND_ZERO: doSigned = false; break; - case EXTEND_EXP: doSigned = nodep->isSigned() && expDTypep->isSigned(); break; - case EXTEND_LHS: doSigned = nodep->isSigned(); break; + case EXTEND_EXP: doSigned = nodep->isSigned() && expDTypep->isSigned(); break; + case EXTEND_LHS: doSigned = nodep->isSigned(); break; default: nodep->v3fatalSrc("bad case"); } - AstNode* newp = (doSigned - ? static_cast(new AstExtendS(nodep->fileline(), nodep)) - : static_cast(new AstExtend (nodep->fileline(), nodep))); + AstNode* newp + = (doSigned ? static_cast(new AstExtendS(nodep->fileline(), nodep)) + : static_cast(new AstExtend(nodep->fileline(), nodep))); linker.relink(newp); nodep = newp; } @@ -4110,7 +4229,7 @@ private: nodep = newp; } nodep->dtypeFrom(expDTypep); - UINFO(4," _new: "<num()); num.isSigned(expSigned); AstNode* newp = new AstConst(nodep->fileline(), num); constp->replaceWith(newp); - VL_DO_DANGLING(constp->deleteTree(), constp); VL_DANGLING(nodep); + VL_DO_DANGLING(constp->deleteTree(), constp); + VL_DANGLING(nodep); nodep = newp; } else { AstNRelinker linker; @@ -4138,20 +4258,20 @@ private: nodep = newp; } nodep->dtypeChgWidthSigned(expWidth, expWidth, AstNumeric::fromBool(expSigned)); - UINFO(4," _new: "<num().autoExtend() && !constp->num().sized() && constp->width()==1) { + if (constp->num().autoExtend() && !constp->num().sized() && constp->width() == 1) { // Make it the proper size. Careful of proper extension of 0's/1's - V3Number num (constp, expWidth); + V3Number num(constp, expWidth); num.opRepl(constp->num(), expWidth); // {width{'1}} AstNode* newp = new AstConst(constp->fileline(), num); // Spec says always unsigned with proper width - if (debug()>4) constp->dumpTree(cout, " fixAutoExtend_old: "); - if (debug()>4) newp->dumpTree(cout, " _new: "); + if (debug() > 4) constp->dumpTree(cout, " fixAutoExtend_old: "); + if (debug() > 4) newp->dumpTree(cout, " _new: "); constp->replaceWith(newp); VL_DO_DANGLING(constp->deleteTree(), constp); // Tell caller the new constp, and that we changed it. @@ -4163,13 +4283,13 @@ private: // Make it the proper size. Careful of proper extension of 0's/1's && expWidth > 32 && constp->num().isMsbXZ()) { constp->v3warn(WIDTH, "Unsized constant being X/Z extended to " - <prettyName()); - V3Number num (constp, expWidth); + << expWidth << " bits: " << constp->prettyName()); + V3Number num(constp, expWidth); num.opExtendXZ(constp->num(), constp->width()); AstNode* newp = new AstConst(constp->fileline(), num); // Spec says always unsigned with proper width - if (debug()>4) constp->dumpTree(cout, " fixUnszExtend_old: "); - if (debug()>4) newp->dumpTree(cout, " _new: "); + if (debug() > 4) constp->dumpTree(cout, " fixUnszExtend_old: "); + if (debug() > 4) newp->dumpTree(cout, " _new: "); constp->replaceWith(newp); VL_DO_DANGLING(constp->deleteTree(), constp); // Tell caller the new constp, and that we changed it. @@ -4188,7 +4308,8 @@ private: // underp may change as a result of replacement underp = userIterateSubtreeReturnEdits(underp, WidthVP(SELF, PRELIM).p()); AstNodeDType* expDTypep = underp->findUInt32DType(); - underp = iterateCheck(nodep, "file_descriptor", underp, SELF, FINAL, expDTypep, EXTEND_EXP); + underp + = iterateCheck(nodep, "file_descriptor", underp, SELF, FINAL, expDTypep, EXTEND_EXP); if (underp) {} // cppcheck } void iterateCheckSigned32(AstNode* nodep, const char* side, AstNode* underp, Stage stage) { @@ -4239,31 +4360,33 @@ private: } if (underp) {} // cppcheck } - void iterateCheckSizedSelf(AstNode* nodep, const char* side, AstNode* underp, - Determ determ, Stage stage) { + void iterateCheckSizedSelf(AstNode* nodep, const char* side, AstNode* underp, Determ determ, + Stage stage) { // Coerce child to any sized-number data type; child is self-determined // i.e. isolated from expected type. // e.g. nodep=CONCAT, underp=lhs in CONCAT(lhs,rhs) UASSERT_OBJ(determ == SELF, nodep, "Bad call"); UASSERT_OBJ(stage == FINAL || stage == BOTH, nodep, "Bad call"); // underp may change as a result of replacement - if (stage & PRELIM) underp = userIterateSubtreeReturnEdits(underp, WidthVP(SELF, PRELIM).p()); + if (stage & PRELIM) { + underp = userIterateSubtreeReturnEdits(underp, WidthVP(SELF, PRELIM).p()); + } underp = checkCvtUS(underp); AstNodeDType* expDTypep = underp->dtypep(); underp = iterateCheck(nodep, side, underp, SELF, FINAL, expDTypep, EXTEND_EXP); if (underp) {} // cppcheck } - void iterateCheckAssign(AstNode* nodep, const char* side, - AstNode* rhsp, Stage stage, AstNodeDType* lhsDTypep) { + void iterateCheckAssign(AstNode* nodep, const char* side, AstNode* rhsp, Stage stage, + AstNodeDType* lhsDTypep) { // Check using assignment-like context rules - //if (debug()) nodep->dumpTree(cout, "-checkass: "); + // if (debug()) nodep->dumpTree(cout, "-checkass: "); UASSERT_OBJ(stage == FINAL, nodep, "Bad width call"); // We iterate and size the RHS based on the result of RHS evaluation - bool lhsStream = (VN_IS(nodep, NodeAssign) - && VN_IS(VN_CAST(nodep, NodeAssign)->lhsp(), NodeStream)); + bool lhsStream + = (VN_IS(nodep, NodeAssign) && VN_IS(VN_CAST(nodep, NodeAssign)->lhsp(), NodeStream)); rhsp = iterateCheck(nodep, side, rhsp, ASSIGN, FINAL, lhsDTypep, lhsStream ? EXTEND_OFF : EXTEND_LHS); - //if (debug()) nodep->dumpTree(cout, "-checkout: "); + // if (debug()) nodep->dumpTree(cout, "-checkout: "); if (rhsp) {} // cppcheck } @@ -4281,39 +4404,42 @@ private: // // For DOUBLE under a logical op, add implied test against zero, never a warning if (underp && underp->isDouble()) { - UINFO(6," spliceCvtCmpD0: "<unlinkFrBack(&linker); - AstNode* newp = new AstNeqD( - nodep->fileline(), underp, - new AstConst(nodep->fileline(), AstConst::RealDouble(), 0.0)); + AstNode* newp + = new AstNeqD(nodep->fileline(), underp, + new AstConst(nodep->fileline(), AstConst::RealDouble(), 0.0)); linker.relink(newp); } else if (!underp->dtypep()->basicp()) { - nodep->v3error("Logical Operator "<prettyTypeName() - <<" expects a non-complex data type on the "<v3error("Logical Operator " << nodep->prettyTypeName() + << " expects a non-complex data type on the " + << side << "."); underp->replaceWith(new AstConst(nodep->fileline(), AstConst::LogicFalse())); VL_DO_DANGLING(pushDeletep(underp), underp); } else { bool bad = widthBad(underp, nodep->findLogicBoolDType()); if (bad) { { // if (warnOn), but not needed here - if (debug()>4) nodep->backp()->dumpTree(cout, " back: "); - nodep->v3warn(WIDTH, "Logical Operator "<prettyTypeName() - <<" expects 1 bit on the "<prettyTypeName()<<" generates "<width() - <<(underp->width()!=underp->widthMin() - ?" or "+cvtToStr(underp->widthMin()):"") - <<" bits."); + if (debug() > 4) nodep->backp()->dumpTree(cout, " back: "); + nodep->v3warn(WIDTH, "Logical Operator " + << nodep->prettyTypeName() << " expects 1 bit on the " + << side << ", but " << side << "'s " + << underp->prettyTypeName() << " generates " + << underp->width() + << (underp->width() != underp->widthMin() + ? " or " + cvtToStr(underp->widthMin()) + : "") + << " bits."); } - VL_DO_DANGLING(fixWidthReduce(underp), underp); //Changed + VL_DO_DANGLING(fixWidthReduce(underp), underp); // Changed } } } - AstNode* iterateCheck(AstNode* nodep, const char* side, AstNode* underp, - Determ determ, Stage stage, AstNodeDType* expDTypep, - ExtendRule extendRule, - bool warnOn=true) { + AstNode* iterateCheck(AstNode* nodep, const char* side, AstNode* underp, Determ determ, + Stage stage, AstNodeDType* expDTypep, ExtendRule extendRule, + bool warnOn = true) { // Perform data type check on underp, which is underneath nodep used for error reporting // Returns the new underp // Conversion to/from doubles and integers are before iterating. @@ -4323,8 +4449,8 @@ private: if (VN_IS(underp, NodeDType)) { // Note the node itself, not node's data type // Must be near top of these checks as underp->dtypep() will look normal underp->v3error(ucfirst(nodep->prettyOperatorName()) - <<" expected non-datatype "<name()<<"' is a datatype."); + << " expected non-datatype " << side << " but '" << underp->name() + << "' is a datatype."); } else if (expDTypep == underp->dtypep()) { // Perfect underp = userIterateSubtreeReturnEdits(underp, WidthVP(SELF, FINAL).p()); } else if (expDTypep->isDouble() && underp->isDouble()) { // Also good @@ -4357,7 +4483,7 @@ private: std::max(subDTypep->width(), underp->width()), std::max(subDTypep->widthMin(), underp->widthMin()), AstNumeric::fromBool(underp->isSigned())); - UINFO(9,"Assignment of opposite-signed RHS to LHS: "<dtypep(), IfaceRefDType)) { + } else if (!VN_IS(expDTypep, IfaceRefDType) + && VN_IS(underp->dtypep(), IfaceRefDType)) { underp->v3error(ucfirst(nodep->prettyOperatorName()) - <<" expected non-interface on "<name()<<"' is an interface."); - } - else { + << " expected non-interface on " << side << " but '" + << underp->name() << "' is an interface."); + } else { // Hope it just works out } } @@ -4382,23 +4506,23 @@ private: void widthCheckSized(AstNode* nodep, const char* side, AstNode* underp, // Node to be checked or have typecast added in front of - AstNodeDType* expDTypep, - ExtendRule extendRule, - bool warnOn=true) { + AstNodeDType* expDTypep, ExtendRule extendRule, bool warnOn = true) { // Issue warnings on sized number width mismatches, then do appropriate size extension // Generally iterateCheck is what is wanted instead of this - //UINFO(9,"wchk "<basicp(); AstBasicDType* underBasicp = underp->dtypep()->basicp(); if (expDTypep == underp->dtypep()) { return; // Same type must match - } else if (!expBasicp || expBasicp->isDouble() - || !underBasicp || underBasicp->isDouble()) { + } else if (!expBasicp || expBasicp->isDouble() || !underBasicp + || underBasicp->isDouble()) { // This is perhaps a v3fatalSrc as we should have checked the types // before calling widthCheck, but we may have missed a non-sized // check in earlier code, so might as well assume it is the users' // fault. - nodep->v3error(ucfirst(nodep->prettyOperatorName())<<" expected non-complex non-double "<v3error(ucfirst(nodep->prettyOperatorName()) + << " expected non-complex non-double " << side << " in width check"); #if VL_DEBUG nodep->v3fatalSrc("widthCheckSized should not be called on doubles/complex types"); #endif @@ -4406,10 +4530,9 @@ private: } else { int expWidth = expDTypep->width(); int expWidthMin = expDTypep->widthMin(); - if (expWidthMin==0) expWidthMin = expWidth; + if (expWidthMin == 0) expWidthMin = expWidth; bool bad = widthBad(underp, expDTypep); - if ((bad || underp->width() != expWidth) - && fixAutoExtend(underp/*ref*/, expWidth)) { + if ((bad || underp->width() != expWidth) && fixAutoExtend(underp /*ref*/, expWidth)) { underp = NULL; // Changes underp return; } @@ -4420,25 +4543,27 @@ private: // Maybe this should be a special warning? Not for now. warnOn = false; } - if ((VN_IS(nodep, Add) && underp->width()==1 && underp->isOne()) - || (VN_IS(nodep, Sub) && underp->width()==1 && underp->isOne() - && 0==strcmp(side, "RHS"))) { + if ((VN_IS(nodep, Add) && underp->width() == 1 && underp->isOne()) + || (VN_IS(nodep, Sub) && underp->width() == 1 && underp->isOne() + && 0 == strcmp(side, "RHS"))) { // "foo + 1'b1", or "foo - 1'b1" are very common, people assume // they extend correctly warnOn = false; } if (bad && warnOn) { - if (debug()>4) nodep->backp()->dumpTree(cout, " back: "); - nodep->v3warn(WIDTH, ucfirst(nodep->prettyOperatorName()) - <<" expects "<prettyTypeName()<<" generates "<width() - <<(underp->width()!=underp->widthMin() - ?" or "+cvtToStr(underp->widthMin()):"") - <<" bits."); + if (debug() > 4) nodep->backp()->dumpTree(cout, " back: "); + nodep->v3warn( + WIDTH, ucfirst(nodep->prettyOperatorName()) + << " expects " << expWidth + << (expWidth != expWidthMin ? " or " + cvtToStr(expWidthMin) : "") + << " bits on the " << side << ", but " << side << "'s " + << underp->prettyTypeName() << " generates " << underp->width() + << (underp->width() != underp->widthMin() + ? " or " + cvtToStr(underp->widthMin()) + : "") + << " bits."); } - if (bad || underp->width()!=expWidth) { + if (bad || underp->width() != expWidth) { // If we're in an NodeAssign, don't truncate the RHS if the LHS is // a NodeStream. The streaming operator changes the rules regarding // which bits to truncate. @@ -4447,7 +4572,7 @@ private: if (assignp && VN_IS(assignp->lhsp(), NodeStream)) { } else if (pinp && pinp->modVarp()->direction() != VDirection::INPUT) { // V3Inst::pinReconnectSimple must deal - UINFO(5,"pinInSizeMismatch: "<isDouble()) { nodep->v3error("Expected integral (non-" << nodep->dtypep()->prettyDTypeName() - << ") input to " << nodep->backp()->prettyTypeName()); + << ") input to " + << nodep->backp()->prettyTypeName()); nodep = spliceCvtS(nodep, true, 32); } return nodep; @@ -4471,7 +4597,7 @@ private: // For integer used in REAL context, convert to real // We don't warn here, "2.0 * 2" is common and reasonable if (nodep && !nodep->dtypep()->skipRefp()->isDouble()) { - UINFO(6," spliceCvtD: "<unlinkFrBack(&linker); AstNode* newp = new AstIToRD(nodep->fileline(), nodep); @@ -4510,9 +4636,8 @@ private: AstNode* spliceCvtString(AstNode* nodep) { // IEEE-2012 11.8.1: Signed: Type coercion creates signed // 11.8.2: Argument to convert is self-determined - if (nodep && !(nodep->dtypep()->basicp() - && nodep->dtypep()->basicp()->isString())) { - UINFO(6," spliceCvtString: "<dtypep()->basicp() && nodep->dtypep()->basicp()->isString())) { + UINFO(6, " spliceCvtString: " << nodep << endl); AstNRelinker linker; nodep->unlinkFrBack(&linker); AstNode* newp = new AstCvtPackString(nodep->fileline(), nodep); @@ -4525,20 +4650,18 @@ private: AstNodeBiop* replaceWithUOrSVersion(AstNodeBiop* nodep, bool signedFlavorNeeded) { // Given a signed/unsigned node type, create the opposite type // Return new node or NULL if nothing - if (signedFlavorNeeded == nodep->signedFlavor()) { - return NULL; - } + if (signedFlavorNeeded == nodep->signedFlavor()) return NULL; if (!nodep->dtypep()) nodep->dtypeFrom(nodep->lhsp()); // To simplify callers, some node types don't need to change switch (nodep->type()) { - case AstType::atEq: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; - case AstType::atNeq: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; + case AstType::atEq: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; + case AstType::atNeq: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; case AstType::atEqCase: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; case AstType::atNeqCase: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; case AstType::atEqWild: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; case AstType::atNeqWild: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; - case AstType::atAdd: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; - case AstType::atSub: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; + case AstType::atAdd: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; + case AstType::atSub: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; case AstType::atShiftL: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; default: break; } @@ -4547,27 +4670,27 @@ private: AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); AstNodeBiop* newp = NULL; switch (nodep->type()) { - case AstType::atGt: newp = new AstGtS (fl, lhsp, rhsp); break; - case AstType::atGtS: newp = new AstGt (fl, lhsp, rhsp); break; - case AstType::atGte: newp = new AstGteS (fl, lhsp, rhsp); break; - case AstType::atGteS: newp = new AstGte (fl, lhsp, rhsp); break; - case AstType::atLt: newp = new AstLtS (fl, lhsp, rhsp); break; - case AstType::atLtS: newp = new AstLt (fl, lhsp, rhsp); break; - case AstType::atLte: newp = new AstLteS (fl, lhsp, rhsp); break; - case AstType::atLteS: newp = new AstLte (fl, lhsp, rhsp); break; - case AstType::atDiv: newp = new AstDivS (fl, lhsp, rhsp); break; - case AstType::atDivS: newp = new AstDiv (fl, lhsp, rhsp); break; - case AstType::atModDiv: newp = new AstModDivS (fl, lhsp, rhsp); break; - case AstType::atModDivS: newp = new AstModDiv (fl, lhsp, rhsp); break; - case AstType::atMul: newp = new AstMulS (fl, lhsp, rhsp); break; - case AstType::atMulS: newp = new AstMul (fl, lhsp, rhsp); break; - case AstType::atShiftR: newp = new AstShiftRS (fl, lhsp, rhsp); break; - case AstType::atShiftRS: newp = new AstShiftR (fl, lhsp, rhsp); break; + case AstType::atGt: newp = new AstGtS(fl, lhsp, rhsp); break; + case AstType::atGtS: newp = new AstGt(fl, lhsp, rhsp); break; + case AstType::atGte: newp = new AstGteS(fl, lhsp, rhsp); break; + case AstType::atGteS: newp = new AstGte(fl, lhsp, rhsp); break; + case AstType::atLt: newp = new AstLtS(fl, lhsp, rhsp); break; + case AstType::atLtS: newp = new AstLt(fl, lhsp, rhsp); break; + case AstType::atLte: newp = new AstLteS(fl, lhsp, rhsp); break; + case AstType::atLteS: newp = new AstLte(fl, lhsp, rhsp); break; + case AstType::atDiv: newp = new AstDivS(fl, lhsp, rhsp); break; + case AstType::atDivS: newp = new AstDiv(fl, lhsp, rhsp); break; + case AstType::atModDiv: newp = new AstModDivS(fl, lhsp, rhsp); break; + case AstType::atModDivS: newp = new AstModDiv(fl, lhsp, rhsp); break; + case AstType::atMul: newp = new AstMulS(fl, lhsp, rhsp); break; + case AstType::atMulS: newp = new AstMul(fl, lhsp, rhsp); break; + case AstType::atShiftR: newp = new AstShiftRS(fl, lhsp, rhsp); break; + case AstType::atShiftRS: newp = new AstShiftR(fl, lhsp, rhsp); break; default: - nodep->v3fatalSrc("Node needs sign change, but bad case: "<v3fatalSrc("Node needs sign change, but bad case: " << nodep << endl); break; } - UINFO(6," ReplaceWithUOrSVersion: "<replaceWith(newp); newp->dtypeFrom(nodep); VL_DO_DANGLING(pushDeletep(nodep), nodep); @@ -4576,31 +4699,37 @@ private: AstNodeBiop* replaceWithDVersion(AstNodeBiop* nodep) { // Given a signed/unsigned node type, create the opposite type // Return new node or NULL if nothing - if (nodep->doubleFlavor()) { - return NULL; - } + if (nodep->doubleFlavor()) { return NULL; } FileLine* fl = nodep->fileline(); AstNode* lhsp = nodep->lhsp()->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); AstNodeBiop* newp = NULL; // No width change on output;... // All below have bool or double outputs switch (nodep->type()) { - case AstType::atAdd: newp = new AstAddD(fl, lhsp, rhsp); break; - case AstType::atSub: newp = new AstSubD(fl, lhsp, rhsp); break; - case AstType::atPow: newp = new AstPowD(fl, lhsp, rhsp); break; - case AstType::atEq: case AstType::atEqCase: newp = new AstEqD (fl, lhsp, rhsp); break; - case AstType::atNeq: case AstType::atNeqCase: newp = new AstNeqD(fl, lhsp, rhsp); break; - case AstType::atGt: case AstType::atGtS: newp = new AstGtD (fl, lhsp, rhsp); break; - case AstType::atGte: case AstType::atGteS: newp = new AstGteD(fl, lhsp, rhsp); break; - case AstType::atLt: case AstType::atLtS: newp = new AstLtD (fl, lhsp, rhsp); break; - case AstType::atLte: case AstType::atLteS: newp = new AstLteD(fl, lhsp, rhsp); break; - case AstType::atDiv: case AstType::atDivS: newp = new AstDivD(fl, lhsp, rhsp); break; - case AstType::atMul: case AstType::atMulS: newp = new AstMulD(fl, lhsp, rhsp); break; + case AstType::atAdd: newp = new AstAddD(fl, lhsp, rhsp); break; + case AstType::atSub: newp = new AstSubD(fl, lhsp, rhsp); break; + case AstType::atPow: newp = new AstPowD(fl, lhsp, rhsp); break; + case AstType::atEq: + case AstType::atEqCase: newp = new AstEqD(fl, lhsp, rhsp); break; + case AstType::atNeq: + case AstType::atNeqCase: newp = new AstNeqD(fl, lhsp, rhsp); break; + case AstType::atGt: + case AstType::atGtS: newp = new AstGtD(fl, lhsp, rhsp); break; + case AstType::atGte: + case AstType::atGteS: newp = new AstGteD(fl, lhsp, rhsp); break; + case AstType::atLt: + case AstType::atLtS: newp = new AstLtD(fl, lhsp, rhsp); break; + case AstType::atLte: + case AstType::atLteS: newp = new AstLteD(fl, lhsp, rhsp); break; + case AstType::atDiv: + case AstType::atDivS: newp = new AstDivD(fl, lhsp, rhsp); break; + case AstType::atMul: + case AstType::atMulS: newp = new AstMulD(fl, lhsp, rhsp); break; default: - nodep->v3fatalSrc("Node needs conversion to double, but bad case: "<v3fatalSrc("Node needs conversion to double, but bad case: " << nodep << endl); break; } - UINFO(6," ReplaceWithDVersion: "<replaceWith(newp); // No width change; the default created type (bool or double) is correct VL_DO_DANGLING(pushDeletep(nodep), nodep); @@ -4609,26 +4738,30 @@ private: AstNodeBiop* replaceWithNVersion(AstNodeBiop* nodep) { // Given a signed/unsigned node type, replace with string version // Return new node or NULL if nothing - if (nodep->stringFlavor()) { - return NULL; - } + if (nodep->stringFlavor()) return NULL; FileLine* fl = nodep->fileline(); AstNode* lhsp = nodep->lhsp()->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); AstNodeBiop* newp = NULL; // No width change on output;... // All below have bool or double outputs switch (nodep->type()) { - case AstType::atEq: case AstType::atEqCase: newp = new AstEqN (fl, lhsp, rhsp); break; - case AstType::atNeq: case AstType::atNeqCase: newp = new AstNeqN(fl, lhsp, rhsp); break; - case AstType::atGt: case AstType::atGtS: newp = new AstGtN (fl, lhsp, rhsp); break; - case AstType::atGte: case AstType::atGteS: newp = new AstGteN(fl, lhsp, rhsp); break; - case AstType::atLt: case AstType::atLtS: newp = new AstLtN (fl, lhsp, rhsp); break; - case AstType::atLte: case AstType::atLteS: newp = new AstLteN(fl, lhsp, rhsp); break; + case AstType::atEq: + case AstType::atEqCase: newp = new AstEqN(fl, lhsp, rhsp); break; + case AstType::atNeq: + case AstType::atNeqCase: newp = new AstNeqN(fl, lhsp, rhsp); break; + case AstType::atGt: + case AstType::atGtS: newp = new AstGtN(fl, lhsp, rhsp); break; + case AstType::atGte: + case AstType::atGteS: newp = new AstGteN(fl, lhsp, rhsp); break; + case AstType::atLt: + case AstType::atLtS: newp = new AstLtN(fl, lhsp, rhsp); break; + case AstType::atLte: + case AstType::atLteS: newp = new AstLteN(fl, lhsp, rhsp); break; default: - nodep->v3fatalSrc("Node needs conversion to string, but bad case: "<v3fatalSrc("Node needs conversion to string, but bad case: " << nodep << endl); break; } - UINFO(6," ReplaceWithNVersion: "<replaceWith(newp); // No width change; the default created type (bool or string) is correct VL_DO_DANGLING(pushDeletep(nodep), nodep); @@ -4637,19 +4770,17 @@ private: AstNodeUniop* replaceWithDVersion(AstNodeUniop* nodep) { // Given a signed/unsigned node type, create the opposite type // Return new node or NULL if nothing - if (nodep->doubleFlavor()) { - return NULL; - } + if (nodep->doubleFlavor()) return NULL; FileLine* fl = nodep->fileline(); AstNode* lhsp = nodep->lhsp()->unlinkFrBack(); AstNodeUniop* newp = NULL; switch (nodep->type()) { case AstType::atNegate: newp = new AstNegateD(fl, lhsp); break; default: - nodep->v3fatalSrc("Node needs conversion to double, but bad case: "<v3fatalSrc("Node needs conversion to double, but bad case: " << nodep << endl); break; } - UINFO(6," ReplaceWithDVersion: "<replaceWith(newp); newp->dtypeFrom(nodep); VL_DO_DANGLING(pushDeletep(nodep), nodep); @@ -4663,14 +4794,13 @@ private: // For string.itoa and similar, replace with SFormatF AstArg* argp = VN_CAST(nodep->pinsp(), Arg); if (!argp) { - nodep->v3error("Argument needed for string." - +nodep->prettyName()+" method"); + nodep->v3error("Argument needed for string." + nodep->prettyName() + " method"); return; } AstNodeVarRef* fromp = VN_CAST(nodep->fromp()->unlinkFrBack(), VarRef); - AstNode* newp = new AstAssign(nodep->fileline(), fromp, - new AstSFormatF(nodep->fileline(), format, false, - argp->exprp()->unlinkFrBack())); + AstNode* newp = new AstAssign( + nodep->fileline(), fromp, + new AstSFormatF(nodep->fileline(), format, false, argp->exprp()->unlinkFrBack())); fromp->lvalue(true); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); @@ -4683,7 +4813,7 @@ private: // DTypes at parse time get added as a e.g. childDType to some node types such as AstVars. // Move type to global scope, so removing/changing a variable won't lose the dtype. UASSERT_OBJ(dtnodep, nodep, "Caller should check for NULL before calling moveDTypeEdit"); - UINFO(9,"moveDTypeEdit "<unlinkFrBack(); // Make non-child v3Global.rootp()->typeTablep()->addTypesp(dtnodep); return dtnodep; @@ -4706,12 +4836,13 @@ private: return nodep; } - AstConst* dimensionValue(FileLine* fileline, AstNodeDType* nodep, AstAttrType attrType, int dim) { + AstConst* dimensionValue(FileLine* fileline, AstNodeDType* nodep, AstAttrType attrType, + int dim) { // Return the dimension value for the specified attribute and constant dimension AstNodeDType* dtypep = nodep->skipRefp(); VNumRange declRange; // ranged() set false for (int i = 1; i <= dim; ++i) { - //UINFO(9, " dim at "<declRange(); @@ -4732,7 +4863,7 @@ private: case AstAttrType::DIM_BITS: { int bits = 1; while (dtypep) { - //UINFO(9, " bits at "<declRange().elements(); dtypep = adtypep->subDTypep()->skipRefp(); @@ -4748,53 +4879,41 @@ private: } if (dim == 0) { val = 0; - } else if (dim == 1 && !declRange.ranged() && bits==1) { // $bits should be sane for non-arrays + } else if (dim == 1 && !declRange.ranged() + && bits == 1) { // $bits should be sane for non-arrays val = nodep->width(); } else { val = bits; } - break; } - case AstAttrType::DIM_HIGH: - val = !declRange.ranged() ? 0 : declRange.hi(); - break; - case AstAttrType::DIM_LEFT: - val = !declRange.ranged() ? 0 : declRange.left(); - break; - case AstAttrType::DIM_LOW: - val = !declRange.ranged() ? 0 : declRange.lo(); - break; - case AstAttrType::DIM_RIGHT: - val = !declRange.ranged() ? 0 : declRange.right(); break; + } + case AstAttrType::DIM_HIGH: val = !declRange.ranged() ? 0 : declRange.hi(); break; + case AstAttrType::DIM_LEFT: val = !declRange.ranged() ? 0 : declRange.left(); break; + case AstAttrType::DIM_LOW: val = !declRange.ranged() ? 0 : declRange.lo(); break; + case AstAttrType::DIM_RIGHT: val = !declRange.ranged() ? 0 : declRange.right(); break; case AstAttrType::DIM_INCREMENT: val = (declRange.ranged() && declRange.littleEndian()) ? -1 : 1; break; - case AstAttrType::DIM_SIZE: - val = !declRange.ranged() ? 0 : declRange.elements(); - break; - default: - nodep->v3fatalSrc("Missing DIM ATTR type case"); - break; + case AstAttrType::DIM_SIZE: val = !declRange.ranged() ? 0 : declRange.elements(); break; + default: nodep->v3fatalSrc("Missing DIM ATTR type case"); break; } if (!valp) valp = new AstConst(fileline, AstConst::Signed32(), val); - UINFO(9," $dimension "<isConst(true); varp->isStatic(true); @@ -4803,7 +4922,7 @@ private: v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(varp); // Element 0 is a non-index and has speced values initp->addValuep(dimensionValue(nodep->fileline(), nodep, attrType, 0)); - for (unsigned i=1; iaddValuep(dimensionValue(nodep->fileline(), nodep, attrType, i)); } userIterate(varp, NULL); // May have already done $unit so must do this var @@ -4813,26 +4932,22 @@ private: AstVar* enumVarp(AstEnumDType* nodep, AstAttrType attrType, uint32_t msbdim) { // Return a variable table which has specified dimension properties for this variable TableMap::iterator pos = m_tableMap.find(make_pair(nodep, attrType)); - if (pos != m_tableMap.end()) { - return pos->second; - } - UINFO(9, "Construct Venumtab attr="<second; + UINFO(9, "Construct Venumtab attr=" << attrType.ascii() << " max=" << msbdim << " for " + << nodep << endl); AstNodeDType* basep; if (attrType == AstAttrType::ENUM_NAME) { basep = nodep->findStringDType(); } else { basep = nodep->dtypep(); } - AstNodeArrayDType* vardtypep - = new AstUnpackArrayDType(nodep->fileline(), - basep, - new AstRange(nodep->fileline(), msbdim, 0)); + AstNodeArrayDType* vardtypep = new AstUnpackArrayDType( + nodep->fileline(), basep, new AstRange(nodep->fileline(), msbdim, 0)); AstInitArray* initp = new AstInitArray(nodep->fileline(), vardtypep, NULL); v3Global.rootp()->typeTablep()->addTypesp(vardtypep); AstVar* varp = new AstVar(nodep->fileline(), AstVarType::MODULETEMP, "__Venumtab_" + VString::downcase(attrType.ascii()) - + cvtToStr(m_dtTables++), + + cvtToStr(m_dtTables++), vardtypep); varp->isConst(true); varp->isStatic(true); @@ -4843,8 +4958,7 @@ private: // Default for all unspecified values if (attrType == AstAttrType::ENUM_NAME) { initp->defaultp(new AstConst(nodep->fileline(), AstConst::String(), "")); - } else if (attrType == AstAttrType::ENUM_NEXT - || attrType == AstAttrType::ENUM_PREV) { + } else if (attrType == AstAttrType::ENUM_NEXT || attrType == AstAttrType::ENUM_PREV) { initp->defaultp(new AstConst(nodep->fileline(), V3Number(nodep, nodep->width(), 0))); } else { nodep->v3fatalSrc("Bad case"); @@ -4853,10 +4967,8 @@ private: // Find valid values and populate UASSERT_OBJ(nodep->itemsp(), nodep, "enum without items"); std::vector values; - values.resize(msbdim+1); - for (unsigned i=0; i<(msbdim+1); ++i) { - values[i] = NULL; - } + values.resize(msbdim + 1); + for (unsigned i = 0; i < (msbdim + 1); ++i) values[i] = NULL; { AstEnumItem* firstp = nodep->itemsp(); AstEnumItem* prevp = firstp; // Prev must start with last item @@ -4880,7 +4992,7 @@ private: } } // Add all specified values to table - for (unsigned i=0; i<(msbdim+1); ++i) { + for (unsigned i = 0; i < (msbdim + 1); ++i) { AstNode* valp = values[i]; if (valp) initp->addIndexValuep(i, valp); } @@ -4892,18 +5004,18 @@ private: PatVecMap patVectorMap(AstPattern* nodep, const VNumRange& range) { PatVecMap patmap; int element = range.left(); - for (AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember); - patp; patp = VN_CAST(patp->nextp(), PatMember)) { + for (AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember); patp; + patp = VN_CAST(patp->nextp(), PatMember)) { if (patp->keyp()) { if (const AstConst* constp = VN_CAST(patp->keyp(), Const)) { element = constp->toSInt(); } else { patp->keyp()->v3error("Assignment pattern key not supported/understood: " - <keyp()->prettyTypeName()); + << patp->keyp()->prettyTypeName()); } } if (patmap.find(element) != patmap.end()) { - patp->v3error("Assignment pattern key used multiple times: "<v3error("Assignment pattern key used multiple times: " << element); } else { patmap.insert(make_pair(element, patp)); } @@ -4913,7 +5025,7 @@ private: } void makeOpenArrayShell(AstNodeFTaskRef* nodep) { - UINFO(4,"Replicate openarray function "<taskp()<taskp() << endl); AstNodeFTask* oldTaskp = nodep->taskp(); oldTaskp->dpiOpenParentInc(); UASSERT_OBJ(!oldTaskp->dpiOpenChild(), oldTaskp, @@ -4921,27 +5033,25 @@ private: AstNodeFTask* newTaskp = oldTaskp->cloneTree(false); newTaskp->dpiOpenChild(true); newTaskp->dpiOpenParentClear(); - newTaskp->name(newTaskp->name()+"__Vdpioc"+cvtToStr(oldTaskp->dpiOpenParent())); + newTaskp->name(newTaskp->name() + "__Vdpioc" + cvtToStr(oldTaskp->dpiOpenParent())); oldTaskp->addNextHere(newTaskp); // Relink reference to new function nodep->taskp(newTaskp); nodep->name(nodep->taskp()->name()); // Replace open array arguments with the callee's task V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp()); - for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) { + for (V3TaskConnects::iterator it = tconnects.begin(); it != tconnects.end(); ++it) { AstVar* portp = it->first; AstArg* argp = it->second; AstNode* pinp = argp->exprp(); if (!pinp) continue; // Argument error we'll find later - if (hasOpenArrayIterateDType(portp->dtypep())) { - portp->dtypep(pinp->dtypep()); - } + if (hasOpenArrayIterateDType(portp->dtypep())) portp->dtypep(pinp->dtypep()); } } bool markHasOpenArray(AstNodeFTask* nodep) { bool hasOpen = false; - for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) { + for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) { if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isDpiOpenArray() || hasOpenArrayIterateDType(portp->dtypep())) { portp->isDpiOpenArray(true); @@ -4962,8 +5072,8 @@ private: // METHODS - special type detection void assertAtStatement(AstNode* nodep) { if (VL_UNCOVERABLE(m_vup && !m_vup->selfDtm())) { - UINFO(1,"-: "<v3fatalSrc("No dtype expected at statement "<prettyTypeName()); + UINFO(1, "-: " << m_vup << endl); + nodep->v3fatalSrc("No dtype expected at statement " << nodep->prettyTypeName()); } } void checkConstantOrReplace(AstNode* nodep, const string& message) { @@ -4977,8 +5087,7 @@ private: } AstNode* nodeForUnsizedWarning(AstNode* nodep) { // Return a nodep to use for unsized warnings, reporting on child if can - if (nodep->op1p() && nodep->op1p()->dtypep() - && !nodep->op1p()->dtypep()->widthSized()) { + if (nodep->op1p() && nodep->op1p()->dtypep() && !nodep->op1p()->dtypep()->widthSized()) { return nodep->op1p(); } else if (nodep->op2p() && nodep->op2p()->dtypep() && !nodep->op2p()->dtypep()->widthSized()) { @@ -5070,11 +5179,11 @@ int V3Width::debug() { } void V3Width::width(AstNetlist* nodep) { - UINFO(2,__FUNCTION__<<": "<= 6); } diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h index 25036ebd2..04320bffb 100644 --- a/src/V3WidthCommit.h +++ b/src/V3WidthCommit.h @@ -120,13 +120,15 @@ private: nodep->replaceWith(newp); AstNode* oldp = nodep; nodep = newp; - // if (debug()>4) oldp->dumpTree(cout, " fixConstSize_old: "); - // if (debug()>4) newp->dumpTree(cout, " _new: "); + // if (debug() > 4) oldp->dumpTree(cout, " fixConstSize_old: "); + // if (debug() > 4) newp->dumpTree(cout, " _new: "); VL_DO_DANGLING(pushDeletep(oldp), oldp); } editDType(nodep); } - virtual void visit(AstNodeDType* nodep) VL_OVERRIDE { visitIterateNodeDType(nodep); } + virtual void visit(AstNodeDType* nodep) VL_OVERRIDE { // + visitIterateNodeDType(nodep); + } virtual void visit(AstNodeUOrStructDType* nodep) VL_OVERRIDE { if (nodep->user1SetOnce()) return; // Process once visitIterateNodeDType(nodep); diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp index 61facc612..78622792c 100644 --- a/src/V3WidthSel.cpp +++ b/src/V3WidthSel.cpp @@ -65,13 +65,16 @@ private: AstNodeDType* m_errp; // Node that was found, for error reporting if not known type AstNodeDType* m_dtypep; // Data type for the 'from' slice VNumRange m_fromRange; // Numeric range bounds for the 'from' slice - FromData(AstNodeDType* errp, AstNodeDType* dtypep, const VNumRange& fromRange) - { m_errp = errp; m_dtypep = dtypep; m_fromRange = fromRange; } + FromData(AstNodeDType* errp, AstNodeDType* dtypep, const VNumRange& fromRange) { + m_errp = errp; + m_dtypep = dtypep; + m_fromRange = fromRange; + } ~FromData() {} }; FromData fromDataForArray(AstNode* nodep, AstNode* basefromp) { // What is the data type and information for this SEL-ish's from()? - UINFO(9," fromData start ddtypep = "<dtypep()->skipRefp(); AstNodeDType* errp = ddtypep; - UINFO(9," fromData.ddtypep = "<rangep() + && (!VN_IS(adtypep->rangep()->msbp(), Const) + || !VN_IS(adtypep->rangep()->lsbp(), Const))), + nodep, + "Non-constant variable range; errored earlier"); // in constifyParam(bfdtypep) fromRange = adtypep->declRange(); } else { nodep->v3error("Illegal bit or array select; type does not have a bit range, or " << "bad dimension: data type is " << errp->prettyDTypeNameQ()); } - } - else { + } else { nodep->v3error("Illegal bit or array select; type already selected, or bad dimension: " << "data type is " << errp->prettyDTypeNameQ()); } @@ -123,7 +122,7 @@ private: return lhsp; } else if (VN_IS(lhsp, Const)) { // Optional vs just making add/sub below, but saves constification some work - V3Number num (lhsp, lhsp->width()); + V3Number num(lhsp, lhsp->width()); num.opSub(VN_CAST(lhsp, Const)->num(), V3Number(lhsp, 32, rhs)); num.isSigned(lhsp->isSigned()); AstNode* newp = new AstConst(lhsp->fileline(), num); @@ -135,8 +134,9 @@ private: newp->dtypeFrom(lhsp); return newp; } else { // rhs < 0; - AstNode* newp = new AstAdd(lhsp->fileline(), lhsp, - new AstConst(lhsp->fileline(), AstConst::Unsized32(), -rhs)); + AstNode* newp + = new AstAdd(lhsp->fileline(), lhsp, + new AstConst(lhsp->fileline(), AstConst::Unsized32(), -rhs)); // We must make sure sub gets sign of original value, not from the constant newp->dtypeFrom(lhsp); return newp; @@ -145,9 +145,8 @@ private: AstNode* newSubNeg(vlsint32_t lhs, AstNode* rhsp) { // Return lhs-rhs // We must make sure sub gets sign of original value - AstNode* newp = new AstSub(rhsp->fileline(), - new AstConst(rhsp->fileline(), AstConst::Unsized32(), lhs), - rhsp); + AstNode* newp = new AstSub( + rhsp->fileline(), new AstConst(rhsp->fileline(), AstConst::Unsized32(), lhs), rhsp); newp->dtypeFrom(rhsp); // Important as AstSub default is lhs's sign return newp; } @@ -176,13 +175,13 @@ private: AstNodeDType* sliceDType(AstPackArrayDType* nodep, int msb, int lsb) { // Return slice needed for msb/lsb, either as original dtype or a new slice dtype - if (nodep->declRange().elements() == (msb-lsb+1) // Extracting whole of original array + if (nodep->declRange().elements() == (msb - lsb + 1) // Extracting whole of original array && nodep->declRange().lo() == lsb) { return nodep; } else { // Need a slice data type, which is an array of the extracted // type, but with (presumably) different size - VNumRange newRange (msb, lsb, nodep->declRange().littleEndian()); + VNumRange newRange(msb, lsb, nodep->declRange().littleEndian()); AstNodeDType* vardtypep = new AstPackArrayDType(nodep->fileline(), nodep->subDTypep(), // Need to strip off array reference @@ -198,85 +197,78 @@ private: virtual void visit(AstSelBit* nodep) VL_OVERRIDE { // Select of a non-width specified part of an array, i.e. "array[2]" // This select style has a lsb and msb (no user specified width) - UINFO(6,"SELBIT "<=9) nodep->backp()->dumpTree(cout, "--SELBT0: "); + UINFO(6, "SELBIT " << nodep << endl); + if (debug() >= 9) nodep->backp()->dumpTree(cout, "--SELBT0: "); // lhsp/rhsp do not need to be constant AstNode* fromp = nodep->lhsp()->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); // bit we're extracting - if (debug()>=9) nodep->dumpTree(cout, "--SELBT2: "); + if (debug() >= 9) nodep->dumpTree(cout, "--SELBT2: "); FromData fromdata = fromDataForArray(nodep, fromp); AstNodeDType* ddtypep = fromdata.m_dtypep; VNumRange fromRange = fromdata.m_fromRange; - UINFO(6," ddtypep "< ARRAYSEL(array, index) AstNode* subp = rhsp; - if (fromRange.lo()!=0 || fromRange.hi()<0) { + if (fromRange.lo() != 0 || fromRange.hi() < 0) { subp = newSubNeg(subp, fromRange.lo()); } - AstArraySel* newp = new AstArraySel(nodep->fileline(), - fromp, subp); + AstArraySel* newp = new AstArraySel(nodep->fileline(), fromp, subp); newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off array reference - if (debug()>=9) newp->dumpTree(cout, "--SELBTn: "); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - else if (AstPackArrayDType* adtypep = VN_CAST(ddtypep, PackArrayDType)) { + if (debug() >= 9) newp->dumpTree(cout, "--SELBTn: "); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } else if (AstPackArrayDType* adtypep = VN_CAST(ddtypep, PackArrayDType)) { // SELBIT(array, index) -> SEL(array, index*width-of-subindex, width-of-subindex) AstNode* subp = rhsp; - if (fromRange.lo()!=0 || fromRange.hi()<0) { + if (fromRange.lo() != 0 || fromRange.hi() < 0) { if (fromRange.littleEndian()) { subp = newSubNeg(fromRange.hi(), subp); } else { subp = newSubNeg(subp, fromRange.lo()); } } - UASSERT_OBJ(!(!fromRange.elements() - || (adtypep->width() % fromRange.elements())!=0), adtypep, - "Array extraction with width miscomputed " - <width()<<"/"<width() % fromRange.elements()) != 0), + adtypep, + "Array extraction with width miscomputed " << adtypep->width() << "/" + << fromRange.elements()); int elwidth = adtypep->width() / fromRange.elements(); - AstSel* newp - = new AstSel(nodep->fileline(), - fromp, - new AstMul(nodep->fileline(), - new AstConst(nodep->fileline(), - AstConst::Unsized32(), elwidth), - subp), - new AstConst(nodep->fileline(), AstConst::Unsized32(), elwidth)); + AstSel* newp = new AstSel( + nodep->fileline(), fromp, + new AstMul(nodep->fileline(), + new AstConst(nodep->fileline(), AstConst::Unsized32(), elwidth), subp), + new AstConst(nodep->fileline(), AstConst::Unsized32(), elwidth)); newp->declRange(fromRange); newp->declElWidth(elwidth); newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off array reference - if (debug()>=9) newp->dumpTree(cout, "--SELBTn: "); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - else if (AstAssocArrayDType* adtypep = VN_CAST(ddtypep, AssocArrayDType)) { + if (debug() >= 9) newp->dumpTree(cout, "--SELBTn: "); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } else if (AstAssocArrayDType* adtypep = VN_CAST(ddtypep, AssocArrayDType)) { // SELBIT(array, index) -> ASSOCSEL(array, index) AstNode* subp = rhsp; - AstAssocSel* newp = new AstAssocSel(nodep->fileline(), - fromp, subp); + AstAssocSel* newp = new AstAssocSel(nodep->fileline(), fromp, subp); newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off array reference - if (debug()>=9) newp->dumpTree(cout, "--SELBTn: "); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - else if (AstDynArrayDType* adtypep = VN_CAST(ddtypep, DynArrayDType)) { + if (debug() >= 9) newp->dumpTree(cout, "--SELBTn: "); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } else if (AstDynArrayDType* adtypep = VN_CAST(ddtypep, DynArrayDType)) { // SELBIT(array, index) -> CMETHODCALL(queue, "at", index) AstNode* subp = rhsp; - AstCMethodHard* newp = new AstCMethodHard(nodep->fileline(), - fromp, "at", subp); + AstCMethodHard* newp = new AstCMethodHard(nodep->fileline(), fromp, "at", subp); newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off queue reference - if (debug()>=9) newp->dumpTree(cout, "--SELBTq: "); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - else if (AstQueueDType* adtypep = VN_CAST(ddtypep, QueueDType)) { + if (debug() >= 9) newp->dumpTree(cout, "--SELBTq: "); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } else if (AstQueueDType* adtypep = VN_CAST(ddtypep, QueueDType)) { // SELBIT(array, index) -> CMETHODCALL(queue, "at", index) AstNode* subp = rhsp; - AstCMethodHard* newp = new AstCMethodHard(nodep->fileline(), - fromp, "at", subp); + AstCMethodHard* newp = new AstCMethodHard(nodep->fileline(), fromp, "at", subp); newp->dtypeFrom(adtypep->subDTypep()); // Need to strip off queue reference - if (debug()>=9) newp->dumpTree(cout, "--SELBTq: "); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - else if (VN_IS(ddtypep, BasicDType) && ddtypep->isString()) { + if (debug() >= 9) newp->dumpTree(cout, "--SELBTq: "); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } else if (VN_IS(ddtypep, BasicDType) && ddtypep->isString()) { // SELBIT(string, index) -> GETC(string, index) AstNodeVarRef* varrefp = VN_CAST(fromp, NodeVarRef); if (!varrefp) nodep->v3error("Unsupported: String array operation on non-variable"); @@ -291,29 +283,25 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); } else if (VN_IS(ddtypep, BasicDType)) { // SELBIT(range, index) -> SEL(array, index, 1) - AstSel* newp = new AstSel(nodep->fileline(), - fromp, - newSubLsbOf(rhsp, fromRange), + AstSel* newp = new AstSel(nodep->fileline(), fromp, newSubLsbOf(rhsp, fromRange), // Unsized so width from user new AstConst(nodep->fileline(), AstConst::Unsized32(), 1)); newp->declRange(fromRange); - UINFO(6," new "<=9) newp->dumpTree(cout, "--SELBTn: "); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - else if (VN_IS(ddtypep, NodeUOrStructDType)) { // A bit from the packed struct + UINFO(6, " new " << newp << endl); + if (debug() >= 9) newp->dumpTree(cout, "--SELBTn: "); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } else if (VN_IS(ddtypep, NodeUOrStructDType)) { // A bit from the packed struct // SELBIT(range, index) -> SEL(array, index, 1) - AstSel* newp = new AstSel(nodep->fileline(), - fromp, - newSubLsbOf(rhsp, fromRange), + AstSel* newp = new AstSel(nodep->fileline(), fromp, newSubLsbOf(rhsp, fromRange), // Unsized so width from user new AstConst(nodep->fileline(), AstConst::Unsized32(), 1)); newp->declRange(fromRange); - UINFO(6," new "<=9) newp->dumpTree(cout, "--SELBTn: "); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - else { // NULL=bad extract, or unknown node type + UINFO(6, " new " << newp << endl); + if (debug() >= 9) newp->dumpTree(cout, "--SELBTn: "); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } else { // NULL=bad extract, or unknown node type nodep->v3error("Illegal bit or array select; type already selected, or bad dimension: " << "data type is" << fromdata.m_errp->prettyDTypeNameQ()); // How to recover? We'll strip a dimension. @@ -326,20 +314,22 @@ private: // Select of a range specified part of an array, i.e. "array[2:3]" // SELEXTRACT(from,msb,lsb) -> SEL(from, lsb, 1+msb-lsb) // This select style has a (msb or lsb) and width - UINFO(6,"SELEXTRACT "<=9) nodep->dumpTree(cout, "--SELEX0: "); + UINFO(6, "SELEXTRACT " << nodep << endl); + // if (debug() >= 9) nodep->dumpTree(cout, "--SELEX0: "); // Below 2 lines may change nodep->widthp() V3Const::constifyParamsEdit(nodep->lsbp()); // May relink pointed to node V3Const::constifyParamsEdit(nodep->msbp()); // May relink pointed to node - //if (debug()>=9) nodep->dumpTree(cout, "--SELEX3: "); - checkConstantOrReplace(nodep->lsbp(), "First value of [a:b] isn't a constant, maybe you want +: or -:"); - checkConstantOrReplace(nodep->msbp(), "Second value of [a:b] isn't a constant, maybe you want +: or -:"); + // if (debug() >= 9) nodep->dumpTree(cout, "--SELEX3: "); + checkConstantOrReplace(nodep->lsbp(), + "First value of [a:b] isn't a constant, maybe you want +: or -:"); + checkConstantOrReplace(nodep->msbp(), + "Second value of [a:b] isn't a constant, maybe you want +: or -:"); AstNode* fromp = nodep->lhsp()->unlinkFrBack(); AstNode* msbp = nodep->rhsp()->unlinkFrBack(); AstNode* lsbp = nodep->thsp()->unlinkFrBack(); vlsint32_t msb = VN_CAST(msbp, Const)->toSInt(); vlsint32_t lsb = VN_CAST(lsbp, Const)->toSInt(); - vlsint32_t elem = (msb>lsb) ? (msb-lsb+1) : (lsb-msb+1); + vlsint32_t elem = (msb > lsb) ? (msb - lsb + 1) : (lsb - msb + 1); FromData fromdata = fromDataForArray(nodep, fromp); AstNodeDType* ddtypep = fromdata.m_dtypep; VNumRange fromRange = fromdata.m_fromRange; @@ -347,90 +337,101 @@ private: // Slice extraction if (fromRange.elements() == elem && fromRange.lo() == lsb) { // Extracting whole of original array - nodep->replaceWith(fromp); VL_DO_DANGLING(pushDeletep(nodep), nodep); + nodep->replaceWith(fromp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); } else if (fromRange.elements() == 1) { // Extracting single element AstArraySel* newp = new AstArraySel(nodep->fileline(), fromp, lsbp); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); } else { // Slice AstSliceSel* newp = new AstSliceSel(nodep->fileline(), fromp, - VNumRange(VNumRange::LeftRight(), - msb, lsb)); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); + VNumRange(VNumRange::LeftRight(), msb, lsb)); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); } - } - else if (AstPackArrayDType* adtypep = VN_CAST(ddtypep, PackArrayDType)) { + } else if (AstPackArrayDType* adtypep = VN_CAST(ddtypep, PackArrayDType)) { // SELEXTRACT(array, msb, lsb) -> SEL(array, // lsb*width-of-subindex, width-of-subindex*(msb-lsb)) - UASSERT_OBJ(!(!fromRange.elements() - || (adtypep->width() % fromRange.elements())!=0), adtypep, - "Array extraction with width miscomputed " - <width()<<"/"<width() % fromRange.elements()) != 0), + adtypep, + "Array extraction with width miscomputed " << adtypep->width() << "/" + << fromRange.elements()); if (fromRange.littleEndian()) { // Below code assumes big bit endian; just works out if we swap - int x = msb; msb = lsb; lsb = x; + int x = msb; + msb = lsb; + lsb = x; } if (lsb > msb) { - nodep->v3error("["<v3error("[" + << msb << ":" << lsb + << "] Range extract has backward bit ordering, perhaps you wanted [" + << lsb << ":" << msb << "]"); + int x = msb; + msb = lsb; + lsb = x; } int elwidth = adtypep->width() / fromRange.elements(); - AstSel* newp = new AstSel(nodep->fileline(), - fromp, - new AstMul(nodep->fileline(), newSubLsbOf(lsbp, fromRange), - new AstConst(nodep->fileline(), - AstConst::Unsized32(), elwidth)), - new AstConst(nodep->fileline(), - AstConst::Unsized32(), (msb-lsb+1)*elwidth)); + AstSel* newp = new AstSel( + nodep->fileline(), fromp, + new AstMul(nodep->fileline(), newSubLsbOf(lsbp, fromRange), + new AstConst(nodep->fileline(), AstConst::Unsized32(), elwidth)), + new AstConst(nodep->fileline(), AstConst::Unsized32(), (msb - lsb + 1) * elwidth)); newp->declRange(fromRange); newp->declElWidth(elwidth); newp->dtypeFrom(sliceDType(adtypep, msb, lsb)); - //if (debug()>=9) newp->dumpTree(cout, "--EXTBTn: "); + // if (debug() >= 9) newp->dumpTree(cout, "--EXTBTn: "); UASSERT_OBJ(newp->widthMin() == newp->widthConst(), nodep, "Width mismatch"); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - else if (VN_IS(ddtypep, BasicDType)) { + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } else if (VN_IS(ddtypep, BasicDType)) { if (fromRange.littleEndian()) { // Below code assumes big bit endian; just works out if we swap - int x = msb; msb = lsb; lsb = x; + int x = msb; + msb = lsb; + lsb = x; } if (lsb > msb) { - nodep->v3error("["<v3error("[" + << msb << ":" << lsb + << "] Range extract has backward bit ordering, perhaps you wanted [" + << lsb << ":" << msb << "]"); + int x = msb; + msb = lsb; + lsb = x; } AstNode* widthp = new AstConst(msbp->fileline(), AstConst::Unsized32(), // Unsized so width from user - msb +1-lsb); - AstSel* newp = new AstSel(nodep->fileline(), - fromp, - newSubLsbOf(lsbp, fromRange), - widthp); + msb + 1 - lsb); + AstSel* newp + = new AstSel(nodep->fileline(), fromp, newSubLsbOf(lsbp, fromRange), widthp); newp->declRange(fromRange); - UINFO(6," new "<=9) newp->dumpTree(cout, "--SELEXnew: "); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - else if (VN_IS(ddtypep, NodeUOrStructDType)) { + UINFO(6, " new " << newp << endl); + // if (debug() >= 9) newp->dumpTree(cout, "--SELEXnew: "); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } else if (VN_IS(ddtypep, NodeUOrStructDType)) { // Classes aren't little endian if (lsb > msb) { - nodep->v3error("["<v3error("[" + << msb << ":" << lsb + << "] Range extract has backward bit ordering, perhaps you wanted [" + << lsb << ":" << msb << "]"); + int x = msb; + msb = lsb; + lsb = x; } AstNode* widthp = new AstConst(msbp->fileline(), AstConst::Unsized32(), // Unsized so width from user - msb +1-lsb); - AstSel* newp = new AstSel(nodep->fileline(), - fromp, - newSubLsbOf(lsbp, fromRange), - widthp); + msb + 1 - lsb); + AstSel* newp + = new AstSel(nodep->fileline(), fromp, newSubLsbOf(lsbp, fromRange), widthp); newp->declRange(fromRange); - UINFO(6," new "<=9) newp->dumpTree(cout, "--SELEXnew: "); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - else { // NULL=bad extract, or unknown node type + UINFO(6, " new " << newp << endl); + // if (debug() >= 9) newp->dumpTree(cout, "--SELEXnew: "); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } else { // NULL=bad extract, or unknown node type nodep->v3error("Illegal range select; type already selected, or bad dimension: " << "data type is " << fromdata.m_errp->prettyDTypeNameQ()); UINFO(1, " Related ddtype: " << ddtypep << endl); @@ -447,38 +448,40 @@ private: void replaceSelPlusMinus(AstNodePreSel* nodep) { // Select of a range specified with +: or -:, i.e. "array[2+:3], [2-:3]" // This select style has a lsb and width - UINFO(6,"SELPLUS/MINUS "<widthp() - if (debug()>=9) nodep->dumpTree(cout, "--SELPM0: "); + if (debug() >= 9) nodep->dumpTree(cout, "--SELPM0: "); V3Const::constifyParamsEdit(nodep->thsp()); // May relink pointed to node checkConstantOrReplace(nodep->thsp(), "Width of :+ or :- bit extract isn't a constant"); - if (debug()>=9) nodep->dumpTree(cout, "--SELPM3: "); + if (debug() >= 9) nodep->dumpTree(cout, "--SELPM3: "); // Now replace it with an AstSel AstNode* fromp = nodep->lhsp()->unlinkFrBack(); - AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); + AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); AstNode* widthp = nodep->thsp()->unlinkFrBack(); int width = VN_CAST(widthp, Const)->toSInt(); - if (width > (1<<28)) nodep->v3error("Width of :+ or :- is huge; vector of over 1billion bits: " - <prettyName()); - if (width<0) nodep->v3error("Width of :+ or :- is < 0: "<prettyName()); + if (width > (1 << 28)) { + nodep->v3error("Width of :+ or :- is huge; vector of over 1billion bits: " + << widthp->prettyName()); + } + if (width < 0) nodep->v3error("Width of :+ or :- is < 0: " << widthp->prettyName()); FromData fromdata = fromDataForArray(nodep, fromp); AstNodeDType* ddtypep = fromdata.m_dtypep; VNumRange fromRange = fromdata.m_fromRange; - if (VN_IS(ddtypep, BasicDType) - || VN_IS(ddtypep, PackArrayDType) + if (VN_IS(ddtypep, BasicDType) || VN_IS(ddtypep, PackArrayDType) || (VN_IS(ddtypep, NodeUOrStructDType) && VN_CAST(ddtypep, NodeUOrStructDType)->packedUnsup())) { int elwidth = 1; AstNode* newwidthp = widthp; if (const AstPackArrayDType* adtypep = VN_CAST(ddtypep, PackArrayDType)) { elwidth = adtypep->width() / fromRange.elements(); - newwidthp = new AstConst(nodep->fileline(), AstConst::Unsized32(), width * elwidth); + newwidthp + = new AstConst(nodep->fileline(), AstConst::Unsized32(), width * elwidth); } AstNode* newlsbp = NULL; if (VN_IS(nodep, SelPlus)) { if (fromRange.littleEndian()) { // SELPLUS(from,lsb,width) -> SEL(from, (vector_msb-width+1)-sel, width) - newlsbp = newSubNeg((fromRange.hi()-width+1), rhsp); + newlsbp = newSubNeg((fromRange.hi() - width + 1), rhsp); } else { // SELPLUS(from,lsb,width) -> SEL(from, lsb-vector_lsb, width) newlsbp = newSubNeg(rhsp, fromRange.lo()); @@ -489,22 +492,23 @@ private: newlsbp = newSubNeg(fromRange.hi(), rhsp); } else { // SELMINUS(from,msb,width) -> SEL(from, msb-(width-1)-lsb#) - newlsbp = newSubNeg(rhsp, fromRange.lo()+(width-1)); + newlsbp = newSubNeg(rhsp, fromRange.lo() + (width - 1)); } } else { nodep->v3fatalSrc("Bad Case"); } - if (elwidth != 1) newlsbp = new AstMul(nodep->fileline(), newlsbp, - new AstConst(nodep->fileline(), elwidth)); - AstSel* newp = new AstSel(nodep->fileline(), - fromp, newlsbp, newwidthp); + if (elwidth != 1) { + newlsbp = new AstMul(nodep->fileline(), newlsbp, + new AstConst(nodep->fileline(), elwidth)); + } + AstSel* newp = new AstSel(nodep->fileline(), fromp, newlsbp, newwidthp); newp->declRange(fromRange); newp->declElWidth(elwidth); - UINFO(6," new "<=9) newp->dumpTree(cout, "--SELNEW: "); - nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - else { // NULL=bad extract, or unknown node type + UINFO(6, " new " << newp << endl); + if (debug() >= 9) newp->dumpTree(cout, "--SELNEW: "); + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } else { // NULL=bad extract, or unknown node type nodep->v3error("Illegal +: or -: select; type already selected, or bad dimension: " << "data type is " << fromdata.m_errp->prettyDTypeNameQ()); // How to recover? We'll strip a dimension. @@ -516,12 +520,8 @@ private: if (!rhsp->backp()) { VL_DO_DANGLING(pushDeletep(rhsp), rhsp); } if (!widthp->backp()) { VL_DO_DANGLING(pushDeletep(widthp), widthp); } } - virtual void visit(AstSelPlus* nodep) VL_OVERRIDE { - replaceSelPlusMinus(nodep); - } - virtual void visit(AstSelMinus* nodep) VL_OVERRIDE { - replaceSelPlusMinus(nodep); - } + virtual void visit(AstSelPlus* nodep) VL_OVERRIDE { replaceSelPlusMinus(nodep); } + virtual void visit(AstSelMinus* nodep) VL_OVERRIDE { replaceSelPlusMinus(nodep); } // If adding new visitors, ensure V3Width's visit(TYPE) calls into here //-------------------- @@ -534,9 +534,7 @@ private: public: // CONSTRUCTORS WidthSelVisitor() {} - AstNode* mainAcceptEdit(AstNode* nodep) { - return iterateSubtreeReturnEdits(nodep); - } + AstNode* mainAcceptEdit(AstNode* nodep) { return iterateSubtreeReturnEdits(nodep); } virtual ~WidthSelVisitor() {} }; @@ -544,7 +542,7 @@ public: // Width class functions AstNode* V3Width::widthSelNoIterEdit(AstNode* nodep) { - UINFO(4,__FUNCTION__<<": "<