Fix rand fields in base classes (#4025)

This commit is contained in:
Ryszard Rozak 2023-03-15 16:48:18 +01:00 committed by GitHub
parent 2488b5a97f
commit 0f6024ef3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 99 additions and 42 deletions

View File

@ -57,9 +57,11 @@ private:
if (VN_IS(memberp, Var) && VN_AS(memberp, Var)->isRand()) {
if (const auto* const classRefp = VN_CAST(memberp->dtypep(), ClassRefDType)) {
auto* const rclassp = classRefp->classp();
markMembers(rclassp);
markDerived(rclassp);
rclassp->user1(true);
if (!rclassp->user1()) {
rclassp->user1(true);
markMembers(rclassp);
markDerived(rclassp);
}
}
}
}
@ -69,9 +71,11 @@ private:
const auto it = m_baseToDerivedMap.find(nodep);
if (it != m_baseToDerivedMap.end()) {
for (auto* classp : it->second) {
classp->user1(true);
markMembers(classp);
markDerived(classp);
if (!classp->user1p()) {
classp->user1(true);
markMembers(classp);
markDerived(classp);
}
}
}
}
@ -121,6 +125,7 @@ private:
// Cleared on Netlist
// AstClass::user1() -> bool. Set true to indicate needs randomize processing
// AstEnumDType::user2() -> AstVar*. Pointer to table with enum values
// AstClass::user3() -> AstFunc*. Pointer to randomize() method of a class
// VNUser1InUse m_inuser1; (Allocated for use in RandomizeMarkVisitor)
const VNUser2InUse m_inuser2;
@ -230,42 +235,59 @@ private:
if (!nodep->user1()) return; // Doesn't need randomize, or already processed
UINFO(9, "Define randomize() for " << nodep << endl);
AstFunc* const funcp = V3Randomize::newRandomizeFunc(nodep);
nodep->user3p(funcp);
AstVar* const fvarp = VN_AS(funcp->fvarp(), Var);
addPrePostCall(nodep, funcp, "pre_randomize");
FileLine* fl = nodep->fileline();
funcp->addStmtsp(new AstAssign{fl, new AstVarRef{fl, fvarp, VAccess::WRITE},
new AstConst{fl, AstConst::WidthedValue{}, 32, 1}});
for (AstClass* classp = nodep; classp;
classp = classp->extendsp() ? classp->extendsp()->classp() : nullptr) {
for (auto* memberp = classp->stmtsp(); memberp; memberp = memberp->nextp()) {
AstVar* const memberVarp = VN_CAST(memberp, Var);
if (!memberVarp || !memberVarp->isRand()) continue;
const AstNodeDType* const dtypep = memberp->dtypep()->skipRefp();
if (VN_IS(dtypep, BasicDType) || VN_IS(dtypep, StructDType)) {
AstVarRef* const refp = new AstVarRef{fl, memberVarp, VAccess::WRITE};
AstNodeStmt* const stmtp = newRandStmtsp(fl, refp);
funcp->addStmtsp(stmtp);
} else if (const auto* const classRefp = VN_CAST(dtypep, ClassRefDType)) {
AstVarRef* const refp = new AstVarRef{fl, memberVarp, VAccess::WRITE};
AstFunc* const memberFuncp
= V3Randomize::newRandomizeFunc(classRefp->classp());
AstMethodCall* const callp = new AstMethodCall{fl, refp, "randomize", nullptr};
callp->taskp(memberFuncp);
callp->dtypeFrom(memberFuncp);
AstAssign* const assignp = new AstAssign{
fl, new AstVarRef{fl, fvarp, VAccess::WRITE},
new AstAnd{fl, new AstVarRef{fl, fvarp, VAccess::READ}, callp}};
AstIf* const assignIfNotNullp
= new AstIf{fl,
new AstNeq{fl, new AstVarRef{fl, memberVarp, VAccess::READ},
new AstConst{fl, AstConst::Null{}}},
assignp};
funcp->addStmtsp(assignIfNotNullp);
} else {
memberp->v3warn(E_UNSUPPORTED,
"Unsupported: random member variables with type "
<< memberp->dtypep()->prettyDTypeNameQ());
AstNodeExpr* beginValp = nullptr;
if (nodep->extendsp()) {
// Call randomize() from the base class
AstFunc* const baseRandomizep = VN_AS(nodep->extendsp()->classp()->user3p(), Func);
if (baseRandomizep) {
AstFuncRef* const baseRandCallp = new AstFuncRef{fl, "randomize", nullptr};
baseRandCallp->taskp(baseRandomizep);
baseRandCallp->dtypeFrom(baseRandomizep->dtypep());
baseRandCallp->classOrPackagep(nodep->extendsp()->classp());
beginValp = baseRandCallp;
}
}
if (!beginValp) beginValp = new AstConst{fl, AstConst::WidthedValue{}, 32, 1};
funcp->addStmtsp(new AstAssign{fl, new AstVarRef{fl, fvarp, VAccess::WRITE}, beginValp});
for (auto* memberp = nodep->stmtsp(); memberp; memberp = memberp->nextp()) {
AstVar* const memberVarp = VN_CAST(memberp, Var);
if (!memberVarp || !memberVarp->isRand()) continue;
const AstNodeDType* const dtypep = memberp->dtypep()->skipRefp();
if (VN_IS(dtypep, BasicDType) || VN_IS(dtypep, StructDType)) {
AstVarRef* const refp = new AstVarRef{fl, memberVarp, VAccess::WRITE};
AstNodeStmt* const stmtp = newRandStmtsp(fl, refp);
funcp->addStmtsp(stmtp);
} else if (const auto* const classRefp = VN_CAST(dtypep, ClassRefDType)) {
if (classRefp->classp() == nodep) {
memberp->v3warn(
E_UNSUPPORTED,
"Unsupported: random member variable with type of a current class");
continue;
}
AstVarRef* const refp = new AstVarRef{fl, memberVarp, VAccess::WRITE};
AstFunc* const memberFuncp = V3Randomize::newRandomizeFunc(classRefp->classp());
AstMethodCall* const callp = new AstMethodCall{fl, refp, "randomize", nullptr};
callp->taskp(memberFuncp);
callp->dtypeFrom(memberFuncp);
AstAssign* const assignp = new AstAssign{
fl, new AstVarRef{fl, fvarp, VAccess::WRITE},
new AstAnd{fl, new AstVarRef{fl, fvarp, VAccess::READ}, callp}};
AstIf* const assignIfNotNullp
= new AstIf{fl,
new AstNeq{fl, new AstVarRef{fl, memberVarp, VAccess::READ},
new AstConst{fl, AstConst::Null{}}},
assignp};
funcp->addStmtsp(assignIfNotNullp);
} else {
memberp->v3warn(E_UNSUPPORTED, "Unsupported: random member variable with type "
<< memberp->dtypep()->prettyDTypeNameQ());
}
}
addPrePostCall(nodep, funcp, "post_randomize");

View File

@ -96,23 +96,46 @@ class ContainsNull;
rand BaseCls b;
endclass
class ClsWithInt;
rand int a;
int b;
endclass
class DeriveClsWithInt extends ClsWithInt;
endclass
class DeriveAndContainClsWithInt extends ClsWithInt;
rand ClsWithInt cls1;
ClsWithInt cls2;
function new;
cls1 = new;
cls2 = new;
endfunction
endclass
module t (/*AUTOARG*/);
DerivedCls derived;
OtherCls other;
BaseCls base;
ContainsNull cont;
DeriveClsWithInt der_int;
DeriveAndContainClsWithInt der_contain;
initial begin
int rand_result;
derived = new;
other = new;
cont = new;
der_int = new;
der_contain = new;
base = derived;
for (int i = 0; i < 10; i++) begin
rand_result = base.randomize();
rand_result = other.randomize();
rand_result = cont.randomize();
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;
@ -120,6 +143,10 @@ module t (/*AUTOARG*/);
if (derived.k != 0) $stop;
if (other.v != 0) $stop;
if (cont.b != null) $stop;
if (der_int.b != 0) $stop;
if (der_contain.cls2.a != 0) $stop;
if (der_contain.cls1.b != 0) $stop;
if (der_contain.b != 0) $stop;
end
`check_rand(derived, derived.i.a);
`check_rand(derived, derived.i.b);
@ -136,6 +163,9 @@ module t (/*AUTOARG*/);
`check_rand(other, other.str.s.a);
`check_rand(other, other.str.s.b);
`check_rand(other, other.str.s.c);
`check_rand(der_int, der_int.a);
`check_rand(der_contain, der_contain.cls1.a);
`check_rand(der_contain, der_contain.a);
$write("*-* All Finished *-*\n");
$finish;

View File

@ -1,18 +1,22 @@
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:12:13: Unsupported: random member variables with type 'int[string]'
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:12:13: Unsupported: random member variable with type 'int[string]'
: ... In instance t
12 | rand int assocarr[string];
| ^~~~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:13:13: Unsupported: random member variables with type 'int[]'
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:13:13: Unsupported: random member variable with type 'int[]'
: ... In instance t
13 | rand int dynarr[];
| ^~~~~~
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:14:13: Unsupported: random member variables with type 'int$[0:4]'
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:14:13: Unsupported: random member variable with type 'int$[0:4]'
: ... In instance t
14 | rand int unpackarr[5];
| ^~~~~~~~~
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:15:15: Unsupported: random member variables with type '$unit::Union'
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:15:15: Unsupported: random member variable with type '$unit::Union'
: ... In instance t
15 | rand Union uni;
| ^~~
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:16:13: Unsupported: random member variable with type of a current class
: ... In instance t
16 | rand Cls cls;
| ^~~
%Error: Exiting due to

View File

@ -13,6 +13,7 @@ class Cls;
rand int dynarr[];
rand int unpackarr[5];
rand Union uni;
rand Cls cls;
endclass
module t (/*AUTOARG*/);