From 2cb97f7475291df496aff131d95f5ace7f5283f3 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 30 Dec 2010 07:55:31 -0500 Subject: [PATCH] For UNUSED, ignore black boxed sys calls --- src/V3AstNodes.h | 16 ++++++++++++++++ src/V3Const.cpp | 8 ++++++++ src/V3EmitV.cpp | 6 ++++++ src/V3LinkLValue.cpp | 6 ++++++ src/V3Undriven.cpp | 18 ++++++++++++++---- src/V3Width.cpp | 3 +++ src/verilog.y | 4 ++-- test_regress/t/t_lint_unused_bad.pl | 2 +- test_regress/t/t_lint_unused_bad.v | 4 ++++ 9 files changed, 60 insertions(+), 7 deletions(-) diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 25e8eece7..eaf62cdbe 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -1679,6 +1679,22 @@ struct AstSFormat : public AstNode { void lhsp(AstNode* nodep) { setOp3p(nodep); } }; +struct AstSysIgnore : public AstNode { + // Parents: stmtlist + // Children: varrefs or exprs + AstSysIgnore(FileLine* fileline, AstNode* exprsp) + : AstNode (fileline) { setNOp1p(exprsp); } + ASTNODE_NODE_FUNCS(SysIgnore, SYSIGNORE) + virtual string verilogKwd() const { return "$ignored"; } + virtual bool isGateOptimizable() const { return false; } // Though deleted before opt + virtual bool isPredictOptimizable() const { return false; } // Though deleted before opt + virtual bool isSplittable() const { return false; } // Though deleted before opt + virtual bool isOutputter() const { return true; } // Though deleted before opt + virtual int instrCount() const { return instrCountPli(); } + AstNode* exprsp() const { return op1p()->castNode(); } // op1 = Expressions to output + void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output +}; + struct AstFClose : public AstNodeStmt { // Parents: stmtlist // Children: file which must be a varref diff --git a/src/V3Const.cpp b/src/V3Const.cpp index bce82e018..c98b4ab19 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -1508,6 +1508,14 @@ private: // If output of a presel didn't get consted, chances are V3Param didn't visit properly virtual void visit(AstNodePreSel* nodep, AstNUser*) {} + // Ignored, can eliminate early + virtual void visit(AstSysIgnore* nodep, AstNUser*) { + nodep->iterateChildren(*this); + if (m_doNConst) { + nodep->unlinkFrBack()->deleteTree(); nodep=NULL; + } + } + //----- // Jump elimination diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index eb43aeb7e..f51c949a8 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -276,6 +276,12 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { if (nodep->msbp()) { putbs(","); nodep->msbp()->iterateChildren(*this); } puts(");\n"); } + virtual void visit(AstSysIgnore* nodep, AstNUser*) { + putfs(nodep,nodep->verilogKwd()); + putbs(" ("); + nodep->exprsp()->iterateChildren(*this); + puts(");\n"); + } virtual void visit(AstNodeFor* nodep, AstNUser*) { putfs(nodep,"for ("); m_suppressSemi = true; diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index 2f6a43df0..c78bc3404 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -154,6 +154,12 @@ private: } m_setRefLvalue = last_setRefLvalue; } + virtual void visit(AstSysIgnore* nodep, AstNUser*) { + // Can't know if lvalue or not; presume so as stricter + bool last_setRefLvalue = m_setRefLvalue; + nodep->iterateChildren(*this); + m_setRefLvalue = last_setRefLvalue; + } virtual void visit(AstReadMem* nodep, AstNUser*) { bool last_setRefLvalue = m_setRefLvalue; { diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp index 5a76e6668..7d7aa632f 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -197,6 +197,7 @@ private: // STATE vector m_entryps; // Nodes to delete when we are finished + bool m_markBoth; // Mark as driven+used // METHODS static int debug() { @@ -242,8 +243,8 @@ private: if (varrefp && constp && !constp->num().isFourState()) { UndrivenVarEntry* entryp = getEntryp (varrefp->varp()); int lsb = constp->toUInt(); - if (varrefp->lvalue()) entryp->drivenBit(lsb, nodep->width()); - else entryp->usedBit(lsb, nodep->width()); + if (m_markBoth || varrefp->lvalue()) entryp->drivenBit(lsb, nodep->width()); + if (m_markBoth || !varrefp->lvalue()) entryp->usedBit(lsb, nodep->width()); } else { // else other varrefs handled as unknown mess in AstVarRef nodep->iterateChildren(*this); @@ -252,8 +253,16 @@ private: virtual void visit(AstVarRef* nodep, AstNUser*) { // Any variable UndrivenVarEntry* entryp = getEntryp (nodep->varp()); - if (nodep->lvalue()) entryp->drivenWhole(); - else entryp->usedWhole(); + if (m_markBoth || nodep->lvalue()) entryp->drivenWhole(); + if (m_markBoth || !nodep->lvalue()) entryp->usedWhole(); + } + + // Don't know what black boxed calls do, assume in+out + virtual void visit(AstSysIgnore* nodep, AstNUser*) { + bool prevMark = m_markBoth; + m_markBoth = true; + nodep->iterateChildren(*this); + m_markBoth = prevMark; } // Until we support tables, primitives will have undriven and unused I/Os @@ -274,6 +283,7 @@ private: public: // CONSTUCTORS UndrivenVisitor(AstNetlist* nodep) { + m_markBoth = false; AstNode::user1ClearTree(); // user1p() used on entire tree nodep->accept(*this); } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 1a2ae9e7f..956d7bcf0 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -809,6 +809,9 @@ private: nodep->width(32,32); } } + virtual void visit(AstSysIgnore* nodep, AstNUser* vup) { + nodep->exprsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); + } virtual void visit(AstReadMem* nodep, AstNUser*) { nodep->filenamep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); nodep->memp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); diff --git a/src/verilog.y b/src/verilog.y index 8dcd6ae78..ff02a621f 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -2063,8 +2063,8 @@ function_subroutine_callNoMethod: // IEEE: function_subroutine_call (as f system_t_call: // IEEE: system_tf_call (as task) // - yaD_IGNORE parenE { $$ = NULL; } - | yaD_IGNORE '(' exprList ')' { $$ = NULL; } + yaD_IGNORE parenE { $$ = new AstSysIgnore($1,NULL); } + | yaD_IGNORE '(' exprList ')' { $$ = new AstSysIgnore($1,$3); } // | yaD_DPI parenE { $$ = new AstTaskRef($1,*$1,NULL); } | yaD_DPI '(' exprList ')' { $$ = new AstTaskRef($2,*$1,$3); } diff --git a/test_regress/t/t_lint_unused_bad.pl b/test_regress/t/t_lint_unused_bad.pl index 873e53d07..8ff39c08c 100755 --- a/test_regress/t/t_lint_unused_bad.pl +++ b/test_regress/t/t_lint_unused_bad.pl @@ -8,7 +8,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di # Version 2.0. compile ( - v_flags2 => ["--lint-only -Wall -Wno-DECLFILENAME"], + v_flags2 => ["--lint-only --bbox-sys -Wall -Wno-DECLFILENAME"], fails=>1, verilator_make_gcc => 0, make_top_shell => 0, diff --git a/test_regress/t/t_lint_unused_bad.v b/test_regress/t/t_lint_unused_bad.v index 9464fa944..bc9c25aeb 100644 --- a/test_regress/t/t_lint_unused_bad.v +++ b/test_regress/t/t_lint_unused_bad.v @@ -18,6 +18,10 @@ module t (/*AUTOARG*/ // Check we don't warn about unused UDP signals udp_mux2 udpsub (out, in, in, in); + // Check ignoreds mark as used + reg sysused; + initial $bboxed(sysused); + endmodule module sub;