forked from github/verilator
Support $isunbounded and parameter $. (#2104)
This commit is contained in:
parent
8850ca962e
commit
72bd91c7f1
2
Changes
2
Changes
@ -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]
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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; }
|
||||
|
@ -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); }
|
||||
|
@ -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
21
test_regress/t/t_unbounded.pl
Executable 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;
|
23
test_regress/t/t_unbounded.v
Normal file
23
test_regress/t/t_unbounded.v
Normal 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
|
Loading…
Reference in New Issue
Block a user