diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp index 9ca63c752..9597277db 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -229,7 +229,7 @@ private: // STATE vector m_entryps[3]; // Nodes to delete when we are finished - bool m_markBoth; // Mark as driven+used + bool m_inBBox; // In black box; mark as driven+used AstNodeFTask* m_taskp; // Current task AstAlways* m_alwaysp; // Current always @@ -258,6 +258,7 @@ private: void warnAlwCombOrder(AstVarRef* nodep) { AstVar* varp = nodep->varp(); if (!varp->isParam() && !varp->isGenVar() && !varp->isUsedLoopIdx() + && !m_inBBox // We may have falsely considered a SysIgnore as a driver && !varp->fileline()->warnIsOff(V3ErrorCode::ALWCOMBORDER)) { // Warn only once per variable nodep->v3warn(ALWCOMBORDER, "Always_comb variable driven after use: "<prettyName()); varp->fileline()->modifyWarnOff(V3ErrorCode::ALWCOMBORDER, true); // Complain just once for any usage @@ -294,7 +295,7 @@ private: for (int usr=1; usr<(m_alwaysp?3:2); ++usr) { UndrivenVarEntry* entryp = getEntryp (varrefp->varp(), usr); int lsb = constp->toUInt(); - if (m_markBoth || varrefp->lvalue()) { + 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_alwaysp && entryp->isUsedNotDrivenBit(lsb, nodep->width())) { UINFO(9," Select. Entryp="<<(void*)entryp<drivenBit(lsb, nodep->width()); } - if (m_markBoth || !varrefp->lvalue()) entryp->usedBit(lsb, nodep->width()); + if (m_inBBox || !varrefp->lvalue()) entryp->usedBit(lsb, nodep->width()); } } else { // else other varrefs handled as unknown mess in AstVarRef @@ -314,23 +315,23 @@ private: for (int usr=1; usr<(m_alwaysp?3:2); ++usr) { UndrivenVarEntry* entryp = getEntryp (nodep->varp(), usr); bool fdrv = nodep->lvalue() && nodep->varp()->attrFileDescr(); // FD's are also being read from - if (m_markBoth || nodep->lvalue()) { + if (m_inBBox || nodep->lvalue()) { if (usr==2 && m_alwaysp && entryp->isUsedNotDrivenAny()) { UINFO(9," Full bus. Entryp="<<(void*)entryp<drivenWhole(); } - if (m_markBoth || !nodep->lvalue() || fdrv) entryp->usedWhole(); + if (m_inBBox || !nodep->lvalue() || fdrv) 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; + bool prevMark = m_inBBox; + m_inBBox = true; nodep->iterateChildren(*this); - m_markBoth = prevMark; + m_inBBox = prevMark; } virtual void visit(AstAlways* nodep, AstNUser*) { @@ -371,7 +372,7 @@ private: public: // CONSTUCTORS explicit UndrivenVisitor(AstNetlist* nodep) { - m_markBoth = false; + m_inBBox = false; m_taskp = NULL; m_alwaysp = NULL; nodep->accept(*this); diff --git a/test_regress/t/t_lint_comb_use.pl b/test_regress/t/t_lint_comb_use.pl new file mode 100755 index 000000000..85a93664d --- /dev/null +++ b/test_regress/t/t_lint_comb_use.pl @@ -0,0 +1,21 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2008 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +$Self->{vlt} or $Self->skip("Verilator only test"); + +compile ( + verilator_flags2 => ["--lint-only --bbox-sys"], + fails=>0, + verilator_make_gcc => 0, + make_top_shell => 0, + make_main => 0, + ); + +ok(1); +1; diff --git a/test_regress/t/t_lint_comb_use.v b/test_regress/t/t_lint_comb_use.v new file mode 100644 index 000000000..cd9a97824 --- /dev/null +++ b/test_regress/t/t_lint_comb_use.v @@ -0,0 +1,30 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2010 by Wilson Snyder. + +module t (/*AUTOARG*/ + // Outputs + hval, + // Inputs + sel + ); + + input logic [2:0] sel; + output logic [3:0] hval; + + /*AUTOINPUT*/ + /*AUTOOUTPUT*/ + + always_comb begin + unique case (sel) + 3'h0: hval = 4'hd; + 3'h1: hval = 4'hc; + 3'h7: hval = 4'hf; + default: begin + $ignore ("ERROR : %s [%m]", $sformatf ("Illegal sel = %x", sel)); + hval = 4'bx; + end + endcase + end +endmodule