Fix class extend param references (#4136)
Signed-off-by: Ryszard Rozak <rrozak@antmicro.com>
This commit is contained in:
parent
65a484e00b
commit
84a46939b3
|
|
@ -2035,6 +2035,8 @@ private:
|
|||
bool m_inSens = false; // True if in senitem
|
||||
std::set<std::string> m_ifClassImpNames; // Names imported from interface class
|
||||
std::set<AstClass*> m_extendsParam; // Classes that has a parameter as its super class
|
||||
bool m_insideClassExtParam = false; // Inside a class that extends a parameter.
|
||||
// It may be set only in linkDotPrimary.
|
||||
|
||||
struct DotStates {
|
||||
DotPosition m_dotPos; // Scope part of dotted resolution
|
||||
|
|
@ -2238,26 +2240,6 @@ private:
|
|||
if (classp->isInterfaceClass()) importImplementsClass(nodep, srcp, classp);
|
||||
if (!cextp->isImplements()) m_curSymp->importFromClass(m_statep->symsp(), srcp);
|
||||
}
|
||||
void visitGlobalClassParams(AstClass* const nodep) {
|
||||
// Parameters from port parameter list are at the beginning of the members list, so if a
|
||||
// node, that isn't a parameter, is encountered, all nodes after aren't global parameters
|
||||
// too.
|
||||
for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
// Global parameters are at the beginning of the members list, so if a node, that isn't
|
||||
// a global parameter, is encountered, all nodes after it aren't global parameters too.
|
||||
bool globalParam = false;
|
||||
if (const AstParamTypeDType* const parp = VN_CAST(stmtp, ParamTypeDType)) {
|
||||
if (parp->isGParam()) globalParam = true;
|
||||
} else if (const AstVar* const varp = VN_CAST(stmtp, Var)) {
|
||||
if (varp->isGParam()) globalParam = true;
|
||||
}
|
||||
if (globalParam) {
|
||||
iterate(stmtp);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// VISITs
|
||||
void visit(AstNetlist* nodep) override {
|
||||
|
|
@ -2424,12 +2406,17 @@ private:
|
|||
nodep->v3error("'super' used on non-extended class (IEEE 1800-2017 8.15)");
|
||||
m_ds.m_dotErr = true;
|
||||
} else {
|
||||
const auto cextp = classp->extendsp();
|
||||
UASSERT_OBJ(cextp, nodep, "Bad super extends link");
|
||||
const auto sclassp = cextp->classp();
|
||||
UASSERT_OBJ(sclassp, nodep, "Bad superclass");
|
||||
m_ds.m_dotSymp = m_statep->getNodeSym(sclassp);
|
||||
UINFO(8, " super. " << m_ds.ascii() << endl);
|
||||
if (m_statep->forPrimary()
|
||||
&& m_extendsParam.find(classp) != m_extendsParam.end()) {
|
||||
m_ds.m_unresolvedClass = true;
|
||||
} else {
|
||||
const auto cextp = classp->extendsp();
|
||||
UASSERT_OBJ(cextp, nodep, "Bad super extends link");
|
||||
const auto sclassp = cextp->classp();
|
||||
UASSERT_OBJ(sclassp, nodep, "Bad superclass");
|
||||
m_ds.m_dotSymp = m_statep->getNodeSym(sclassp);
|
||||
UINFO(8, " super. " << m_ds.ascii() << endl);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (VN_IS(nodep->lhsp(), ClassOrPackageRef)) {
|
||||
|
|
@ -2798,8 +2785,10 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
if (!ok) {
|
||||
// Don't throw error ifthe reference is inside a class that extends a param, because
|
||||
// some members can't be linked in such a case. m_insideClassExtParam may be true only
|
||||
// in the first stage of linking.
|
||||
if (!ok && !m_insideClassExtParam) {
|
||||
// Cells/interfaces can't be implicit
|
||||
const bool isCell = foundp ? VN_IS(foundp->nodep(), Cell) : false;
|
||||
const bool checkImplicit = (!m_ds.m_dotp && m_ds.m_dotText == "" && !isCell);
|
||||
|
|
@ -3110,6 +3099,10 @@ private:
|
|||
nodep->taskp(taskp);
|
||||
nodep->classOrPackagep(foundp->classOrPackagep());
|
||||
UINFO(7, " Resolved " << nodep << endl); // Also prints taskp
|
||||
} else if (m_insideClassExtParam) {
|
||||
// The reference may point to a method declared in a super class, which is proved
|
||||
// by a parameter. In such a case, it can't be linked at the first stage.
|
||||
return;
|
||||
} else {
|
||||
// Note ParseRef has similar error handling/message output
|
||||
UINFO(7, " ErrFtask curSymp=se" << cvtToHex(m_curSymp) << " dotSymp=se"
|
||||
|
|
@ -3300,6 +3293,7 @@ private:
|
|||
VL_RESTORER(m_curSymp);
|
||||
VL_RESTORER(m_modSymp);
|
||||
VL_RESTORER(m_ifClassImpNames);
|
||||
VL_RESTORER(m_insideClassExtParam);
|
||||
{
|
||||
m_ds.init(m_curSymp);
|
||||
// Until overridden by a SCOPE
|
||||
|
|
@ -3352,10 +3346,7 @@ private:
|
|||
&& m_extendsParam.find(classp) != m_extendsParam.end()) {
|
||||
// Has a parameter as its base class
|
||||
m_extendsParam.insert(nodep);
|
||||
// Link global parameters. They are declared before the extends
|
||||
// statement, so should be unrelated to the base class
|
||||
visitGlobalClassParams(nodep);
|
||||
return;
|
||||
m_insideClassExtParam = true;
|
||||
}
|
||||
AstPin* paramsp = cpackagerefp->paramsp();
|
||||
if (paramsp) paramsp = paramsp->cloneTree(true);
|
||||
|
|
@ -3364,13 +3355,12 @@ private:
|
|||
} else if (AstParamTypeDType* const paramp
|
||||
= VN_CAST(foundp->nodep(), ParamTypeDType)) {
|
||||
if (m_statep->forPrimary()) {
|
||||
// Extending has to be handled after V3Param.cpp, but the type
|
||||
// reference has to be visited
|
||||
iterate(paramp);
|
||||
// Extending has to be handled after V3Param.cpp
|
||||
m_extendsParam.insert(nodep);
|
||||
return;
|
||||
m_insideClassExtParam = true;
|
||||
continue;
|
||||
} else {
|
||||
AstNodeDType* const paramTypep = paramp->getChildDTypep();
|
||||
AstNodeDType* const paramTypep = paramp->subDTypep();
|
||||
classRefDtypep
|
||||
= VN_CAST(paramTypep->cloneTree(false), ClassRefDType);
|
||||
if (!classRefDtypep) {
|
||||
|
|
|
|||
|
|
@ -949,16 +949,18 @@ class ParamVisitor final : public VNVisitor {
|
|||
|
||||
// Process once; note user5 will be cleared on specialization, so we will do the
|
||||
// specialized module if needed
|
||||
if (modp->user5SetOnce()) continue;
|
||||
if (!modp->user5SetOnce()) {
|
||||
|
||||
// TODO: this really should be an assert, but classes and hier_blocks are special...
|
||||
if (modp->someInstanceName().empty()) modp->someInstanceName(modp->origName());
|
||||
// TODO: this really should be an assert, but classes and hier_blocks are
|
||||
// special...
|
||||
if (modp->someInstanceName().empty()) modp->someInstanceName(modp->origName());
|
||||
|
||||
// Iterate the body
|
||||
{
|
||||
VL_RESTORER(m_modp);
|
||||
m_modp = modp;
|
||||
iterateChildren(modp);
|
||||
// Iterate the body
|
||||
{
|
||||
VL_RESTORER(m_modp);
|
||||
m_modp = modp;
|
||||
iterateChildren(modp);
|
||||
}
|
||||
}
|
||||
|
||||
// Process interface cells, then non-interface cells, which may reference an interface
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ module t (/*AUTOARG*/
|
|||
endfunction
|
||||
endclass
|
||||
|
||||
class ExtendBar extends Bar;
|
||||
class ExtendBar extends Bar#();
|
||||
function int get_x;
|
||||
return super.get_x();
|
||||
endfunction
|
||||
|
|
@ -39,7 +39,7 @@ module t (/*AUTOARG*/
|
|||
endfunction
|
||||
endclass
|
||||
|
||||
Bar bar_foo_i;
|
||||
Bar #() bar_foo_i;
|
||||
Bar #(Baz) bar_baz_i;
|
||||
ExtendBar extend_bar_i;
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ class Foo #(type IF=Empty) extends IF;
|
|||
int a = 1;
|
||||
endclass
|
||||
|
||||
class Bar #(type A=int, type B=A) extends Foo;
|
||||
class Bar #(type A=int, type B=A) extends Foo#();
|
||||
function int get_size_A;
|
||||
return $bits(A);
|
||||
endfunction
|
||||
|
|
@ -64,16 +64,32 @@ endclass
|
|||
class Empty2;
|
||||
endclass
|
||||
|
||||
class Baz #(type T=Empty2) extends Foo;
|
||||
class Baz #(type T=Empty2) extends Foo#();
|
||||
endclass
|
||||
|
||||
class Getter1 extends Baz;
|
||||
class Getter1 extends Baz#();
|
||||
function int get_1;
|
||||
foo_t f = new;
|
||||
return f.a;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class MyInt1;
|
||||
int x = 1;
|
||||
endclass
|
||||
|
||||
class MyInt2;
|
||||
int x = 2;
|
||||
endclass
|
||||
|
||||
class ExtendsMyInt #(type T=MyInt1) extends T;
|
||||
typedef ExtendsMyInt#(T) this_type;
|
||||
function int get_this_type_x;
|
||||
this_type t = new;
|
||||
return t.x;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
initial begin
|
||||
|
|
@ -93,6 +109,9 @@ module t (/*AUTOARG*/);
|
|||
|
||||
automatic Getter1 getter1 = new;
|
||||
|
||||
automatic ExtendsMyInt#() ext1 = new;
|
||||
automatic ExtendsMyInt#(MyInt2) ext2 = new;
|
||||
|
||||
typedef bit my_bit_t;
|
||||
Bar#(.A(my_bit_t)) bar_a_bit = new;
|
||||
Bar#(.B(my_bit_t)) bar_b_bit = new;
|
||||
|
|
@ -123,6 +142,9 @@ module t (/*AUTOARG*/);
|
|||
|
||||
if (getter1.get_1() != 1) $stop;
|
||||
|
||||
if (ext1.get_this_type_x() != 1) $stop;
|
||||
if (ext2.get_this_type_x() != 2) $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue