mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Support inside array constraints (#5448)
Signed-off-by: Arkadiusz Kozdra <akozdra@antmicro.com>
This commit is contained in:
parent
371a4055b0
commit
dd95e033e7
@ -557,6 +557,21 @@ class ConstraintExprVisitor final : public VNVisitor {
|
|||||||
return new AstSFormatF{fl, fmt.str(), false, exprsp};
|
return new AstSFormatF{fl, fmt.str(), false, exprsp};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AstNodeExpr* newSel(FileLine* fl, AstNodeExpr* arrayp, AstNodeExpr* idxp) {
|
||||||
|
// similar to V3WidthSel.cpp
|
||||||
|
AstNodeDType* const arrDtp = arrayp->unlinkFrBack()->dtypep();
|
||||||
|
AstNodeExpr* selp = nullptr;
|
||||||
|
if (VN_IS(arrDtp, QueueDType) || VN_IS(arrDtp, DynArrayDType))
|
||||||
|
selp = new AstCMethodHard{fl, arrayp, "at", idxp};
|
||||||
|
else if (VN_IS(arrDtp, UnpackArrayDType))
|
||||||
|
selp = new AstArraySel{fl, arrayp, idxp};
|
||||||
|
else if (VN_IS(arrDtp, AssocArrayDType))
|
||||||
|
selp = new AstAssocSel{fl, arrayp, idxp};
|
||||||
|
UASSERT_OBJ(selp, arrayp, "Selecting from non-array?");
|
||||||
|
selp->dtypep(arrDtp->subDTypep());
|
||||||
|
return selp;
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
void visit(AstNodeVarRef* nodep) override {
|
void visit(AstNodeVarRef* nodep) override {
|
||||||
AstVar* const varp = nodep->varp();
|
AstVar* const varp = nodep->varp();
|
||||||
@ -699,8 +714,7 @@ class ConstraintExprVisitor final : public VNVisitor {
|
|||||||
new AstForeach{fl, nodep->arrayp()->unlinkFrBack(), new AstCStmt{fl, cstmtp}},
|
new AstForeach{fl, nodep->arrayp()->unlinkFrBack(), new AstCStmt{fl, cstmtp}},
|
||||||
false, true});
|
false, true});
|
||||||
exprsp->addNext(
|
exprsp->addNext(
|
||||||
new AstText{fl, "return ret.empty() ? \"#b1\" : \"(bvand \" + ret + \")\";"});
|
new AstText{fl, "return ret.empty() ? \"#b1\" : \"(bvand\" + ret + \")\";})()"});
|
||||||
exprsp->addNext(new AstText{fl, "return ret + \")\"; })()"});
|
|
||||||
AstNodeExpr* const newp = new AstCExpr{fl, exprsp};
|
AstNodeExpr* const newp = new AstCExpr{fl, exprsp};
|
||||||
newp->dtypeSetString();
|
newp->dtypeSetString();
|
||||||
nodep->replaceWith(new AstSFormatF{fl, "%@", false, newp});
|
nodep->replaceWith(new AstSFormatF{fl, "%@", false, newp});
|
||||||
@ -741,18 +755,45 @@ class ConstraintExprVisitor final : public VNVisitor {
|
|||||||
}
|
}
|
||||||
void visit(AstCMethodHard* nodep) override {
|
void visit(AstCMethodHard* nodep) override {
|
||||||
if (editFormat(nodep)) return;
|
if (editFormat(nodep)) return;
|
||||||
|
FileLine* const fl = nodep->fileline();
|
||||||
|
|
||||||
if (nodep->name() == "at" && nodep->fromp()->user1()) {
|
if (nodep->name() == "at" && nodep->fromp()->user1()) {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
AstNodeExpr* const argsp
|
AstNodeExpr* const argsp
|
||||||
= AstNode::addNext(nodep->fromp()->unlinkFrBack(), nodep->pinsp()->unlinkFrBack());
|
= AstNode::addNext(nodep->fromp()->unlinkFrBack(), nodep->pinsp()->unlinkFrBack());
|
||||||
AstSFormatF* const newp
|
AstSFormatF* const newp = new AstSFormatF{fl, "(select %@ %@)", false, argsp};
|
||||||
= new AstSFormatF{nodep->fileline(), "(select %@ %@)", false, argsp};
|
|
||||||
nodep->replaceWith(newp);
|
nodep->replaceWith(newp);
|
||||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nodep->name() == "inside") {
|
||||||
|
bool randArr = nodep->fromp()->user1();
|
||||||
|
|
||||||
|
AstVar* const newVarp
|
||||||
|
= new AstVar{fl, VVarType::BLOCKTEMP, "__Vinside", nodep->findSigned32DType()};
|
||||||
|
AstNodeExpr* const idxRefp = new AstVarRef{nodep->fileline(), newVarp, VAccess::READ};
|
||||||
|
AstSelLoopVars* const arrayp
|
||||||
|
= new AstSelLoopVars{fl, nodep->fromp()->cloneTreePure(false), newVarp};
|
||||||
|
AstNodeExpr* const selp = newSel(nodep->fileline(), nodep->fromp(), idxRefp);
|
||||||
|
selp->user1(randArr);
|
||||||
|
AstNode* const itemp = new AstEq{fl, selp, nodep->pinsp()->unlinkFrBack()};
|
||||||
|
itemp->user1(true);
|
||||||
|
AstNode* const cstmtp = new AstText{fl, "ret += \" \" + "};
|
||||||
|
cstmtp->addNext(iterateSubtreeReturnEdits(itemp));
|
||||||
|
cstmtp->addNext(new AstText{fl, ";"});
|
||||||
|
AstNode* const exprsp = new AstText{fl, "([&]{ std::string ret;"};
|
||||||
|
exprsp->addNext(new AstBegin{
|
||||||
|
fl, "", new AstForeach{fl, arrayp, new AstCStmt{fl, cstmtp}}, false, true});
|
||||||
|
exprsp->addNext(
|
||||||
|
new AstText{fl, "return ret.empty() ? \"#b0\" : \"(bvor\" + ret + \")\";})()"});
|
||||||
|
AstNodeExpr* const newp = new AstCExpr{fl, exprsp};
|
||||||
|
newp->dtypeSetString();
|
||||||
|
nodep->replaceWith(new AstSFormatF{fl, "%@", false, newp});
|
||||||
|
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
nodep->v3warn(CONSTRAINTIGN,
|
nodep->v3warn(CONSTRAINTIGN,
|
||||||
"Unsupported: randomizing this expression, treating as state");
|
"Unsupported: randomizing this expression, treating as state");
|
||||||
nodep->user1(false);
|
nodep->user1(false);
|
||||||
|
@ -20,12 +20,18 @@ begin \
|
|||||||
end
|
end
|
||||||
|
|
||||||
class C;
|
class C;
|
||||||
rand int x, y;
|
rand int x, y, z, w;
|
||||||
|
int que[$] = '{3, 4, 5};
|
||||||
|
int arr[3] = '{5, 6, 7};
|
||||||
constraint distrib {
|
constraint distrib {
|
||||||
x dist { [1:3] := 0, [5:6], [9:15] :/ 0 };
|
x dist { [1:3] := 0, [5:6], [9:15] :/ 0 };
|
||||||
y dist { [1:3] := 0, 5, 6 := 8, [9:15] :/ 0 };
|
y dist { [1:3] := 0, 5, 6 := 8, [9:15] :/ 0 };
|
||||||
x < 20;
|
x < 20;
|
||||||
};
|
};
|
||||||
|
constraint distinside {
|
||||||
|
z dist {que};
|
||||||
|
w dist {arr};
|
||||||
|
};
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
module t;
|
module t;
|
||||||
@ -33,6 +39,8 @@ module t;
|
|||||||
C c = new;
|
C c = new;
|
||||||
`check_rand(c, c.x, 5 <= c.x && c.x <= 6);
|
`check_rand(c, c.x, 5 <= c.x && c.x <= 6);
|
||||||
`check_rand(c, c.y, 5 <= c.y && c.y <= 6);
|
`check_rand(c, c.y, 5 <= c.y && c.y <= 6);
|
||||||
|
`check_rand(c, c.z, 3 <= c.z && c.z <= 5);
|
||||||
|
`check_rand(c, c.w, 5 <= c.w && c.w <= 7);
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
%Warning-CONSTRAINTIGN: t/t_constraint_dist_unsup.v:27:10: Constraint expression ignored (imperfect distribution)
|
|
||||||
: ... note: In instance 't'
|
|
||||||
27 | x dist {que};
|
|
||||||
| ^~~~
|
|
||||||
... For warning description see https://verilator.org/warn/CONSTRAINTIGN?v=latest
|
|
||||||
... Use "/* verilator lint_off CONSTRAINTIGN */" and lint_on around source to disable this message.
|
|
||||||
%Warning-CONSTRAINTIGN: t/t_constraint_dist_unsup.v:28:10: Constraint expression ignored (imperfect distribution)
|
|
||||||
: ... note: In instance 't'
|
|
||||||
28 | y dist {arr};
|
|
||||||
| ^~~~
|
|
||||||
%Warning-CONSTRAINTIGN: t/t_constraint_dist_unsup.v:27:10: Unsupported: randomizing this expression, treating as state
|
|
||||||
27 | x dist {que};
|
|
||||||
| ^~~~
|
|
||||||
%Warning-CONSTRAINTIGN: t/t_constraint_dist_unsup.v:28:10: Unsupported: randomizing this expression, treating as state
|
|
||||||
28 | y dist {arr};
|
|
||||||
| ^~~~
|
|
||||||
%Error: Exiting due to
|
|
@ -1,16 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
|
||||||
#
|
|
||||||
# Copyright 2024 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
|
|
||||||
|
|
||||||
import vltest_bootstrap
|
|
||||||
|
|
||||||
test.scenarios('linter')
|
|
||||||
|
|
||||||
test.lint(fails=test.vlt_all, expect_filename=test.golden_filename)
|
|
||||||
|
|
||||||
test.passes()
|
|
@ -1,40 +0,0 @@
|
|||||||
// DESCRIPTION: Verilator: Verilog Test module
|
|
||||||
//
|
|
||||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
|
||||||
// any use, without warranty, 2024 by Antmicro Ltd.
|
|
||||||
// SPDX-License-Identifier: CC0-1.0
|
|
||||||
|
|
||||||
`define check_rand(cl, field, cond) \
|
|
||||||
begin \
|
|
||||||
longint prev_result; \
|
|
||||||
int ok = 0; \
|
|
||||||
for (int i = 0; i < 10; i++) begin \
|
|
||||||
longint result; \
|
|
||||||
if (!bit'(cl.randomize())) $stop; \
|
|
||||||
result = longint'(field); \
|
|
||||||
if (!(cond)) $stop; \
|
|
||||||
if (i > 0 && result != prev_result) ok = 1; \
|
|
||||||
prev_result = result; \
|
|
||||||
end \
|
|
||||||
if (ok != 1) $stop; \
|
|
||||||
end
|
|
||||||
|
|
||||||
class C;
|
|
||||||
int que[$] = '{3, 4, 5};
|
|
||||||
int arr[3] = '{5, 6, 7};
|
|
||||||
rand int x, y;
|
|
||||||
constraint distrib {
|
|
||||||
x dist {que};
|
|
||||||
y dist {arr};
|
|
||||||
};
|
|
||||||
endclass
|
|
||||||
|
|
||||||
module t;
|
|
||||||
initial begin
|
|
||||||
C c = new;
|
|
||||||
`check_rand(c, c.x, 3 <= c.x && c.x <= 5);
|
|
||||||
`check_rand(c, c.y, 5 <= c.y && c.y <= 7);
|
|
||||||
$write("*-* All Finished *-*\n");
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
endmodule
|
|
Loading…
Reference in New Issue
Block a user