diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index 918b9d753..d93eeca15 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -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(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}; } } diff --git a/test_regress/t/t_randomize_method.v b/test_regress/t/t_randomize_method.v index 69868eb48..1309f9f03 100644 --- a/test_regress/t/t_randomize_method.v +++ b/test_regress/t/t_randomize_method.v @@ -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);