Support elaboration assertions, bug973.
This commit is contained in:
parent
040b1b06d5
commit
4fde6ee7af
2
Changes
2
Changes
|
@ -11,6 +11,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||||
|
|
||||||
** Support $sformatf, bug977. [Johan Bjork]
|
** Support $sformatf, bug977. [Johan Bjork]
|
||||||
|
|
||||||
|
*** Support elaboration assertions, bug973. [Johan Bjork]
|
||||||
|
|
||||||
**** Add VerilatedScopeNameMap for introspection, bug966. [Todd Strader]
|
**** Add VerilatedScopeNameMap for introspection, bug966. [Todd Strader]
|
||||||
|
|
||||||
**** Fix very long module names, bug937. [Todd Strader]
|
**** Fix very long module names, bug937. [Todd Strader]
|
||||||
|
|
|
@ -3340,6 +3340,10 @@ with "unused" in the name, or put the appropriate lint_off around the wire.
|
||||||
Having unused signals in one place makes it easy to find what is unused,
|
Having unused signals in one place makes it easy to find what is unused,
|
||||||
and reduces the number of lint_off pragmas, reducing bugs.
|
and reduces the number of lint_off pragmas, reducing bugs.
|
||||||
|
|
||||||
|
=item USERINFO, USERWARN, USERERROR, USERFATAL
|
||||||
|
|
||||||
|
A SystemVerilog elaboration-time assertion print was executed.
|
||||||
|
|
||||||
=item VARHIDDEN
|
=item VARHIDDEN
|
||||||
|
|
||||||
Warns that a task, function, or begin/end block is declaring a variable by
|
Warns that a task, function, or begin/end block is declaring a variable by
|
||||||
|
|
|
@ -96,6 +96,10 @@ public:
|
||||||
UNPACKED, // Unsupported unpacked
|
UNPACKED, // Unsupported unpacked
|
||||||
UNSIGNED, // Comparison is constant due to unsigned arithmetic
|
UNSIGNED, // Comparison is constant due to unsigned arithmetic
|
||||||
UNUSED, // No receivers
|
UNUSED, // No receivers
|
||||||
|
USERERROR, // Elaboration time $error
|
||||||
|
USERFATAL, // Elaboration time $fatal
|
||||||
|
USERINFO, // Elaboration time $info
|
||||||
|
USERWARN, // Elaboration time $warning
|
||||||
VARHIDDEN, // Hiding variable
|
VARHIDDEN, // Hiding variable
|
||||||
WIDTH, // Width mismatch
|
WIDTH, // Width mismatch
|
||||||
WIDTHCONCAT, // Unsized numbers/parameters in concatenations
|
WIDTHCONCAT, // Unsized numbers/parameters in concatenations
|
||||||
|
@ -132,6 +136,7 @@ public:
|
||||||
"REALCVT", "REDEFMACRO",
|
"REALCVT", "REDEFMACRO",
|
||||||
"SELRANGE", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
|
"SELRANGE", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
|
||||||
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNPACKED", "UNSIGNED", "UNUSED",
|
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNPACKED", "UNSIGNED", "UNUSED",
|
||||||
|
"USERERROR", "USERFATAL", "USERINFO", "USERWARN",
|
||||||
"VARHIDDEN", "WIDTH", "WIDTHCONCAT",
|
"VARHIDDEN", "WIDTH", "WIDTHCONCAT",
|
||||||
" MAX"
|
" MAX"
|
||||||
};
|
};
|
||||||
|
|
|
@ -343,13 +343,6 @@ private:
|
||||||
virtual void visit(AstDisplay* nodep, AstNUser* vup) {
|
virtual void visit(AstDisplay* nodep, AstNUser* vup) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (nodep->filep()) expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
|
if (nodep->filep()) expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
|
||||||
if (!m_assertp
|
|
||||||
&& (nodep->displayType() == AstDisplayType::DT_INFO
|
|
||||||
|| nodep->displayType() == AstDisplayType::DT_WARNING
|
|
||||||
|| nodep->displayType() == AstDisplayType::DT_ERROR
|
|
||||||
|| nodep->displayType() == AstDisplayType::DT_FATAL)) {
|
|
||||||
nodep->v3error(nodep->verilogKwd()+" only allowed under an assertion.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstUdpTable* nodep, AstNUser*) {
|
virtual void visit(AstUdpTable* nodep, AstNUser*) {
|
||||||
|
|
|
@ -580,6 +580,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstStop* nodep, AstNUser*) {
|
virtual void visit(AstStop* nodep, AstNUser*) {
|
||||||
|
if (jumpingOver(nodep)) return;
|
||||||
if (m_params) { // This message seems better than an obscure $stop
|
if (m_params) { // This message seems better than an obscure $stop
|
||||||
// The spec says $stop is just ignored, it seems evil to ignore assertions
|
// The spec says $stop is just ignored, it seems evil to ignore assertions
|
||||||
clearOptimizable(nodep,"$stop executed during function constification; maybe indicates assertion firing");
|
clearOptimizable(nodep,"$stop executed during function constification; maybe indicates assertion firing");
|
||||||
|
@ -695,9 +696,78 @@ private:
|
||||||
if (!m_params) { badNodeType(nodep); return; }
|
if (!m_params) { badNodeType(nodep); return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void visit(AstSFormatF *nodep, AstNUser *) {
|
||||||
|
if (jumpingOver(nodep)) return;
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
if (m_params) {
|
||||||
|
AstNode* nextArgp = nodep->exprsp();
|
||||||
|
|
||||||
|
string result = "";
|
||||||
|
string format = nodep->text();
|
||||||
|
string::const_iterator pos = format.begin();
|
||||||
|
bool inPct = false;
|
||||||
|
for (; pos != format.end(); ++pos) {
|
||||||
|
if (!inPct && pos[0] == '%') {
|
||||||
|
inPct = true;
|
||||||
|
} else if (!inPct) { // Normal text
|
||||||
|
result += *pos;
|
||||||
|
} else { // Format character
|
||||||
|
AstNode* argp = nextArgp;
|
||||||
|
inPct = false;
|
||||||
|
nextArgp = nextArgp->nextp();
|
||||||
|
|
||||||
|
if (V3Number::displayedFmtLegal(tolower(pos[0]))) {
|
||||||
|
V3Number* nump = fetchNumberNull(argp);
|
||||||
|
if (!nump) {
|
||||||
|
clearOptimizable(nodep, "Argument for $display like statement is not constant");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
string format = string("%") + pos[0];
|
||||||
|
result += nump->displayed(format);
|
||||||
|
} else {
|
||||||
|
switch (tolower(pos[0])) {
|
||||||
|
case '%':
|
||||||
|
result += "%";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
clearOptimizable(nodep, "Unknown $display-like format code.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodep->text(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void visit(AstDisplay *nodep, AstNUser *) {
|
||||||
|
if (jumpingOver(nodep)) return;
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
if (m_params) {
|
||||||
|
switch (nodep->displayType()) {
|
||||||
|
case AstDisplayType::DT_DISPLAY: // FALLTHRU
|
||||||
|
case AstDisplayType::DT_INFO:
|
||||||
|
v3warn(USERINFO, nodep->fmtp()->text());
|
||||||
|
break;
|
||||||
|
case AstDisplayType::DT_ERROR:
|
||||||
|
v3warn(USERERROR, nodep->fmtp()->text());
|
||||||
|
break;
|
||||||
|
case AstDisplayType::DT_WARNING:
|
||||||
|
v3warn(USERWARN, nodep->fmtp()->text());
|
||||||
|
break;
|
||||||
|
case AstDisplayType::DT_FATAL:
|
||||||
|
v3warn(USERFATAL, nodep->fmtp()->text());
|
||||||
|
break;
|
||||||
|
case AstDisplayType::DT_WRITE: // FALLTHRU
|
||||||
|
default:
|
||||||
|
clearOptimizable(nodep, "Unexpected display type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// default
|
// default
|
||||||
// These types are definately not reducable
|
// These types are definately not reducable
|
||||||
// AstCoverInc, AstDisplay, AstArraySel, AstStop, AstFinish,
|
// AstCoverInc, AstArraySel, AstFinish,
|
||||||
// AstRand, AstTime, AstUCFunc, AstCCall, AstCStmt, AstUCStmt
|
// AstRand, AstTime, AstUCFunc, AstCCall, AstCStmt, AstUCStmt
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
if (jumpingOver(nodep)) return;
|
if (jumpingOver(nodep)) return;
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 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.
|
||||||
|
|
||||||
|
compile (
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
check_finished=>1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
|
@ -0,0 +1,24 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2015 by Johan Bjork.
|
||||||
|
|
||||||
|
module t;
|
||||||
|
localparam str = "string";
|
||||||
|
function logic checkParameter(input logic [8:0] N);
|
||||||
|
if (N == 1)
|
||||||
|
return 0;
|
||||||
|
$fatal(1, "Parameter %d is invalid...%s and %s", N, str, "constant both work");
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
`ifdef FAILING_ASSERTIONS
|
||||||
|
localparam x = checkParameter(5);
|
||||||
|
`else
|
||||||
|
localparam x = checkParameter(1);
|
||||||
|
`endif
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
|
@ -0,0 +1,28 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003-2009 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.
|
||||||
|
|
||||||
|
top_filename("t/t_assert_elab.v");
|
||||||
|
unlink("$Self->{obj_dir}/t_assert_elab_bad.log");
|
||||||
|
|
||||||
|
|
||||||
|
compile (
|
||||||
|
v_flags2 => ['+define+FAILING_ASSERTIONS',
|
||||||
|
$Self->{v3}?'--assert':($Self->{nc}?'+assert':'')],
|
||||||
|
fails => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
execute (
|
||||||
|
fails => $Self->{vlt},
|
||||||
|
);
|
||||||
|
|
||||||
|
file_grep ("$Self->{obj_dir}/vlt_compile.log",
|
||||||
|
qr/%Warning-USERFATAL: Parameter 5 is invalid...string and constant both work/);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
Loading…
Reference in New Issue