Fix handling of rand fields not referenced in constraints (#5305)
Signed-off-by: Ryszard Rozak <rrozak@antmicro.com>
This commit is contained in:
parent
0d43c14b93
commit
b9e1d55262
|
|
@ -743,6 +743,51 @@ class RandomizeVisitor final : public VNVisitor {
|
|||
return clearp->makeStmt();
|
||||
}
|
||||
|
||||
void addBasicRandomizeBody(AstFunc* const basicRandomizep, AstClass* const nodep) {
|
||||
FileLine* const fl = nodep->fileline();
|
||||
AstVar* const basicFvarp = VN_AS(basicRandomizep->fvarp(), Var);
|
||||
AstVarRef* const basicFvarRefp = new AstVarRef{fl, basicFvarp, VAccess::WRITE};
|
||||
AstConst* const beginBasicValp = new AstConst{fl, AstConst::WidthedValue{}, 32, 1};
|
||||
basicRandomizep->addStmtsp(new AstAssign{fl, basicFvarRefp, beginBasicValp});
|
||||
|
||||
nodep->foreachMember([&](AstClass* classp, AstVar* memberVarp) {
|
||||
if (!memberVarp->isRand() || memberVarp->user3()) return;
|
||||
const AstNodeDType* const dtypep = memberVarp->dtypep()->skipRefp();
|
||||
if (VN_IS(dtypep, BasicDType) || VN_IS(dtypep, StructDType)) {
|
||||
AstVar* const randcVarp = newRandcVarsp(memberVarp);
|
||||
AstVarRef* const refp = new AstVarRef{fl, classp, memberVarp, VAccess::WRITE};
|
||||
AstNodeStmt* const stmtp = newRandStmtsp(fl, refp, randcVarp);
|
||||
basicRandomizep->addStmtsp(stmtp);
|
||||
} else if (const AstClassRefDType* const classRefp = VN_CAST(dtypep, ClassRefDType)) {
|
||||
if (classRefp->classp() == nodep) {
|
||||
memberVarp->v3warn(E_UNSUPPORTED,
|
||||
"Unsupported: random member variable with the "
|
||||
"type of the containing class");
|
||||
return;
|
||||
}
|
||||
AstFunc* const memberFuncp
|
||||
= V3Randomize::newRandomizeFunc(m_memberMap, classRefp->classp());
|
||||
AstMethodCall* const callp
|
||||
= new AstMethodCall{fl, new AstVarRef{fl, classp, memberVarp, VAccess::WRITE},
|
||||
"randomize", nullptr};
|
||||
callp->taskp(memberFuncp);
|
||||
callp->dtypeFrom(memberFuncp);
|
||||
AstVarRef* const basicFvarRefReadp = basicFvarRefp->cloneTree(false);
|
||||
basicFvarRefReadp->access(VAccess::READ);
|
||||
AstIf* const assignIfNotNullp = new AstIf{
|
||||
fl,
|
||||
new AstNeq{fl, new AstVarRef{fl, classp, memberVarp, VAccess::READ},
|
||||
new AstConst{fl, AstConst::Null{}}},
|
||||
new AstAssign{fl, basicFvarRefp->cloneTree(false),
|
||||
new AstAnd{fl, basicFvarRefReadp, callp}}};
|
||||
basicRandomizep->addStmtsp(assignIfNotNullp);
|
||||
} else {
|
||||
memberVarp->v3warn(E_UNSUPPORTED, "Unsupported: random member variable with type "
|
||||
<< memberVarp->dtypep()->prettyDTypeNameQ());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
|
|
@ -815,42 +860,17 @@ class RandomizeVisitor final : public VNVisitor {
|
|||
AstNodeFTask* const newp = VN_AS(m_memberMap.findMember(nodep, "new"), NodeFTask);
|
||||
UASSERT_OBJ(newp, nodep, "No new() in class");
|
||||
|
||||
nodep->foreachMember([&](AstClass* classp, AstVar* memberVarp) {
|
||||
if (!memberVarp->isRand() || memberVarp->user3()) return;
|
||||
const AstNodeDType* const dtypep = memberVarp->dtypep()->skipRefp();
|
||||
if (VN_IS(dtypep, BasicDType) || VN_IS(dtypep, StructDType)) {
|
||||
AstVar* const randcVarp = newRandcVarsp(memberVarp);
|
||||
AstVarRef* const refp = new AstVarRef{fl, classp, memberVarp, VAccess::WRITE};
|
||||
AstNodeStmt* const stmtp = newRandStmtsp(fl, refp, randcVarp);
|
||||
randomizep->addStmtsp(stmtp);
|
||||
} else if (const AstClassRefDType* const classRefp = VN_CAST(dtypep, ClassRefDType)) {
|
||||
if (classRefp->classp() == nodep) {
|
||||
memberVarp->v3warn(E_UNSUPPORTED,
|
||||
"Unsupported: random member variable with the "
|
||||
"type of the containing class");
|
||||
return;
|
||||
}
|
||||
AstFunc* const memberFuncp
|
||||
= V3Randomize::newRandomizeFunc(m_memberMap, classRefp->classp());
|
||||
AstMethodCall* const callp
|
||||
= new AstMethodCall{fl, new AstVarRef{fl, classp, memberVarp, VAccess::WRITE},
|
||||
"randomize", nullptr};
|
||||
callp->taskp(memberFuncp);
|
||||
callp->dtypeFrom(memberFuncp);
|
||||
AstVarRef* fvarRefReadp = fvarRefp->cloneTree(false);
|
||||
fvarRefReadp->access(VAccess::READ);
|
||||
AstIf* const assignIfNotNullp = new AstIf{
|
||||
fl,
|
||||
new AstNeq{fl, new AstVarRef{fl, classp, memberVarp, VAccess::READ},
|
||||
new AstConst{fl, AstConst::Null{}}},
|
||||
new AstAssign{fl, fvarRefp->cloneTree(false),
|
||||
new AstAnd{fl, fvarRefReadp, callp}}};
|
||||
randomizep->addStmtsp(assignIfNotNullp);
|
||||
} else {
|
||||
memberVarp->v3warn(E_UNSUPPORTED, "Unsupported: random member variable with type "
|
||||
<< memberVarp->dtypep()->prettyDTypeNameQ());
|
||||
}
|
||||
});
|
||||
AstFunc* const basicRandomizep
|
||||
= V3Randomize::newRandomizeFunc(m_memberMap, nodep, "__Vbasic_randomize");
|
||||
addBasicRandomizeBody(basicRandomizep, nodep);
|
||||
AstFuncRef* const basicRandomizeCallp = new AstFuncRef{fl, "__Vbasic_randomize", nullptr};
|
||||
basicRandomizeCallp->taskp(basicRandomizep);
|
||||
basicRandomizeCallp->dtypep(basicRandomizep->dtypep());
|
||||
AstVarRef* const fvarRefReadp = fvarRefp->cloneTree(false);
|
||||
fvarRefReadp->access(VAccess::READ);
|
||||
|
||||
randomizep->addStmtsp(new AstAssign{fl, fvarRefp->cloneTree(false),
|
||||
new AstAnd{fl, fvarRefReadp, basicRandomizeCallp}});
|
||||
addPrePostCall(nodep, randomizep, "post_randomize");
|
||||
nodep->user1(false);
|
||||
}
|
||||
|
|
@ -978,6 +998,13 @@ class RandomizeVisitor final : public VNVisitor {
|
|||
|
||||
randomizeFuncp->addStmtsp(localGenp);
|
||||
|
||||
AstFunc* const basicRandomizeFuncp
|
||||
= V3Randomize::newRandomizeFunc(m_memberMap, classp, "__Vbasic_randomize");
|
||||
AstFuncRef* const basicRandomizeFuncCallp
|
||||
= new AstFuncRef{nodep->fileline(), "__Vbasic_randomize", nullptr};
|
||||
basicRandomizeFuncCallp->taskp(basicRandomizeFuncp);
|
||||
basicRandomizeFuncCallp->dtypep(basicRandomizeFuncp->dtypep());
|
||||
|
||||
// Copy (derive) class constraints if present
|
||||
if (classGenp) {
|
||||
AstTask* const constrSetupFuncp = getCreateConstraintSetupFunc(classp);
|
||||
|
|
@ -1004,7 +1031,7 @@ class RandomizeVisitor final : public VNVisitor {
|
|||
randomizeFuncp->addStmtsp(new AstAssign{
|
||||
nodep->fileline(),
|
||||
new AstVarRef{nodep->fileline(), VN_AS(randomizeFuncp->fvarp(), Var), VAccess::WRITE},
|
||||
solverCallp});
|
||||
new AstAnd{nodep->fileline(), basicRandomizeFuncCallp, solverCallp}});
|
||||
|
||||
// Replace the node with a call to that function
|
||||
nodep->name(randomizeFuncp->name());
|
||||
|
|
|
|||
|
|
@ -4,6 +4,20 @@
|
|||
// any use, without warranty, 2024 by Antmicro Ltd.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`define check_rand(cl, field) \
|
||||
begin \
|
||||
longint prev_result; \
|
||||
int ok = 0; \
|
||||
for (int i = 0; i < 10; i++) begin \
|
||||
longint result; \
|
||||
void'(cl.randomize()); \
|
||||
result = longint'(field); \
|
||||
if (i > 0 && result != prev_result) ok = 1; \
|
||||
prev_result = result; \
|
||||
end \
|
||||
if (ok != 1) $stop; \
|
||||
end
|
||||
|
||||
class Boo;
|
||||
function new();
|
||||
boo = 6;
|
||||
|
|
@ -73,6 +87,15 @@ function automatic int return_2();
|
|||
return 2;
|
||||
endfunction
|
||||
|
||||
class Cls;
|
||||
rand int a;
|
||||
rand int b;
|
||||
endclass
|
||||
|
||||
class Cls2 extends Cls;
|
||||
rand int c;
|
||||
endclass
|
||||
|
||||
module mwith();
|
||||
submodule sub1();
|
||||
submodule sub2();
|
||||
|
|
@ -87,6 +110,8 @@ module mwith();
|
|||
Baz baz = new;
|
||||
Baz2 baz2 = new;
|
||||
Bar bar = new;
|
||||
Cls2 cls2 = new;
|
||||
Cls cls = cls2;
|
||||
$display("foo.x = %d", foo.x);
|
||||
$display("-----------------");
|
||||
|
||||
|
|
@ -106,6 +131,10 @@ module mwith();
|
|||
$display("Failed to randomize foo with inline constraints");
|
||||
end
|
||||
|
||||
if (cls.randomize() with { b == 1;} != 1) $stop;
|
||||
if (cls.b != 1) $stop;
|
||||
`check_rand(cls2, cls2.a);
|
||||
`check_rand(cls2, cls2.c);
|
||||
// Check capture of a static variable
|
||||
if (foo.randomize() with { a > sub1.sub_var; } != 1) $stop;
|
||||
// Check reference to a function
|
||||
|
|
|
|||
Loading…
Reference in New Issue