Fix virtual methods (#4616)

This commit is contained in:
Ryszard Rozak 2023-10-24 15:51:46 +02:00 committed by GitHub
parent 17721aff55
commit 84125d7c92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 72 additions and 2 deletions

View File

@ -183,6 +183,7 @@ class AstNodeCCall VL_NOT_FINAL : public AstNodeExpr {
// @astgen op2 := argsp : List[AstNodeExpr] // Note: op1 used by some sub-types only
AstCFunc* m_funcp;
string m_argTypes;
bool m_superReference = false; // Called with super reference
protected:
AstNodeCCall(VNType t, FileLine* fl, AstCFunc* funcp, AstNodeExpr* argsp = nullptr)
@ -213,6 +214,8 @@ public:
string emitVerilog() final override { V3ERROR_NA_RETURN(""); }
string emitC() final override { V3ERROR_NA_RETURN(""); }
bool cleanOut() const final override { return true; }
bool superReference() const { return m_superReference; }
void superReference(bool flag) { m_superReference = flag; }
};
class AstNodeFTaskRef VL_NOT_FINAL : public AstNodeExpr {
// A reference to a task (or function)
@ -4198,12 +4201,15 @@ public:
// === AstNodeFTaskRef ===
class AstFuncRef final : public AstNodeFTaskRef {
// A reference to a function
bool m_superReference = false; // Called with super reference
public:
AstFuncRef(FileLine* fl, AstParseRef* namep, AstNodeExpr* pinsp)
: ASTGEN_SUPER_FuncRef(fl, (AstNode*)namep, pinsp) {}
AstFuncRef(FileLine* fl, const string& name, AstNodeExpr* pinsp)
: ASTGEN_SUPER_FuncRef(fl, name, pinsp) {}
ASTGEN_MEMBERS_AstFuncRef;
bool superReference() const { return m_superReference; }
void superReference(bool flag) { m_superReference = flag; }
};
class AstMethodCall final : public AstNodeFTaskRef {
// A reference to a member task (or function)
@ -4240,6 +4246,7 @@ public:
};
class AstTaskRef final : public AstNodeFTaskRef {
// A reference to a task
bool m_superReference = false; // Called with super reference
public:
AstTaskRef(FileLine* fl, AstParseRef* namep, AstNodeExpr* pinsp)
: ASTGEN_SUPER_TaskRef(fl, (AstNode*)namep, pinsp) {
@ -4250,6 +4257,8 @@ public:
dtypeSetVoid();
}
ASTGEN_MEMBERS_AstTaskRef;
bool superReference() const { return m_superReference; }
void superReference(bool flag) { m_superReference = flag; }
};
// === AstNodePreSel ===

View File

@ -486,7 +486,7 @@ public:
// Call static method via the containing class
puts(prefixNameProtect(funcModp) + "::");
puts(funcp->nameProtect());
} else if (VN_IS(funcModp, Class) && funcModp != m_modp) {
} else if (nodep->superReference()) {
// Calling superclass method
puts(prefixNameProtect(funcModp) + "::");
puts(funcp->nameProtect());

View File

@ -2039,6 +2039,7 @@ private:
DotPosition m_dotPos; // Scope part of dotted resolution
VSymEnt* m_dotSymp; // SymEnt for dotted AstParse lookup
const AstDot* m_dotp; // Current dot
bool m_super; // Starts with super reference
bool m_unresolvedCell; // Unresolved cell, needs help from V3Param
bool m_unresolvedClass; // Unresolved class reference, needs help from V3Param
AstNode* m_unlinkedScopep; // Unresolved scope, needs corresponding VarXRef
@ -2050,6 +2051,7 @@ private:
m_dotPos = DP_NONE;
m_dotSymp = curSymp;
m_dotp = nullptr;
m_super = false;
m_dotErr = false;
m_dotText = "";
m_unresolvedCell = false;
@ -2061,6 +2063,7 @@ private:
std::ostringstream sstr;
sstr << "ds=" << names[m_dotPos];
sstr << " dse" << cvtToHex(m_dotSymp);
sstr << " sup=" << m_super;
sstr << " txt=" << m_dotText;
sstr << " unrCell=" << m_unresolvedCell;
sstr << " unrClass=" << m_unresolvedClass;
@ -2462,6 +2465,7 @@ private:
const auto baseClassp = cextp->classp();
UASSERT_OBJ(baseClassp, nodep, "Bad superclass");
m_ds.m_dotSymp = m_statep->getNodeSym(baseClassp);
m_ds.m_super = true;
UINFO(8, " super. " << m_ds.ascii() << endl);
}
}
@ -2538,7 +2542,6 @@ private:
// Generally resolved during Primay, but might be at param time under AstUnlinkedRef
UASSERT_OBJ(m_statep->forPrimary() || m_statep->forPrearray(), nodep,
"ParseRefs should no longer exist");
if (nodep->name() == "super") nodep->v3warn(E_UNSUPPORTED, "Unsupported: super");
const DotStates lastStates = m_ds;
const bool start = (m_ds.m_dotPos == DP_NONE); // Save, as m_dotp will be changed
if (start) {
@ -3079,6 +3082,14 @@ private:
iterateChildren(nodep);
}
if (m_ds.m_super) {
if (AstFuncRef* const funcRefp = VN_CAST(nodep, FuncRef)) {
funcRefp->superReference(true);
} else if (AstTaskRef* const taskRefp = VN_CAST(nodep, TaskRef)) {
taskRefp->superReference(true);
}
}
bool staticAccess = false;
if (m_ds.m_unresolvedClass) {
// Unable to link before V3Param

View File

@ -310,6 +310,7 @@ private:
baseRandCallp->taskp(baseRandomizep);
baseRandCallp->dtypeFrom(baseRandomizep->dtypep());
baseRandCallp->classOrPackagep(nodep->extendsp()->classp());
baseRandCallp->superReference(true);
beginValp = baseRandCallp;
}
}

View File

@ -638,6 +638,12 @@ private:
beginp->addNext(ccallp->makeStmt());
}
if (const AstFuncRef* const funcRefp = VN_CAST(refp, FuncRef)) {
ccallp->superReference(funcRefp->superReference());
} else if (const AstTaskRef* const taskRefp = VN_CAST(refp, TaskRef)) {
ccallp->superReference(taskRefp->superReference());
}
// Convert complicated outputs to temp signals
{
const V3TaskConnects tconnects = V3Task::taskConnects(refp, refp->taskp()->stmtsp());

View File

@ -22,12 +22,48 @@ class VB extends VBase;
endfunction
endclass
virtual class uvm_phase;
virtual function int exec_func;
return 0;
endfunction
endclass
class uvm_topdown_phase extends uvm_phase;
function int get1;
return exec_func();
endfunction
endclass
class uvm_build_phase extends uvm_topdown_phase;
virtual function int exec_func;
return 1;
endfunction
endclass
virtual class Cls;
uvm_phase ph;
endclass
class ExtendsCls extends Cls;
function new;
uvm_build_phase bp = new;
ph = bp;
endfunction
function int get1;
return super.ph.exec_func();
endfunction
endclass
module t;
initial begin
VA va = new;
VB vb = new;
VBase b;
uvm_build_phase ph;
ExtendsCls ec;
if (va.hello() != 2) $stop;
if (vb.hello() != 3) $stop;
@ -35,6 +71,13 @@ module t;
if (b.hello() != 2) $stop;
b = vb;
if (b.hello() != 3) $stop;
ph = new;
if (ph.get1() != 1) $stop;
ec = new;
if (ec.get1() != 1) $stop;
$write("*-* All Finished *-*\n");
$finish;
end