Fix class param extends A=B (#4128)
Visit global class params even if a class extends a param
This commit is contained in:
parent
df86e39845
commit
a10b51705f
|
|
@ -2011,9 +2011,6 @@ private:
|
|||
// *::user4() -> See LinkDotState
|
||||
// Cleared on Cell
|
||||
// AstVar::user5() // bool. True if pin used in this cell
|
||||
// AstClass::user5() // bool. True if class has a parameter
|
||||
// as a (possibly indirect) base class.
|
||||
// Used only in LDS_PRIMARY pass
|
||||
const VNUser3InUse m_inuser3;
|
||||
const VNUser5InUse m_inuser5;
|
||||
|
||||
|
|
@ -2037,6 +2034,7 @@ private:
|
|||
int m_modportNum = 0; // Uniqueify modport numbers
|
||||
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
|
||||
|
||||
struct DotStates {
|
||||
DotPosition m_dotPos; // Scope part of dotted resolution
|
||||
|
|
@ -2240,6 +2238,26 @@ 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 {
|
||||
|
|
@ -3330,9 +3348,13 @@ private:
|
|||
// function
|
||||
iterate(classp);
|
||||
}
|
||||
if (classp->user5()) {
|
||||
if (m_statep->forPrimary()
|
||||
&& m_extendsParam.find(classp) != m_extendsParam.end()) {
|
||||
// Has a parameter as its base class
|
||||
nodep->user5(true);
|
||||
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;
|
||||
}
|
||||
AstPin* paramsp = cpackagerefp->paramsp();
|
||||
|
|
@ -3345,7 +3367,7 @@ private:
|
|||
// Extending has to be handled after V3Param.cpp, but the type
|
||||
// reference has to be visited
|
||||
iterate(paramp);
|
||||
nodep->user5(true);
|
||||
m_extendsParam.insert(nodep);
|
||||
return;
|
||||
} else {
|
||||
AstNodeDType* const paramTypep = paramp->getChildDTypep();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2022 by Arkadiusz Kozdra.
|
||||
// any use, without warranty, 2023 by Antmicro Ltd.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// See also t_class_param.v
|
||||
|
|
@ -44,6 +44,36 @@ class SingletonUnusedDefault #(type T=int);
|
|||
endfunction
|
||||
endclass
|
||||
|
||||
class Empty;
|
||||
endclass
|
||||
|
||||
class Foo #(type IF=Empty) extends IF;
|
||||
typedef Foo foo_t;
|
||||
int a = 1;
|
||||
endclass
|
||||
|
||||
class Bar #(type A=int, type B=A) extends Foo;
|
||||
function int get_size_A;
|
||||
return $bits(A);
|
||||
endfunction
|
||||
function int get_size_B;
|
||||
return $bits(B);
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class Empty2;
|
||||
endclass
|
||||
|
||||
class Baz #(type T=Empty2) extends Foo;
|
||||
endclass
|
||||
|
||||
class Getter1 extends Baz;
|
||||
function int get_1;
|
||||
foo_t f = new;
|
||||
return f.a;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
initial begin
|
||||
|
|
@ -61,6 +91,20 @@ module t (/*AUTOARG*/);
|
|||
automatic SingletonUnusedDefault #(bit) sud1 = SingletonUnusedDefault#(bit)::self();
|
||||
automatic SingletonUnusedDefault #(bit) sud2 = SingletonUnusedDefault#(bit)::self();
|
||||
|
||||
automatic Getter1 getter1 = new;
|
||||
|
||||
typedef bit my_bit_t;
|
||||
Bar#(.A(my_bit_t)) bar_a_bit = new;
|
||||
Bar#(.B(my_bit_t)) bar_b_bit = new;
|
||||
Bar#() bar_default = new;
|
||||
|
||||
if (bar_a_bit.get_size_A != 1) $stop;
|
||||
if (bar_a_bit.get_size_B != 1) $stop;
|
||||
if (bar_b_bit.get_size_A != 32) $stop;
|
||||
if (bar_b_bit.get_size_B != 1) $stop;
|
||||
if (bar_default.get_size_A != 32) $stop;
|
||||
if (bar_default.get_size_B != 32) $stop;
|
||||
|
||||
if (pdt1 != pdt2) $stop;
|
||||
if (pdt2 != pdt3) $stop;
|
||||
if (p1 != p2) $stop;
|
||||
|
|
@ -77,6 +121,8 @@ module t (/*AUTOARG*/);
|
|||
if (pdt1.get_p() != 20) $stop;
|
||||
if (Parcls#(cls2_t)::get_p() != 20) $stop;
|
||||
|
||||
if (getter1.get_1() != 1) $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue