Support get/set_randstate as class method.

This commit is contained in:
Wilson Snyder 2025-09-14 10:33:50 -04:00
parent 4b5e602392
commit 5e4668c146
6 changed files with 37 additions and 20 deletions

View File

@ -620,6 +620,7 @@ class AstCMethodHard final : public AstNodeExpr {
// @astgen op2 := pinsp : List[AstNodeExpr] // Arguments
string m_name; // Name of method
bool m_pure = false; // Pure optimizable
bool m_usePtr = false; // Use '->' not '.'
public:
AstCMethodHard(FileLine* fl, AstNodeExpr* fromp, const string& name,
AstNodeExpr* pinsp = nullptr)
@ -641,6 +642,8 @@ public:
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
string emitC() override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const override { return true; }
bool usePtr() const { return m_usePtr; }
void usePtr(bool flag) { m_usePtr = flag; }
private:
void setPurity();

View File

@ -3116,7 +3116,9 @@ int AstCMethodHard::instrCount() const {
return 0;
}
void AstCMethodHard::setPurity() {
static const std::map<std::string, bool> isPureMethod{{"andNot", false},
static const std::map<std::string, bool> isPureMethod{{"__Vm_rng.get_randstate", true},
{"__Vm_rng.set_randstate", false},
{"andNot", false},
{"any", true},
{"anyTriggered", false},
{"assign", false},
@ -3124,6 +3126,7 @@ void AstCMethodHard::setPurity() {
{"atBack", true},
{"atWrite", true},
{"awaitingCurrentTime", true},
{"basicStdRandomization", false},
{"clear", false},
{"clearFired", false},
{"commit", false},
@ -3187,8 +3190,7 @@ void AstCMethodHard::setPurity() {
{"unique", true},
{"unique_index", true},
{"word", true},
{"write_var", false},
{"basicStdRandomization", false}};
{"write_var", false}};
if (name() == "atWriteAppend" || name() == "atWriteAppendBack") {
m_pure = false;

View File

@ -649,7 +649,7 @@ public:
}
void visit(AstCMethodHard* nodep) override {
iterateConst(nodep->fromp());
putns(nodep, ".");
putns(nodep, nodep->usePtr() ? "->" : ".");
putns(nodep, nodep->name());
puts("(");
bool comma = false;

View File

@ -4286,11 +4286,31 @@ class WidthVisitor final : public VNVisitor {
processFTaskRefArgs(nodep);
}
return;
} else if (nodep->name() == "get_randstate" || nodep->name() == "set_randstate") {
// See implementations under AstNodeFTaskRef
nodep->v3warn(E_UNSUPPORTED, "Unsupported: 'get_randstate'/'set_randstate' called "
"on object. Suggest call from inside class.");
nodep->replaceWith(new AstConst{nodep->fileline(), AstConst::BitTrue{}});
} else if (nodep->name() == "get_randstate") {
methodOkArguments(nodep, 0, 0);
first_classp->baseMostClassp()->needRNG(true);
v3Global.useRandomizeMethods(true);
AstCMethodHard* const newp
= new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"__Vm_rng.get_randstate", nullptr};
newp->usePtr(true);
newp->dtypeSetString();
nodep->replaceWith(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
return;
} else if (nodep->name() == "set_randstate") {
methodOkArguments(nodep, 1, 1);
AstNodeExpr* const expr1p = VN_AS(nodep->pinsp(), Arg)->exprp(); // May edit
iterateCheckString(nodep, "LHS", expr1p, BOTH);
AstNodeExpr* const exprp = VN_AS(nodep->pinsp(), Arg)->exprp();
first_classp->baseMostClassp()->needRNG(true);
v3Global.useRandomizeMethods(true);
AstCMethodHard* const newp
= new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
"__Vm_rng.set_randstate", exprp->unlinkFrBack()};
newp->usePtr(true);
newp->dtypeSetString();
nodep->replaceWith(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
return;
} else if (nodep->name() == "constraint_mode") {

View File

@ -1,10 +0,0 @@
%Error-UNSUPPORTED: t/t_randstate_obj.v:20:13: Unsupported: 'get_randstate'/'set_randstate' called on object. Suggest call from inside class.
: ... note: In instance 't'
20 | s = c.get_randstate();
| ^~~~~~~~~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_randstate_obj.v:26:9: Unsupported: 'get_randstate'/'set_randstate' called on object. Suggest call from inside class.
: ... note: In instance 't'
26 | c.set_randstate(s);
| ^~~~~~~~~~~~~
%Error: Exiting due to

View File

@ -11,6 +11,8 @@ import vltest_bootstrap
test.scenarios('simulator')
test.compile(fails=test.vlt_all, expect_filename=test.golden_filename)
test.compile()
test.execute()
test.passes()