Add BOUNDED warning and promote bounded queues to unbounded.

This commit is contained in:
Wilson Snyder 2019-12-08 15:56:49 -05:00
parent 3be0eea995
commit cda5c53cf9
10 changed files with 108 additions and 27 deletions

View File

@ -4,6 +4,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 4.025 devel
*** Add BOUNDED warning and promote bounded queues to unbounded.
* Verilator 4.024 2019-12-08

View File

@ -3743,6 +3743,14 @@ generally unrolls small loops. You may want to try increasing
--unroll-count (and occasionally --unroll-stmts) which will raise the small
loop bar to avoid this error.
=item BOUNDED
This indicates that bounded queues (e.g. "var name[$ : 3]") are
unsupported.
Ignoring this warning may make Verilator simulations differ from other
simulators.
=item BSSPACE
Warns that a backslash is followed by a space then a newline. Likely the

View File

@ -105,6 +105,7 @@ public:
SYMRSVDWORD, // Symbol is Reserved Word
SYNCASYNCNET, // Mixed sync + async reset
TICKCOUNT, // Too large tick count
UNBOUNDED, // Unbounded queue
UNDRIVEN, // No drivers
UNOPT, // Unoptimizable block
UNOPTFLAT, // Unoptimizable block after flattening
@ -154,7 +155,7 @@ public:
"REALCVT", "REDEFMACRO",
"SELRANGE", "SHORTREAL", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
"TICKCOUNT",
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS",
"UNBOUNDED", "UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS",
"UNPACKED", "UNSIGNED", "UNUSED",
"USERERROR", "USERFATAL", "USERINFO", "USERWARN",
"VARHIDDEN", "WIDTH", "WIDTHCONCAT",

View File

@ -116,11 +116,17 @@ AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep,
if (rangep && isPacked) {
arrayp = new AstPackArrayDType
(rangep->fileline(), VFlagChildDType(), arrayp, rangep);
} else if (rangep) {
if (VN_IS(rangep->leftp(), Unbounded)
|| VN_IS(rangep->rightp(), Unbounded)) {
rangep->v3error("Unsupported: Bounded queues. Suggest use unbounded.");
} else if (VN_IS(nrangep, QueueRange)) {
arrayp = new AstQueueDType
(nrangep->fileline(), VFlagChildDType(), arrayp);
} else if (rangep && (VN_IS(rangep->leftp(), Unbounded)
|| VN_IS(rangep->rightp(), Unbounded))) {
if (!VN_IS(rangep->rightp(), Unbounded)) {
rangep->v3warn(UNBOUNDED,
"Unsupported: Bounded queues. Converting to unbounded.");
}
arrayp = new AstQueueDType(nrangep->fileline(), VFlagChildDType(), arrayp);
} else if (rangep) {
arrayp = new AstUnpackArrayDType
(rangep->fileline(), VFlagChildDType(), arrayp, rangep);
} else if (VN_IS(nrangep, UnsizedRange)) {
@ -131,9 +137,6 @@ AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep,
AstNodeDType* keyp = arangep->keyDTypep(); keyp->unlinkFrBack();
arrayp = new AstAssocArrayDType
(nrangep->fileline(), VFlagChildDType(), arrayp, keyp);
} else if (VN_IS(nrangep, QueueRange)) {
arrayp = new AstQueueDType
(nrangep->fileline(), VFlagChildDType(), arrayp);
} else {
UASSERT_OBJ(0, nrangep, "Expected range or unsized range");
}

View File

@ -1935,28 +1935,46 @@ private:
newp->protect(false);
newp->makeStatement();
} else {
nodep->v3error("Unsupported: Queue .delete(index) method, as is O(n) complexity and slow.");
AstNode* index_exprp = methodCallQueueIndexExpr(nodep);
newp = new AstCMethodCall(nodep->fileline(),
nodep->fromp()->unlinkFrBack(),
"erase", index_exprp->unlinkFrBack());
newp->protect(false);
newp->makeStatement();
if (index_exprp->isZero()) { // delete(0) is a pop_front
newp = new AstCMethodCall(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 AstCMethodCall(nodep->fileline(),
nodep->fromp()->unlinkFrBack(),
"erase", index_exprp->unlinkFrBack());
newp->protect(false);
newp->makeStatement();
}
}
} else if (nodep->name() == "insert") {
nodep->v3error("Unsupported: Queue .insert method, as is O(n) complexity and slow.");
methodOkArguments(nodep, 2, 2);
methodCallLValue(nodep, nodep->fromp(), true);
AstNode* index_exprp = methodCallQueueIndexExpr(nodep);
AstArg* argp = VN_CAST(nodep->pinsp()->nextp(), Arg);
iterateCheckTyped(nodep, "insert value", argp->exprp(), adtypep->subDTypep(), BOTH);
newp = new AstCMethodCall(nodep->fileline(),
nodep->fromp()->unlinkFrBack(),
nodep->name(),
index_exprp->unlinkFrBack());
newp->addPinsp(argp->exprp()->unlinkFrBack());
newp->protect(false);
newp->makeStatement();
if (index_exprp->isZero()) { // insert(0, ...) is a push_front
newp = new AstCMethodCall(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 AstCMethodCall(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") {
methodOkArguments(nodep, 0, 0);

View File

@ -72,6 +72,15 @@ module t (/*AUTOARG*/
i = q.size(); `checkh(i, 0);
v = q.pop_front(); `checks(v, ""); // Was empty, optional warning
v = q.pop_back(); `checks(v, ""); // Was empty, optional warning
// COnversion of insert/delete with zero to operator
q.push_front("front");
q.insert(0, "newfront");
i = q.size(); `checkh(i, 2);
q.delete(0);
i = q.size(); `checkh(i, 1);
`checks(q[0], "front");
end
// See t_queue_unsup_bad for more unsupported stuff

View File

@ -0,0 +1,20 @@
#!/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.
scenarios(simulator => 1);
compile(
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,23 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by Wilson Snyder.
module t (/*AUTOARG*/);
// verilator lint_off UNBOUNDED
int q[$ : 3];
initial begin
q.push_front(1);
q.push_front(1);
q.push_front(1);
if (q.size() != 3) $stop;
q.push_front(1);
// TODO correct answer when supported:
//if (q.size() != 3) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -1,4 +1,5 @@
%Error: t/t_queue_bounded_unsup_bad.v:7: Unsupported: Bounded queues. Suggest use unbounded.
%Warning-UNBOUNDED: t/t_queue_bounded_unsup_bad.v:7: Unsupported: Bounded queues. Converting to unbounded.
int q[$ : 3];
^
... Use "/* verilator lint_off UNBOUNDED */" and lint_on around source to disable this message.
%Error: Exiting due to

View File

@ -6,10 +6,6 @@
: ... In instance t
q.delete(1);
^~~~~~
%Error: t/t_queue_unsup_bad.v:26: Unsupported: Queue .insert method, as is O(n) complexity and slow.
: ... In instance t
q.insert(0, "ins0");
^~~~~~
%Error: t/t_queue_unsup_bad.v:27: Unsupported: Queue .insert method, as is O(n) complexity and slow.
: ... In instance t
q.insert(2, "ins2");