Fix class param extends A=B (#4128)

Visit global class params even if a class extends a param
This commit is contained in:
Ryszard Rozak 2023-04-17 14:08:57 +02:00 committed by GitHub
parent df86e39845
commit a10b51705f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 75 additions and 7 deletions

View File

@ -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();

View File

@ -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