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
|
// *::user4() -> See LinkDotState
|
||||||
// Cleared on Cell
|
// Cleared on Cell
|
||||||
// AstVar::user5() // bool. True if pin used in this 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 VNUser3InUse m_inuser3;
|
||||||
const VNUser5InUse m_inuser5;
|
const VNUser5InUse m_inuser5;
|
||||||
|
|
||||||
|
|
@ -2037,6 +2034,7 @@ private:
|
||||||
int m_modportNum = 0; // Uniqueify modport numbers
|
int m_modportNum = 0; // Uniqueify modport numbers
|
||||||
bool m_inSens = false; // True if in senitem
|
bool m_inSens = false; // True if in senitem
|
||||||
std::set<std::string> m_ifClassImpNames; // Names imported from interface class
|
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 {
|
struct DotStates {
|
||||||
DotPosition m_dotPos; // Scope part of dotted resolution
|
DotPosition m_dotPos; // Scope part of dotted resolution
|
||||||
|
|
@ -2240,6 +2238,26 @@ private:
|
||||||
if (classp->isInterfaceClass()) importImplementsClass(nodep, srcp, classp);
|
if (classp->isInterfaceClass()) importImplementsClass(nodep, srcp, classp);
|
||||||
if (!cextp->isImplements()) m_curSymp->importFromClass(m_statep->symsp(), srcp);
|
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
|
// VISITs
|
||||||
void visit(AstNetlist* nodep) override {
|
void visit(AstNetlist* nodep) override {
|
||||||
|
|
@ -3330,9 +3348,13 @@ private:
|
||||||
// function
|
// function
|
||||||
iterate(classp);
|
iterate(classp);
|
||||||
}
|
}
|
||||||
if (classp->user5()) {
|
if (m_statep->forPrimary()
|
||||||
|
&& m_extendsParam.find(classp) != m_extendsParam.end()) {
|
||||||
// Has a parameter as its base class
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
AstPin* paramsp = cpackagerefp->paramsp();
|
AstPin* paramsp = cpackagerefp->paramsp();
|
||||||
|
|
@ -3345,7 +3367,7 @@ private:
|
||||||
// Extending has to be handled after V3Param.cpp, but the type
|
// Extending has to be handled after V3Param.cpp, but the type
|
||||||
// reference has to be visited
|
// reference has to be visited
|
||||||
iterate(paramp);
|
iterate(paramp);
|
||||||
nodep->user5(true);
|
m_extendsParam.insert(nodep);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
AstNodeDType* const paramTypep = paramp->getChildDTypep();
|
AstNodeDType* const paramTypep = paramp->getChildDTypep();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
// 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
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
// See also t_class_param.v
|
// See also t_class_param.v
|
||||||
|
|
@ -44,6 +44,36 @@ class SingletonUnusedDefault #(type T=int);
|
||||||
endfunction
|
endfunction
|
||||||
endclass
|
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*/);
|
module t (/*AUTOARG*/);
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
|
|
@ -61,6 +91,20 @@ module t (/*AUTOARG*/);
|
||||||
automatic SingletonUnusedDefault #(bit) sud1 = SingletonUnusedDefault#(bit)::self();
|
automatic SingletonUnusedDefault #(bit) sud1 = SingletonUnusedDefault#(bit)::self();
|
||||||
automatic SingletonUnusedDefault #(bit) sud2 = 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 (pdt1 != pdt2) $stop;
|
||||||
if (pdt2 != pdt3) $stop;
|
if (pdt2 != pdt3) $stop;
|
||||||
if (p1 != p2) $stop;
|
if (p1 != p2) $stop;
|
||||||
|
|
@ -77,6 +121,8 @@ module t (/*AUTOARG*/);
|
||||||
if (pdt1.get_p() != 20) $stop;
|
if (pdt1.get_p() != 20) $stop;
|
||||||
if (Parcls#(cls2_t)::get_p() != 20) $stop;
|
if (Parcls#(cls2_t)::get_p() != 20) $stop;
|
||||||
|
|
||||||
|
if (getter1.get_1() != 1) $stop;
|
||||||
|
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue