Fix unconstrained randomization of unpacked structs (#5252)
Signed-off-by: Krzysztof Bieganski <kbieganski@antmicro.com>
This commit is contained in:
parent
abb46c9cb2
commit
2696a9a5bd
|
|
@ -478,17 +478,26 @@ class RandomizeVisitor final : public VNVisitor {
|
||||||
UINFO(9, "created " << varp << endl);
|
UINFO(9, "created " << varp << endl);
|
||||||
return newp;
|
return newp;
|
||||||
}
|
}
|
||||||
AstNodeStmt* newRandStmtsp(FileLine* fl, AstNodeVarRef* varrefp, AstVar* randcVarp,
|
AstNodeStmt* newRandStmtsp(FileLine* fl, AstNodeExpr* exprp, AstVar* randcVarp, int offset = 0,
|
||||||
int offset = 0, AstMemberDType* memberp = nullptr) {
|
AstMemberDType* memberp = nullptr) {
|
||||||
if (const auto* const structDtp
|
if (const auto* const structDtp
|
||||||
= VN_CAST(memberp ? memberp->subDTypep()->skipRefp() : varrefp->dtypep()->skipRefp(),
|
= VN_CAST(memberp ? memberp->subDTypep()->skipRefp() : exprp->dtypep()->skipRefp(),
|
||||||
StructDType)) {
|
StructDType)) {
|
||||||
AstNodeStmt* stmtsp = nullptr;
|
AstNodeStmt* stmtsp = nullptr;
|
||||||
offset += memberp ? memberp->lsb() : 0;
|
if (structDtp->packed()) offset += memberp ? memberp->lsb() : 0;
|
||||||
for (AstMemberDType* smemberp = structDtp->membersp(); smemberp;
|
for (AstMemberDType* smemberp = structDtp->membersp(); smemberp;
|
||||||
smemberp = VN_AS(smemberp->nextp(), MemberDType)) {
|
smemberp = VN_AS(smemberp->nextp(), MemberDType)) {
|
||||||
AstNodeStmt* const randp = newRandStmtsp(
|
AstNodeStmt* randp = nullptr;
|
||||||
fl, stmtsp ? varrefp->cloneTree(false) : varrefp, nullptr, offset, smemberp);
|
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) {
|
if (stmtsp) {
|
||||||
stmtsp->addNext(randp);
|
stmtsp->addNext(randp);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -499,24 +508,24 @@ class RandomizeVisitor final : public VNVisitor {
|
||||||
} else {
|
} else {
|
||||||
AstNodeExpr* valp;
|
AstNodeExpr* valp;
|
||||||
if (AstEnumDType* const enumDtp = VN_CAST(memberp ? memberp->subDTypep()->subDTypep()
|
if (AstEnumDType* const enumDtp = VN_CAST(memberp ? memberp->subDTypep()->subDTypep()
|
||||||
: varrefp->dtypep()->subDTypep(),
|
: exprp->dtypep()->subDTypep(),
|
||||||
EnumDType)) {
|
EnumDType)) {
|
||||||
AstVarRef* const tabRefp
|
AstVarRef* const tabRefp
|
||||||
= new AstVarRef{fl, enumValueTabp(enumDtp), VAccess::READ};
|
= new AstVarRef{fl, enumValueTabp(enumDtp), VAccess::READ};
|
||||||
tabRefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
|
tabRefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||||
AstNodeExpr* const randp
|
AstNodeExpr* const randp
|
||||||
= newRandValue(fl, randcVarp, varrefp->findBasicDType(VBasicDTypeKwd::UINT32));
|
= newRandValue(fl, randcVarp, exprp->findBasicDType(VBasicDTypeKwd::UINT32));
|
||||||
AstNodeExpr* const moddivp = new AstModDiv{
|
AstNodeExpr* const moddivp = new AstModDiv{
|
||||||
fl, randp, new AstConst{fl, static_cast<uint32_t>(enumDtp->itemCount())}};
|
fl, randp, new AstConst{fl, static_cast<uint32_t>(enumDtp->itemCount())}};
|
||||||
moddivp->dtypep(enumDtp);
|
moddivp->dtypep(enumDtp);
|
||||||
valp = new AstArraySel{fl, tabRefp, moddivp};
|
valp = new AstArraySel{fl, tabRefp, moddivp};
|
||||||
} else {
|
} else {
|
||||||
valp = newRandValue(fl, randcVarp,
|
valp
|
||||||
(memberp ? memberp->dtypep() : varrefp->varp()->dtypep()));
|
= newRandValue(fl, randcVarp, (memberp ? memberp->dtypep() : exprp->dtypep()));
|
||||||
}
|
}
|
||||||
return new AstAssign{fl,
|
return new AstAssign{fl,
|
||||||
new AstSel{fl, varrefp, offset + (memberp ? memberp->lsb() : 0),
|
new AstSel{fl, exprp, offset + (memberp ? memberp->lsb() : 0),
|
||||||
memberp ? memberp->width() : varrefp->width()},
|
memberp ? memberp->width() : exprp->width()},
|
||||||
valp};
|
valp};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,13 @@ typedef struct packed {
|
||||||
longint z;
|
longint z;
|
||||||
} StructOuter;
|
} StructOuter;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int i;
|
||||||
|
StructOuter j;
|
||||||
|
Enum k;
|
||||||
|
longint z;
|
||||||
|
} StructUnpacked;
|
||||||
|
|
||||||
class BaseCls;
|
class BaseCls;
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
|
|
@ -79,7 +86,7 @@ class OtherCls;
|
||||||
rand logic[47:0] x;
|
rand logic[47:0] x;
|
||||||
rand logic[31:0] y;
|
rand logic[31:0] y;
|
||||||
rand logic[23:0] z;
|
rand logic[23:0] z;
|
||||||
rand StructOuter str;
|
rand StructUnpacked str;
|
||||||
|
|
||||||
function new;
|
function new;
|
||||||
v = 0;
|
v = 0;
|
||||||
|
|
@ -87,7 +94,9 @@ class OtherCls;
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
z = 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
|
endfunction
|
||||||
|
|
||||||
endclass
|
endclass
|
||||||
|
|
@ -152,8 +161,9 @@ module t (/*AUTOARG*/);
|
||||||
rand_result = der_int.randomize();
|
rand_result = der_int.randomize();
|
||||||
rand_result = der_contain.randomize();
|
rand_result = der_contain.randomize();
|
||||||
if (!(derived.l inside {ONE, TWO, THREE, FOUR})) $stop;
|
if (!(derived.l inside {ONE, TWO, THREE, FOUR})) $stop;
|
||||||
if (!(other.str.s.c inside {ONE, TWO, THREE, FOUR})) $stop;
|
if (!(other.str.j.s.c inside {ONE, TWO, THREE, FOUR})) $stop;
|
||||||
if (!(other.str.y 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.i.e != 0) $stop;
|
||||||
if (derived.k != 0) $stop;
|
if (derived.k != 0) $stop;
|
||||||
if (other.v != 0) $stop;
|
if (other.v != 0) $stop;
|
||||||
|
|
@ -172,12 +182,14 @@ module t (/*AUTOARG*/);
|
||||||
`check_rand(other, other.x);
|
`check_rand(other, other.x);
|
||||||
`check_rand(other, other.y);
|
`check_rand(other, other.y);
|
||||||
`check_rand(other, other.z);
|
`check_rand(other, other.z);
|
||||||
`check_rand(other, other.str.x);
|
`check_rand(other, other.str.i);
|
||||||
`check_rand(other, other.str.y);
|
`check_rand(other, other.str.j.x);
|
||||||
`check_rand(other, other.str.z);
|
`check_rand(other, other.str.j.y);
|
||||||
`check_rand(other, other.str.s.a);
|
`check_rand(other, other.str.j.z);
|
||||||
`check_rand(other, other.str.s.b);
|
`check_rand(other, other.str.j.s.a);
|
||||||
`check_rand(other, other.str.s.c);
|
`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_int, der_int.a);
|
||||||
`check_rand(der_contain, der_contain.cls1.a);
|
`check_rand(der_contain, der_contain.cls1.a);
|
||||||
`check_rand(der_contain, der_contain.a);
|
`check_rand(der_contain, der_contain.a);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue