Add support for `this.randomize with` (#5282)
Signed-off-by: Arkadiusz Kozdra <akozdra@antmicro.com>
This commit is contained in:
parent
b18037b7e7
commit
43377ed8b0
|
|
@ -898,25 +898,33 @@ class RandomizeVisitor final : public VNVisitor {
|
|||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
void visit(AstMethodCall* nodep) override {
|
||||
void visit(AstNodeFTaskRef* nodep) override {
|
||||
AstWith* const withp = VN_CAST(nodep->pinsp(), With);
|
||||
|
||||
if (!(nodep->name() == "randomize") || !withp) {
|
||||
iterateChildren(nodep);
|
||||
return;
|
||||
}
|
||||
withp->unlinkFrBack();
|
||||
|
||||
iterateChildren(nodep);
|
||||
|
||||
UASSERT_OBJ(nodep->fromp()->dtypep(), nodep->fromp(), "Object dtype is not linked");
|
||||
AstClassRefDType* const classrefdtypep = VN_CAST(nodep->fromp()->dtypep(), ClassRefDType);
|
||||
if (!classrefdtypep) {
|
||||
nodep->v3warn(E_UNSUPPORTED,
|
||||
"Inline constraints are not supported for this node type");
|
||||
return;
|
||||
AstClass* classp = nullptr;
|
||||
if (AstMethodCall* const callp = VN_CAST(nodep, MethodCall)) {
|
||||
UASSERT_OBJ(callp->fromp()->dtypep(), callp->fromp(), "Object dtype is not linked");
|
||||
AstClassRefDType* const classrefdtypep
|
||||
= VN_CAST(callp->fromp()->dtypep(), ClassRefDType);
|
||||
if (!classrefdtypep) {
|
||||
nodep->v3warn(E_UNSUPPORTED,
|
||||
"Inline constraints are not supported for this node type");
|
||||
return;
|
||||
}
|
||||
classp = classrefdtypep->classp();
|
||||
UASSERT_OBJ(classp, classrefdtypep, "Class type is unlinked to its ref type");
|
||||
} else {
|
||||
classp = VN_CAST(m_modp, Class);
|
||||
UASSERT_OBJ(classp, m_modp, "Module not class, should have failed in V3Width");
|
||||
}
|
||||
AstClass* const classp = classrefdtypep->classp();
|
||||
UASSERT_OBJ(classp, classrefdtypep, "Class type is unlinked to its ref type");
|
||||
if (classp->user1()) {
|
||||
// We need to first ensure that the class randomizer is instantiated if needed
|
||||
// NOTE: This is safe only because AstClass visit function overwrites all
|
||||
|
|
@ -985,15 +993,13 @@ class RandomizeVisitor final : public VNVisitor {
|
|||
solverCallp});
|
||||
|
||||
// Replace the node with a call to that function
|
||||
AstMethodCall* const callp
|
||||
= new AstMethodCall(nodep->fileline(), nodep->fromp()->unlinkFrBack(),
|
||||
randomizeFuncp->name(), captured.getArgs());
|
||||
callp->taskp(randomizeFuncp);
|
||||
callp->dtypeFrom(randomizeFuncp->dtypep());
|
||||
callp->classOrPackagep(classp);
|
||||
nodep->replaceWith(callp);
|
||||
nodep->name(randomizeFuncp->name());
|
||||
nodep->addPinsp(captured.getArgs());
|
||||
nodep->taskp(randomizeFuncp);
|
||||
nodep->dtypeFrom(randomizeFuncp->dtypep());
|
||||
nodep->classOrPackagep(classp);
|
||||
UINFO(9, "Added `%s` randomization procedure");
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
VL_DO_DANGLING(withp->deleteTree(), withp);
|
||||
}
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
|
|
|
|||
|
|
@ -3132,7 +3132,7 @@ class WidthVisitor final : public VNVisitor {
|
|||
<< nodep->fromp()->dtypep()->prettyTypeName() << "'");
|
||||
}
|
||||
}
|
||||
AstWith* methodWithArgument(AstMethodCall* nodep, bool required, bool arbReturn,
|
||||
AstWith* methodWithArgument(AstNodeFTaskRef* nodep, bool required, bool arbReturn,
|
||||
AstNodeDType* returnDtp, AstNodeDType* indexDtp,
|
||||
AstNodeDType* valueDtp) {
|
||||
UASSERT_OBJ(arbReturn || returnDtp, nodep, "Null return type");
|
||||
|
|
@ -5990,6 +5990,7 @@ class WidthVisitor final : public VNVisitor {
|
|||
// For arguments, is assignment-like context; see IEEE rules in AstNodeAssign
|
||||
// Function hasn't been widthed, so make it so.
|
||||
UINFO(5, " FTASKREF " << nodep << endl);
|
||||
AstWith* withp = nullptr;
|
||||
if (nodep->name() == "randomize" || nodep->name() == "srandom"
|
||||
|| (!nodep->taskp()
|
||||
&& (nodep->name() == "get_randstate" || nodep->name() == "set_randstate"))) {
|
||||
|
|
@ -5998,6 +5999,15 @@ class WidthVisitor final : public VNVisitor {
|
|||
UASSERT_OBJ(classp, nodep, "Should have failed in V3LinkDot");
|
||||
if (nodep->name() == "randomize") {
|
||||
nodep->taskp(V3Randomize::newRandomizeFunc(m_memberMap, classp));
|
||||
AstClassRefDType* const adtypep
|
||||
= new AstClassRefDType{nodep->fileline(), classp, nullptr};
|
||||
v3Global.rootp()->typeTablep()->addTypesp(adtypep);
|
||||
withp = methodWithArgument(nodep, false, false, adtypep->findVoidDType(),
|
||||
adtypep->findBitDType(), adtypep);
|
||||
if (nodep->pinsp()) {
|
||||
nodep->pinsp()->v3warn(CONSTRAINTIGN, "rand_mode ignored (unsupported)");
|
||||
nodep->pinsp()->unlinkFrBackWithNext()->deleteTree();
|
||||
}
|
||||
} else if (nodep->name() == "srandom") {
|
||||
nodep->taskp(V3Randomize::newSRandomFunc(m_memberMap, classp));
|
||||
m_memberMap.clear();
|
||||
|
|
@ -6041,6 +6051,7 @@ class WidthVisitor final : public VNVisitor {
|
|||
userIterate(nodep->taskp(), nullptr);
|
||||
// And do the arguments to the task/function too
|
||||
processFTaskRefArgs(nodep);
|
||||
nodep->addPinsp(withp);
|
||||
nodep->didWidth(true);
|
||||
}
|
||||
void visit(AstNodeProcedure* nodep) override {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ class Foo extends Boo;
|
|||
endfunction
|
||||
|
||||
constraint constr1_c { b < x; }
|
||||
function bit test_this_randomize;
|
||||
return this.randomize() with { a <= boo; } == 1;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
// Current AstWith representation makes VARs of caller indistinguishable from VARs of randomized
|
||||
|
|
@ -55,6 +58,13 @@ class Baz;
|
|||
rand int v;
|
||||
endclass
|
||||
|
||||
class Baz2;
|
||||
rand int v;
|
||||
function bit test_this_randomize;
|
||||
return this.randomize() with { v == 5; } == 1;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
module submodule();
|
||||
int sub_var = 7;
|
||||
endmodule
|
||||
|
|
@ -75,6 +85,7 @@ module mwith();
|
|||
int c = 30;
|
||||
Foo foo = new(c);
|
||||
Baz baz = new;
|
||||
Baz2 baz2 = new;
|
||||
Bar bar = new;
|
||||
$display("foo.x = %d", foo.x);
|
||||
$display("-----------------");
|
||||
|
|
@ -105,6 +116,10 @@ module mwith();
|
|||
if (!bar.test_capture_of_callers_derived_var(foo)) $stop;
|
||||
// Check randomization with non-captured non-static variable from different AstNodeModule
|
||||
if (!Bar::test_capture_of_callees_derived_var(foo)) $stop;
|
||||
// Check this.randomize()
|
||||
if (!foo.test_this_randomize()) $stop;
|
||||
// Check this.randomize() with no constraints
|
||||
if (!baz2.test_this_randomize()) $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish();
|
||||
|
|
|
|||
Loading…
Reference in New Issue