forked from github/verilator
Fix rand fields in base classes (#4025)
This commit is contained in:
parent
2488b5a97f
commit
0f6024ef3c
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -13,6 +13,7 @@ class Cls;
|
||||
rand int dynarr[];
|
||||
rand int unpackarr[5];
|
||||
rand Union uni;
|
||||
rand Cls cls;
|
||||
endclass
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
Loading…
Reference in New Issue
Block a user