Fix unconstrained randomization of unpacked structs (#5252)

Signed-off-by: Krzysztof Bieganski <kbieganski@antmicro.com>
This commit is contained in:
Krzysztof Bieganski 2024-07-11 16:43:56 +02:00 committed by GitHub
parent abb46c9cb2
commit 2696a9a5bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 43 additions and 22 deletions

View File

@ -478,17 +478,26 @@ class RandomizeVisitor final : public VNVisitor {
UINFO(9, "created " << varp << endl);
return newp;
}
AstNodeStmt* newRandStmtsp(FileLine* fl, AstNodeVarRef* varrefp, AstVar* randcVarp,
int offset = 0, AstMemberDType* memberp = nullptr) {
AstNodeStmt* newRandStmtsp(FileLine* fl, AstNodeExpr* exprp, AstVar* randcVarp, int offset = 0,
AstMemberDType* memberp = nullptr) {
if (const auto* const structDtp
= VN_CAST(memberp ? memberp->subDTypep()->skipRefp() : varrefp->dtypep()->skipRefp(),
= VN_CAST(memberp ? memberp->subDTypep()->skipRefp() : exprp->dtypep()->skipRefp(),
StructDType)) {
AstNodeStmt* stmtsp = nullptr;
offset += memberp ? memberp->lsb() : 0;
if (structDtp->packed()) offset += memberp ? memberp->lsb() : 0;
for (AstMemberDType* smemberp = structDtp->membersp(); smemberp;
smemberp = VN_AS(smemberp->nextp(), MemberDType)) {
AstNodeStmt* const randp = newRandStmtsp(
fl, stmtsp ? varrefp->cloneTree(false) : varrefp, nullptr, offset, smemberp);
AstNodeStmt* randp = nullptr;
if (structDtp->packed()) {
randp = newRandStmtsp(fl, stmtsp ? exprp->cloneTree(false) : exprp, nullptr,
offset, smemberp);
} else {
AstStructSel* structSelp
= new AstStructSel{fl, exprp->cloneTree(false), smemberp->name()};
structSelp->dtypep(smemberp->childDTypep());
if (!structSelp->dtypep()) structSelp->dtypep(smemberp->subDTypep());
randp = newRandStmtsp(fl, structSelp, nullptr);
}
if (stmtsp) {
stmtsp->addNext(randp);
} else {
@ -499,24 +508,24 @@ class RandomizeVisitor final : public VNVisitor {
} else {
AstNodeExpr* valp;
if (AstEnumDType* const enumDtp = VN_CAST(memberp ? memberp->subDTypep()->subDTypep()
: varrefp->dtypep()->subDTypep(),
: exprp->dtypep()->subDTypep(),
EnumDType)) {
AstVarRef* const tabRefp
= new AstVarRef{fl, enumValueTabp(enumDtp), VAccess::READ};
tabRefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
AstNodeExpr* const randp
= newRandValue(fl, randcVarp, varrefp->findBasicDType(VBasicDTypeKwd::UINT32));
= newRandValue(fl, randcVarp, exprp->findBasicDType(VBasicDTypeKwd::UINT32));
AstNodeExpr* const moddivp = new AstModDiv{
fl, randp, new AstConst{fl, static_cast<uint32_t>(enumDtp->itemCount())}};
moddivp->dtypep(enumDtp);
valp = new AstArraySel{fl, tabRefp, moddivp};
} else {
valp = newRandValue(fl, randcVarp,
(memberp ? memberp->dtypep() : varrefp->varp()->dtypep()));
valp
= newRandValue(fl, randcVarp, (memberp ? memberp->dtypep() : exprp->dtypep()));
}
return new AstAssign{fl,
new AstSel{fl, varrefp, offset + (memberp ? memberp->lsb() : 0),
memberp ? memberp->width() : varrefp->width()},
new AstSel{fl, exprp, offset + (memberp ? memberp->lsb() : 0),
memberp ? memberp->width() : exprp->width()},
valp};
}
}

View File

@ -38,6 +38,13 @@ typedef struct packed {
longint z;
} StructOuter;
typedef struct {
int i;
StructOuter j;
Enum k;
longint z;
} StructUnpacked;
class BaseCls;
endclass
@ -79,7 +86,7 @@ class OtherCls;
rand logic[47:0] x;
rand logic[31:0] y;
rand logic[23:0] z;
rand StructOuter str;
rand StructUnpacked str;
function new;
v = 0;
@ -87,7 +94,9 @@ class OtherCls;
x = 0;
y = 0;
z = 0;
str = '{x: 1'b0, y: ONE, z: 64'd0, s: '{a: 32'd0, b: 1'b0, c: ONE}};
str.i = 0;
str.j = '{x: 1'b0, y: ONE, z: 64'd0, s: '{a: 32'd0, b: 1'b0, c: ONE}};
str.k = ONE;
endfunction
endclass
@ -152,8 +161,9 @@ module t (/*AUTOARG*/);
rand_result = der_int.randomize();
rand_result = der_contain.randomize();
if (!(derived.l inside {ONE, TWO, THREE, FOUR})) $stop;
if (!(other.str.s.c inside {ONE, TWO, THREE, FOUR})) $stop;
if (!(other.str.y inside {ONE, TWO, THREE, FOUR})) $stop;
if (!(other.str.j.s.c inside {ONE, TWO, THREE, FOUR})) $stop;
if (!(other.str.j.y inside {ONE, TWO, THREE, FOUR})) $stop;
if (!(other.str.k inside {ONE, TWO, THREE, FOUR})) $stop;
if (derived.i.e != 0) $stop;
if (derived.k != 0) $stop;
if (other.v != 0) $stop;
@ -172,12 +182,14 @@ module t (/*AUTOARG*/);
`check_rand(other, other.x);
`check_rand(other, other.y);
`check_rand(other, other.z);
`check_rand(other, other.str.x);
`check_rand(other, other.str.y);
`check_rand(other, other.str.z);
`check_rand(other, other.str.s.a);
`check_rand(other, other.str.s.b);
`check_rand(other, other.str.s.c);
`check_rand(other, other.str.i);
`check_rand(other, other.str.j.x);
`check_rand(other, other.str.j.y);
`check_rand(other, other.str.j.z);
`check_rand(other, other.str.j.s.a);
`check_rand(other, other.str.j.s.b);
`check_rand(other, other.str.j.s.c);
`check_rand(other, other.str.k);
`check_rand(der_int, der_int.a);
`check_rand(der_contain, der_contain.cls1.a);
`check_rand(der_contain, der_contain.a);