Support $isunbounded and parameter $. (#2104)

This commit is contained in:
Wilson Snyder 2020-05-07 21:09:14 -04:00
parent 8850ca962e
commit 72bd91c7f1
10 changed files with 97 additions and 9 deletions

View File

@ -5,6 +5,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 4.035 devel
**** Support $isunbounded and parameter $. (#2104)
**** Fix FST tracing of little bit endian signals. [Geza Lore]
**** Fix +: and -: on unpacked arrays. (#2304) [engr248]

View File

@ -2886,14 +2886,18 @@ public:
AstNode* rhsp() const { return op2p(); }
};
class AstUnbounded : public AstNode {
class AstUnbounded : public AstNodeMath {
// A $ in the parser, used for unbounded and queues
// Due to where is used, treated as Signed32
public:
explicit AstUnbounded(FileLine* fl)
: ASTGEN_SUPER(fl) {}
: ASTGEN_SUPER(fl) {
dtypeSetSigned32();
}
ASTNODE_NODE_FUNCS(Unbounded)
virtual string emitVerilog() { return "$"; }
virtual string emitC() { V3ERROR_NA_RETURN(""); }
virtual bool cleanOut() const { return true; }
};
//######################################################################
@ -5449,6 +5453,24 @@ public:
virtual bool cleanLhs() const { return false; }
virtual bool sizeMattersLhs() const { return false; }
};
class AstIsUnbounded : public AstNodeUniop {
// True if is unmbounded ($)
public:
AstIsUnbounded(FileLine* fl, AstNode* lhsp)
: ASTGEN_SUPER(fl, lhsp) {
dtypeSetLogicBool();
}
ASTNODE_NODE_FUNCS(IsUnbounded)
virtual void numberOperate(V3Number& out, const V3Number&) {
// Any constant isn't unbounded
out.setZero();
}
virtual string emitVerilog() { return "%f$isunbounded(%l)"; }
virtual string emitC() { V3ERROR_NA_RETURN(""); }
virtual bool cleanOut() const { return false; }
virtual bool cleanLhs() const { return false; }
virtual bool sizeMattersLhs() const { return false; }
};
class AstOneHot : public AstNodeUniop {
// True if only single bit set in vector
public:

View File

@ -1629,6 +1629,11 @@ private:
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
did = true;
} else if (nodep->varp()->isParam() && VN_IS(valuep, Unbounded)) {
AstNode* newp = valuep->cloneTree(false);
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
did = true;
}
}
}
@ -2141,6 +2146,7 @@ private:
}
virtual void visit(AstInitArray* nodep) VL_OVERRIDE { iterateChildren(nodep); }
virtual void visit(AstInitItem* nodep) VL_OVERRIDE { iterateChildren(nodep); }
virtual void visit(AstUnbounded* nodep) VL_OVERRIDE { iterateChildren(nodep); }
// These are converted by V3Param. Don't constify as we don't want the
// from() VARREF to disappear, if any.
// If output of a presel didn't get consted, chances are V3Param didn't visit properly
@ -2531,6 +2537,9 @@ private:
TREEOPC("AstPutcN{$lhsp.castConst, $rhsp.castConst, $thsp.castConst}", "replaceConst(nodep)");
TREEOPC("AstSubstrN{$lhsp.castConst, $rhsp.castConst, $thsp.castConst}", "replaceConst(nodep)");
TREEOPC("AstCvtPackString{$lhsp.castConst}", "replaceConstString(nodep, VN_CAST(nodep->lhsp(), Const)->num().toString())");
// Custom
// Implied by AstIsUnbounded::numberOperate: V("AstIsUnbounded{$lhsp.castConst}", "replaceNum(nodep, 0)");
TREEOPV("AstIsUnbounded{$lhsp.castUnbounded}", "replaceNum(nodep, 1)");
// clang-format on
// Possible futures:

View File

@ -301,7 +301,8 @@ private:
<< " (IEEE 1800-2017 6.20.1): " << nodep->prettyNameQ());
} else {
V3Const::constifyParamsEdit(nodep); // The variable, not just the var->init()
if (!VN_IS(nodep->valuep(), Const)) { // Complex init, like an array
if (!VN_IS(nodep->valuep(), Const)
&& !VN_IS(nodep->valuep(), Unbounded)) { // Complex init, like an array
// Make a new INITIAL to set the value.
// This allows the normal array/struct handling code to properly
// initialize the parameter.

View File

@ -1045,7 +1045,18 @@ private:
}
}
virtual void visit(AstUnbounded* nodep) VL_OVERRIDE {
nodep->v3error("Unsupported/illegal unbounded ('$') in this context.");
nodep->dtypeSetSigned32(); // Used in int context
if (!VN_IS(nodep->backp(), IsUnbounded)
&& !(VN_IS(nodep->backp(), Var)
&& VN_CAST(nodep->backp(), Var)->isParam())) {
nodep->v3error("Unsupported/illegal unbounded ('$') in this context.");
}
}
virtual void visit(AstIsUnbounded* nodep) VL_OVERRIDE {
if (m_vup->prelim()) {
userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p());
nodep->dtypeSetLogicBool();
}
}
virtual void visit(AstUCFunc* nodep) VL_OVERRIDE {
// Give it the size the user wants.

View File

@ -441,6 +441,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$high" { FL; return yD_HIGH; }
"$increment" { FL; return yD_INCREMENT; }
"$info" { FL; return yD_INFO; }
"$isunbounded" { FL; return yD_ISUNBOUNDED; }
"$isunknown" { FL; return yD_ISUNKNOWN; }
"$left" { FL; return yD_LEFT; }
"$low" { FL; return yD_LOW; }

View File

@ -595,6 +595,7 @@ class AstSenTree;
%token<fl> yD_HYPOT "$hypot"
%token<fl> yD_INCREMENT "$increment"
%token<fl> yD_INFO "$info"
%token<fl> yD_ISUNBOUNDED "$isunbounded"
%token<fl> yD_ISUNKNOWN "$isunknown"
%token<fl> yD_ITOR "$itor"
%token<fl> yD_LEFT "$left"
@ -3408,7 +3409,8 @@ system_f_call_or_t<nodep>: // IEEE: part of system_tf_call (can be task or func)
| yD_HYPOT '(' expr ',' expr ')' { $$ = new AstHypotD($1,$3,$5); }
| yD_INCREMENT '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_INCREMENT,$3,NULL); }
| yD_INCREMENT '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_INCREMENT,$3,$5); }
| yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); }
| yD_ISUNBOUNDED '(' expr ')' { $$ = new AstIsUnbounded($1, $3); }
| yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1, $3); }
| yD_ITOR '(' expr ')' { $$ = new AstIToRD($1,$3); }
| yD_LEFT '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LEFT,$3,NULL); }
| yD_LEFT '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LEFT,$3,$5); }

View File

@ -34,10 +34,6 @@
: ... In instance t
38 | q = {q[0], q[2:$]};
| ^
%Error: t/t_queue_unsup_bad.v:38:22: Expecting expression to be constant, but can't convert a UNBOUNDED to constant.
: ... In instance t
38 | q = {q[0], q[2:$]};
| ^
%Error: t/t_queue_unsup_bad.v:38:22: First value of [a:b] isn't a constant, maybe you want +: or -:
: ... In instance t
38 | q = {q[0], q[2:$]};

21
test_regress/t/t_unbounded.pl Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-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 under the Creative Commons Public Domain, for
// any use, without warranty, 2014 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t();
localparam UNB = $;
localparam int UNB2 = $;
localparam SIX = 6;
initial begin
if ($bits($isunbounded(0)) !== 1) $stop;
if ($isunbounded(0) !== 1'b0) $stop;
if ($isunbounded(SIX) !== 0) $stop;
if ($isunbounded($) !== 1) $stop;
if ($isunbounded(UNB) !== 1) $stop;
if ($isunbounded(UNB2) !== 1) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule