forked from github/verilator
Support access to constructs inside type parameters (#3702)
This changeset brings support for accesses like: class Cls#(type TYPE1); TYPE1::some_method(); endclass It is done by delaying dot resolution on type parameters until they get resolved by V3Param, and doing a more thorough reference skip.
This commit is contained in:
parent
5688d1a935
commit
627a144b83
@ -912,6 +912,7 @@ public:
|
|||||||
dtypep(nullptr); // V3Width will resolve
|
dtypep(nullptr); // V3Width will resolve
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_AstParamTypeDType;
|
ASTGEN_MEMBERS_AstParamTypeDType;
|
||||||
|
void dump(std::ostream& str = std::cout) const override;
|
||||||
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
|
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
|
||||||
AstNodeDType* subDTypep() const override { return dtypep() ? dtypep() : childDTypep(); }
|
AstNodeDType* subDTypep() const override { return dtypep() ? dtypep() : childDTypep(); }
|
||||||
AstBasicDType* basicp() const override VL_MT_SAFE { return subDTypep()->basicp(); }
|
AstBasicDType* basicp() const override VL_MT_SAFE { return subDTypep()->basicp(); }
|
||||||
|
@ -1719,12 +1719,25 @@ void AstTimeImport::dump(std::ostream& str) const {
|
|||||||
void AstTypedef::dump(std::ostream& str) const {
|
void AstTypedef::dump(std::ostream& str) const {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
if (attrPublic()) str << " [PUBLIC]";
|
if (attrPublic()) str << " [PUBLIC]";
|
||||||
|
if (subDTypep()) {
|
||||||
|
str << " -> ";
|
||||||
|
subDTypep()->dump(str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void AstNodeRange::dump(std::ostream& str) const { this->AstNode::dump(str); }
|
void AstNodeRange::dump(std::ostream& str) const { this->AstNode::dump(str); }
|
||||||
void AstRange::dump(std::ostream& str) const {
|
void AstRange::dump(std::ostream& str) const {
|
||||||
this->AstNodeRange::dump(str);
|
this->AstNodeRange::dump(str);
|
||||||
if (littleEndian()) str << " [LITTLE]";
|
if (littleEndian()) str << " [LITTLE]";
|
||||||
}
|
}
|
||||||
|
void AstParamTypeDType::dump(std::ostream& str) const {
|
||||||
|
this->AstNodeDType::dump(str);
|
||||||
|
if (subDTypep()) {
|
||||||
|
str << " -> ";
|
||||||
|
subDTypep()->dump(str);
|
||||||
|
} else {
|
||||||
|
str << " -> UNLINKED";
|
||||||
|
}
|
||||||
|
}
|
||||||
void AstRefDType::dump(std::ostream& str) const {
|
void AstRefDType::dump(std::ostream& str) const {
|
||||||
this->AstNodeDType::dump(str);
|
this->AstNodeDType::dump(str);
|
||||||
if (typedefp() || subDTypep()) {
|
if (typedefp() || subDTypep()) {
|
||||||
@ -2095,7 +2108,8 @@ void AstClassOrPackageRef::dump(std::ostream& str) const {
|
|||||||
}
|
}
|
||||||
AstNodeModule* AstClassOrPackageRef::classOrPackagep() const {
|
AstNodeModule* AstClassOrPackageRef::classOrPackagep() const {
|
||||||
AstNode* foundp = m_classOrPackageNodep;
|
AstNode* foundp = m_classOrPackageNodep;
|
||||||
while (auto* const anodep = VN_CAST(foundp, Typedef)) foundp = anodep->subDTypep();
|
if (auto* const anodep = VN_CAST(foundp, Typedef)) foundp = anodep->subDTypep();
|
||||||
|
if (auto* const anodep = VN_CAST(foundp, NodeDType)) foundp = anodep->skipRefp();
|
||||||
if (auto* const anodep = VN_CAST(foundp, ClassRefDType)) foundp = anodep->classp();
|
if (auto* const anodep = VN_CAST(foundp, ClassRefDType)) foundp = anodep->classp();
|
||||||
return VN_CAST(foundp, NodeModule);
|
return VN_CAST(foundp, NodeModule);
|
||||||
}
|
}
|
||||||
|
@ -2069,11 +2069,13 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isParamedClassRef(const AstNode* nodep) {
|
bool isParamedClassRef(const AstNode* nodep) {
|
||||||
|
// Is this a parametrized reference to a class, or a reference to class parameter
|
||||||
if (const auto* classRefp = VN_CAST(nodep, ClassOrPackageRef)) {
|
if (const auto* classRefp = VN_CAST(nodep, ClassOrPackageRef)) {
|
||||||
if (classRefp->paramsp()) return true;
|
if (classRefp->paramsp()) return true;
|
||||||
const auto* classp = classRefp->classOrPackageNodep();
|
const auto* classp = classRefp->classOrPackageNodep();
|
||||||
while (const auto* typedefp = VN_CAST(classp, Typedef)) classp = typedefp->subDTypep();
|
while (const auto* typedefp = VN_CAST(classp, Typedef)) classp = typedefp->subDTypep();
|
||||||
return VN_IS(classp, ClassRefDType) && VN_AS(classp, ClassRefDType)->paramsp();
|
return (VN_IS(classp, ClassRefDType) && VN_AS(classp, ClassRefDType)->paramsp())
|
||||||
|
|| VN_IS(classp, ParamTypeDType);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2633,8 +2635,9 @@ private:
|
|||||||
// Class: Recurse inside or cleanup not founds
|
// Class: Recurse inside or cleanup not founds
|
||||||
// checkNoDot not appropriate, can be under a dot
|
// checkNoDot not appropriate, can be under a dot
|
||||||
AstNode::user5ClearTree();
|
AstNode::user5ClearTree();
|
||||||
UASSERT_OBJ(m_statep->forPrimary() || nodep->classOrPackagep(), nodep,
|
UASSERT_OBJ(m_statep->forPrimary() || VN_IS(nodep->classOrPackageNodep(), ParamTypeDType)
|
||||||
"ClassRef has unlinked class");
|
|| nodep->classOrPackagep(),
|
||||||
|
nodep, "ClassRef has unlinked class");
|
||||||
UASSERT_OBJ(m_statep->forPrimary() || !nodep->paramsp(), nodep,
|
UASSERT_OBJ(m_statep->forPrimary() || !nodep->paramsp(), nodep,
|
||||||
"class reference parameter not removed by V3Param");
|
"class reference parameter not removed by V3Param");
|
||||||
VL_RESTORER(m_ds);
|
VL_RESTORER(m_ds);
|
||||||
|
@ -936,11 +936,13 @@ class ParamVisitor final : public VNVisitor {
|
|||||||
srcModp = modCellp->modp();
|
srcModp = modCellp->modp();
|
||||||
} else if (const auto* classRefp = VN_CAST(cellp, ClassOrPackageRef)) {
|
} else if (const auto* classRefp = VN_CAST(cellp, ClassOrPackageRef)) {
|
||||||
srcModp = classRefp->classOrPackagep();
|
srcModp = classRefp->classOrPackagep();
|
||||||
|
if (VN_IS(classRefp->classOrPackageNodep(), ParamTypeDType)) continue;
|
||||||
} else if (const auto* classRefp = VN_CAST(cellp, ClassRefDType)) {
|
} else if (const auto* classRefp = VN_CAST(cellp, ClassRefDType)) {
|
||||||
srcModp = classRefp->classp();
|
srcModp = classRefp->classp();
|
||||||
} else {
|
} else {
|
||||||
cellp->v3fatalSrc("Expected module parametrization");
|
cellp->v3fatalSrc("Expected module parametrization");
|
||||||
}
|
}
|
||||||
|
UASSERT_OBJ(srcModp, cellp, "Unlinked class ref");
|
||||||
|
|
||||||
// Update path
|
// Update path
|
||||||
string someInstanceName(modp->someInstanceName());
|
string someInstanceName(modp->someInstanceName());
|
||||||
|
21
test_regress/t/t_class_param_type.pl
Executable file
21
test_regress/t/t_class_param_type.pl
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2020 by Wilson Snyder. This program is free software; you
|
||||||
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
scenarios(simulator => 1);
|
||||||
|
|
||||||
|
compile(
|
||||||
|
);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
check_finished => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
32
test_regress/t/t_class_param_type.v
Normal file
32
test_regress/t/t_class_param_type.v
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// 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.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
// See also t_class_param.v
|
||||||
|
|
||||||
|
class Parcls #(type T);
|
||||||
|
static function int get_p;
|
||||||
|
return T::get_p();
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class Cls;
|
||||||
|
static function int get_p;
|
||||||
|
return 20;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
typedef Cls cls_t;
|
||||||
|
typedef cls_t cls2_t;
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if (Parcls#(cls2_t)::get_p() != 20) $stop;
|
||||||
|
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
Loading…
Reference in New Issue
Block a user