Fix "Missing coverage in PSL" due to "cover property $stop" statements.

"cover property" reported hierarchy now includes named begin blocks.
This commit is contained in:
Wilson Snyder 2008-11-05 10:23:03 -05:00
parent 5d2675e38a
commit 3d788b4b93
5 changed files with 53 additions and 9 deletions

View File

@ -115,7 +115,7 @@ private:
} else {
// V3Coverage assigned us a bucket to increment.
AstCoverInc* covincp = snodep->coverincp()->castCoverInc();
if (!covincp) snodep->v3fatalSrc("Missing coverage in PSL");
if (!covincp) snodep->v3fatalSrc("Missing AstCoverInc under assertion");
covincp->unlinkFrBack();
if (message!="") covincp->declp()->comment(message);
bodysp = covincp;

View File

@ -142,6 +142,11 @@ private:
}
nodep->iterateChildren(*this);
}
virtual void visit(AstCoverDecl* nodep, AstNUser*) {
// Don't need to fix path in coverage statements, they're not under
// any BEGINs, but V3Coverage adds them all under the module itself.
nodep->iterateChildren(*this);
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}

View File

@ -52,11 +52,13 @@ private:
bool m_checkBlock; // Should this block get covered?
AstModule* m_modp; // Current module to add statement to
FileMap m_fileps; // Column counts for each fileline
string m_beginHier; // AstBegin hier name for user coverage points
//int debug() { return 9; }
// METHODS
AstCoverInc* newCoverInc(FileLine* fl, const string& type, const string& comment) {
AstCoverInc* newCoverInc(FileLine* fl, const string& hier,
const string& type, const string& comment) {
int column = 0;
FileMap::iterator it = m_fileps.find(fl);
if (it == m_fileps.end()) {
@ -66,6 +68,7 @@ private:
}
AstCoverDecl* declp = new AstCoverDecl(fl, column, type, comment);
declp->hier(hier);
m_modp->addStmtp(declp);
return new AstCoverInc(fl, declp);
@ -86,7 +89,7 @@ private:
if (!nodep->backp()->castIf()
|| nodep->backp()->castIf()->elsesp()!=nodep) { // Ignore if else; did earlier
UINFO(4," COVER: "<<nodep<<endl);
nodep->addIfsp(newCoverInc(nodep->fileline(), "block", "if"));
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "block", "if"));
}
}
// Don't do empty else's, only empty if/case's
@ -96,9 +99,9 @@ private:
if (m_checkBlock && v3Global.opt.coverageLine()) { // if a "else" branch didn't disable it
UINFO(4," COVER: "<<nodep<<endl);
if (nodep->elsesp()->castIf()) {
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "block", "elsif"));
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "", "block", "elsif"));
} else {
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "block", "else"));
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(), "", "block", "else"));
}
}
}
@ -111,18 +114,20 @@ private:
nodep->bodysp()->iterateAndNext(*this);
if (m_checkBlock) { // if the case body didn't disable it
UINFO(4," COVER: "<<nodep<<endl);
nodep->addBodysp(newCoverInc(nodep->fileline(), "block", "case"));
nodep->addBodysp(newCoverInc(nodep->fileline(), "", "block", "case"));
}
m_checkBlock = true; // Reset as a child may have cleared it
}
}
virtual void visit(AstPslCover* nodep, AstNUser*) {
UINFO(4," PSLCOVER: "<<nodep<<endl);
m_checkBlock = true; // Always do cover blocks, even if there's a $stop
nodep->iterateChildren(*this);
if (!nodep->coverincp()) {
// Note the name may be overridden by V3Assert processing
nodep->coverincp(newCoverInc(nodep->fileline(), "psl_cover", "cover"));
nodep->coverincp(newCoverInc(nodep->fileline(), m_beginHier, "psl_cover", "cover"));
}
m_checkBlock = true; // Reset as a child may have cleared it
}
virtual void visit(AstStop* nodep, AstNUser*) {
UINFO(4," STOP: "<<nodep<<endl);
@ -134,8 +139,24 @@ private:
UINFO(4," OFF: "<<nodep<<endl);
m_checkBlock = false;
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
} else {
if (m_checkBlock) nodep->iterateChildren(*this);
}
if (m_checkBlock) nodep->iterateChildren(*this);
}
virtual void visit(AstBegin* nodep, AstNUser*) {
// Record the hiearchy of any named begins, so we can apply to user
// coverage points. This is because there may be cov points inside
// generate blocks; each point should get separate consideration.
// (Currently ignored for line coverage, since any generate iteration
// covers the code in that line.)
string oldHier = m_beginHier;
{
if (nodep->name()!="") {
m_beginHier = m_beginHier + (m_beginHier!=""?".":"") + nodep->name();
}
nodep->iterateChildren(*this);
}
m_beginHier = oldHier;
}
virtual void visit(AstNode* nodep, AstNUser*) {
// Default: Just iterate
@ -150,6 +171,7 @@ public:
CoverageVisitor(AstNetlist* rootp) {
// Operate on all modules
m_checkBlock = true;
m_beginHier = "";
rootp->iterateChildren(*this);
}
virtual ~CoverageVisitor() {}

View File

@ -481,7 +481,9 @@ sub _run {
my %param = (tee=>1,
@_);
my $command = join(' ',@{$param{cmd}});
print "\t$command\n";
print "\t$command";
print " > $param{logfile}" if $param{logfile};
print "\n";
if ($param{logfile}) {
open(SAVEOUT, ">&STDOUT") or die "%Error: Can't dup stdout";

View File

@ -64,7 +64,22 @@ module Test
cover property (@(posedge clk) disable iff (!toggle) cyc==8)
$stop;
//============================================================
// Using a macro and generate
wire reset = (cyc < 2);
`define covclk(eqn) cover property (@(posedge clk) disable iff (reset) (eqn))
genvar i;
generate
for (i=0; i<32; i=i+1)
begin: cycval
CycCover_i: `covclk( cyc[i] );
end
endgenerate
`ifndef verilator // Unsupported
//============================================================
// Using a more complicated property
property C1;
@(posedge clk)