mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
parent
87ac61140d
commit
292c2e289e
@ -145,8 +145,14 @@ class RandomizeMarkVisitor final : public VNVisitor {
|
|||||||
if (!varp) continue;
|
if (!varp) continue;
|
||||||
// If member is randomizable and of class type, mark its class
|
// If member is randomizable and of class type, mark its class
|
||||||
if (varp->rand().isRandomizable()) {
|
if (varp->rand().isRandomizable()) {
|
||||||
if (const AstClassRefDType* const classRefp
|
const AstNodeDType* const varDtypep = varp->dtypep()->skipRefp();
|
||||||
= VN_CAST(varp->dtypep()->skipRefp(), ClassRefDType)) {
|
const AstClassRefDType* classRefp = VN_CAST(varDtypep, ClassRefDType);
|
||||||
|
if (!classRefp) {
|
||||||
|
const AstNodeDType* subDTypep = varDtypep->subDTypep();
|
||||||
|
if (subDTypep) subDTypep = subDTypep->skipRefp();
|
||||||
|
classRefp = VN_CAST(subDTypep, ClassRefDType);
|
||||||
|
}
|
||||||
|
if (classRefp) {
|
||||||
AstClass* const rclassp = classRefp->classp();
|
AstClass* const rclassp = classRefp->classp();
|
||||||
if (!rclassp->user1()) {
|
if (!rclassp->user1()) {
|
||||||
rclassp->user1(IS_RANDOMIZED);
|
rclassp->user1(IS_RANDOMIZED);
|
||||||
@ -1374,7 +1380,7 @@ class RandomizeVisitor final : public VNVisitor {
|
|||||||
return newp;
|
return newp;
|
||||||
}
|
}
|
||||||
AstNodeStmt* createArrayForeachLoop(FileLine* const fl, AstNodeDType* const dtypep,
|
AstNodeStmt* createArrayForeachLoop(FileLine* const fl, AstNodeDType* const dtypep,
|
||||||
AstNodeExpr* exprp) {
|
AstNodeExpr* exprp, AstVar* const outputVarp) {
|
||||||
V3UniqueNames* uniqueNamep = new V3UniqueNames{"__Vrandarr"};
|
V3UniqueNames* uniqueNamep = new V3UniqueNames{"__Vrandarr"};
|
||||||
AstNodeDType* tempDTypep = dtypep;
|
AstNodeDType* tempDTypep = dtypep;
|
||||||
AstVar* randLoopIndxp = nullptr;
|
AstVar* randLoopIndxp = nullptr;
|
||||||
@ -1393,7 +1399,8 @@ class RandomizeVisitor final : public VNVisitor {
|
|||||||
auto createForeachLoop = [&](AstNodeExpr* tempElementp, AstVar* randLoopIndxp) {
|
auto createForeachLoop = [&](AstNodeExpr* tempElementp, AstVar* randLoopIndxp) {
|
||||||
AstSelLoopVars* const randLoopVarp
|
AstSelLoopVars* const randLoopVarp
|
||||||
= new AstSelLoopVars{fl, exprp->cloneTree(false), randLoopIndxp};
|
= new AstSelLoopVars{fl, exprp->cloneTree(false), randLoopIndxp};
|
||||||
return new AstForeach{fl, randLoopVarp, newRandStmtsp(fl, tempElementp, nullptr)};
|
return new AstForeach{fl, randLoopVarp,
|
||||||
|
newRandStmtsp(fl, tempElementp, nullptr, outputVarp)};
|
||||||
};
|
};
|
||||||
AstNodeExpr* tempElementp = nullptr;
|
AstNodeExpr* tempElementp = nullptr;
|
||||||
while (VN_IS(tempDTypep, DynArrayDType) || VN_IS(tempDTypep, UnpackArrayDType)
|
while (VN_IS(tempDTypep, DynArrayDType) || VN_IS(tempDTypep, UnpackArrayDType)
|
||||||
@ -1426,7 +1433,8 @@ class RandomizeVisitor final : public VNVisitor {
|
|||||||
stmtsp = createForeachLoop(tempElementp, randLoopIndxp);
|
stmtsp = createForeachLoop(tempElementp, randLoopIndxp);
|
||||||
return stmtsp;
|
return stmtsp;
|
||||||
}
|
}
|
||||||
AstNodeStmt* newRandStmtsp(FileLine* fl, AstNodeExpr* exprp, AstVar* randcVarp, int offset = 0,
|
AstNodeStmt* newRandStmtsp(FileLine* fl, AstNodeExpr* exprp, AstVar* randcVarp,
|
||||||
|
AstVar* const outputVarp, int offset = 0,
|
||||||
AstMemberDType* memberp = nullptr) {
|
AstMemberDType* memberp = nullptr) {
|
||||||
AstNodeDType* const memberDtp
|
AstNodeDType* const memberDtp
|
||||||
= memberp ? memberp->subDTypep()->skipRefp() : exprp->dtypep()->skipRefp();
|
= memberp ? memberp->subDTypep()->skipRefp() : exprp->dtypep()->skipRefp();
|
||||||
@ -1438,13 +1446,13 @@ class RandomizeVisitor final : public VNVisitor {
|
|||||||
AstNodeStmt* randp = nullptr;
|
AstNodeStmt* randp = nullptr;
|
||||||
if (structDtp->packed()) {
|
if (structDtp->packed()) {
|
||||||
randp = newRandStmtsp(fl, stmtsp ? exprp->cloneTree(false) : exprp, nullptr,
|
randp = newRandStmtsp(fl, stmtsp ? exprp->cloneTree(false) : exprp, nullptr,
|
||||||
offset, smemberp);
|
outputVarp, offset, smemberp);
|
||||||
} else {
|
} else {
|
||||||
AstStructSel* structSelp
|
AstStructSel* structSelp
|
||||||
= new AstStructSel{fl, exprp->cloneTree(false), smemberp->name()};
|
= new AstStructSel{fl, exprp->cloneTree(false), smemberp->name()};
|
||||||
structSelp->dtypep(smemberp->childDTypep());
|
structSelp->dtypep(smemberp->childDTypep());
|
||||||
if (!structSelp->dtypep()) structSelp->dtypep(smemberp->subDTypep());
|
if (!structSelp->dtypep()) structSelp->dtypep(smemberp->subDTypep());
|
||||||
randp = newRandStmtsp(fl, structSelp, nullptr);
|
randp = newRandStmtsp(fl, structSelp, nullptr, outputVarp);
|
||||||
}
|
}
|
||||||
stmtsp = stmtsp ? stmtsp->addNext(randp) : randp;
|
stmtsp = stmtsp ? stmtsp->addNext(randp) : randp;
|
||||||
}
|
}
|
||||||
@ -1456,16 +1464,25 @@ class RandomizeVisitor final : public VNVisitor {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
AstMemberDType* const firstMemberp = unionDtp->membersp();
|
AstMemberDType* const firstMemberp = unionDtp->membersp();
|
||||||
return newRandStmtsp(fl, exprp, nullptr, offset, firstMemberp);
|
return newRandStmtsp(fl, exprp, nullptr, outputVarp, offset, firstMemberp);
|
||||||
|
} else if (const AstClassRefDType* const classRefDtp = VN_CAST(memberDtp, ClassRefDType)) {
|
||||||
|
AstFunc* const memberFuncp
|
||||||
|
= V3Randomize::newRandomizeFunc(m_memberMap, classRefDtp->classp());
|
||||||
|
AstMethodCall* const callp = new AstMethodCall{fl, exprp, "randomize", nullptr};
|
||||||
|
callp->taskp(memberFuncp);
|
||||||
|
callp->dtypeFrom(memberFuncp);
|
||||||
|
return new AstAssign{
|
||||||
|
fl, new AstVarRef{fl, outputVarp, VAccess::WRITE},
|
||||||
|
new AstAnd{fl, new AstVarRef{fl, outputVarp, VAccess::READ}, callp}};
|
||||||
} else if (AstDynArrayDType* const dynarrayDtp = VN_CAST(memberDtp, DynArrayDType)) {
|
} else if (AstDynArrayDType* const dynarrayDtp = VN_CAST(memberDtp, DynArrayDType)) {
|
||||||
return createArrayForeachLoop(fl, dynarrayDtp, exprp);
|
return createArrayForeachLoop(fl, dynarrayDtp, exprp, outputVarp);
|
||||||
} else if (AstQueueDType* const queueDtp = VN_CAST(memberDtp, QueueDType)) {
|
} else if (AstQueueDType* const queueDtp = VN_CAST(memberDtp, QueueDType)) {
|
||||||
return createArrayForeachLoop(fl, queueDtp, exprp);
|
return createArrayForeachLoop(fl, queueDtp, exprp, outputVarp);
|
||||||
} else if (AstUnpackArrayDType* const unpackarrayDtp
|
} else if (AstUnpackArrayDType* const unpackarrayDtp
|
||||||
= VN_CAST(memberDtp, UnpackArrayDType)) {
|
= VN_CAST(memberDtp, UnpackArrayDType)) {
|
||||||
return createArrayForeachLoop(fl, unpackarrayDtp, exprp);
|
return createArrayForeachLoop(fl, unpackarrayDtp, exprp, outputVarp);
|
||||||
} else if (AstAssocArrayDType* const assocarrayDtp = VN_CAST(memberDtp, AssocArrayDType)) {
|
} else if (AstAssocArrayDType* const assocarrayDtp = VN_CAST(memberDtp, AssocArrayDType)) {
|
||||||
return createArrayForeachLoop(fl, assocarrayDtp, exprp);
|
return createArrayForeachLoop(fl, assocarrayDtp, exprp, outputVarp);
|
||||||
} 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()
|
||||||
@ -1671,7 +1688,7 @@ class RandomizeVisitor final : public VNVisitor {
|
|||||||
} else {
|
} else {
|
||||||
AstVar* const randcVarp = newRandcVarsp(memberVarp);
|
AstVar* const randcVarp = newRandcVarsp(memberVarp);
|
||||||
AstVarRef* const refp = new AstVarRef{fl, classp, memberVarp, VAccess::WRITE};
|
AstVarRef* const refp = new AstVarRef{fl, classp, memberVarp, VAccess::WRITE};
|
||||||
AstNodeStmt* const stmtp = newRandStmtsp(fl, refp, randcVarp);
|
AstNodeStmt* const stmtp = newRandStmtsp(fl, refp, randcVarp, basicFvarp);
|
||||||
basicRandomizep->addStmtsp(new AstBegin{fl, "", stmtp});
|
basicRandomizep->addStmtsp(new AstBegin{fl, "", stmtp});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -63,10 +63,15 @@ class unconstrained_unpacked_array_test;
|
|||||||
|
|
||||||
endclass
|
endclass
|
||||||
|
|
||||||
|
class Cls;
|
||||||
|
rand int x = 1;
|
||||||
|
endclass
|
||||||
|
|
||||||
class unconstrained_dynamic_array_test;
|
class unconstrained_dynamic_array_test;
|
||||||
|
|
||||||
rand int dynamic_array_1d[];
|
rand int dynamic_array_1d[];
|
||||||
rand int dynamic_array_2d[][];
|
rand int dynamic_array_2d[][];
|
||||||
|
rand Cls class_dynamic_array[];
|
||||||
|
|
||||||
function new();
|
function new();
|
||||||
// Initialize 1D dynamic array
|
// Initialize 1D dynamic array
|
||||||
@ -83,6 +88,12 @@ class unconstrained_dynamic_array_test;
|
|||||||
dynamic_array_2d[i][j] = 'h0 + i + j;
|
dynamic_array_2d[i][j] = 'h0 + i + j;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class_dynamic_array = new[5];
|
||||||
|
foreach(class_dynamic_array[i]) begin
|
||||||
|
class_dynamic_array[i] = new;
|
||||||
|
end
|
||||||
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function void check_randomization();
|
function void check_randomization();
|
||||||
@ -94,6 +105,9 @@ class unconstrained_dynamic_array_test;
|
|||||||
`check_rand(this, dynamic_array_2d[i][j])
|
`check_rand(this, dynamic_array_2d[i][j])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
foreach (class_dynamic_array[i]) begin
|
||||||
|
`check_rand(this, class_dynamic_array[i].x)
|
||||||
|
end
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
endclass
|
endclass
|
||||||
|
Loading…
Reference in New Issue
Block a user