Fix passing typedef value as parameter (#6543)
This commit is contained in:
parent
7b4ad29260
commit
1a91ab02cf
|
|
@ -2889,14 +2889,14 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
dtypep = dtypep->skipRefp();
|
||||
while (true) {
|
||||
if (const AstBracketArrayDType* const adtypep = VN_CAST(dtypep, BracketArrayDType)) {
|
||||
dtypep = adtypep->childDTypep()->skipRefp();
|
||||
dtypep = adtypep->subDTypep()->skipRefp();
|
||||
} else if (const AstDynArrayDType* const adtypep = VN_CAST(dtypep, DynArrayDType)) {
|
||||
dtypep = adtypep->childDTypep()->skipRefp();
|
||||
dtypep = adtypep->subDTypep()->skipRefp();
|
||||
} else if (const AstQueueDType* const adtypep = VN_CAST(dtypep, QueueDType)) {
|
||||
dtypep = adtypep->childDTypep()->skipRefp();
|
||||
dtypep = adtypep->subDTypep()->skipRefp();
|
||||
} else if (const AstUnpackArrayDType* const adtypep
|
||||
= VN_CAST(dtypep, UnpackArrayDType)) {
|
||||
dtypep = adtypep->childDTypep()->skipRefp();
|
||||
dtypep = adtypep->subDTypep()->skipRefp();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@
|
|||
|
||||
#include <cctype>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -1265,6 +1266,7 @@ public:
|
|||
class ParamVisitor final : public VNVisitor {
|
||||
// NODE STATE
|
||||
// AstNodeModule::user1 -> bool: already fixed level (temporary)
|
||||
// AstNodeDType::user2 -> bool: already visited from typedef
|
||||
|
||||
// STATE - across all visitors
|
||||
ParamState& m_state; // Common state
|
||||
|
|
@ -1279,6 +1281,8 @@ class ParamVisitor final : public VNVisitor {
|
|||
// STATE - for current visit position (use VL_RESTORER)
|
||||
AstNodeModule* m_modp; // Module iterating
|
||||
string m_generateHierName; // Generate portion of hierarchy name
|
||||
std::map<const AstRefDType*, bool>
|
||||
m_isCircularTypeCache; // Caches return values of `V3Width::isCircularType` calls
|
||||
|
||||
// METHODS
|
||||
|
||||
|
|
@ -1413,6 +1417,25 @@ class ParamVisitor final : public VNVisitor {
|
|||
processWorkQ();
|
||||
}
|
||||
}
|
||||
void visit(AstRefDType* nodep) override {
|
||||
const auto iter = m_isCircularTypeCache.find(nodep);
|
||||
bool isCircular;
|
||||
if (iter != m_isCircularTypeCache.end()) {
|
||||
isCircular = iter->second;
|
||||
} else {
|
||||
isCircular = V3Width::isCircularType(nodep);
|
||||
m_isCircularTypeCache.emplace(nodep, isCircular);
|
||||
}
|
||||
if (isCircular) {
|
||||
nodep->v3error("Typedef's type is circular: " << nodep->prettyName());
|
||||
} else if (nodep->typedefp() && nodep->subDTypep()
|
||||
&& (VN_IS(nodep->subDTypep()->skipRefOrNullp(), IfaceRefDType)
|
||||
|| VN_IS(nodep->subDTypep()->skipRefOrNullp(), ClassRefDType))
|
||||
&& !nodep->skipRefp()->user2SetOnce()) {
|
||||
iterate(nodep->skipRefp());
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstCell* nodep) override {
|
||||
checkParamNotHier(nodep->paramsp());
|
||||
visitCellOrClassRef(nodep, VN_IS(nodep->modp(), Iface));
|
||||
|
|
|
|||
|
|
@ -2108,12 +2108,6 @@ class WidthVisitor final : public VNVisitor {
|
|||
UINFO(4, "dtWidthed " << nodep);
|
||||
}
|
||||
void visit(AstRefDType* nodep) override {
|
||||
if (nodep->doingWidth()) { // Early exit if have circular parameter definition
|
||||
nodep->v3error("Typedef's type is circular: " << nodep->prettyName());
|
||||
nodep->dtypeSetBit();
|
||||
nodep->doingWidth(false);
|
||||
return;
|
||||
}
|
||||
if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed
|
||||
nodep->doingWidth(true);
|
||||
if (nodep->typeofp()) { // type(typeofp_expression)
|
||||
|
|
@ -8958,3 +8952,12 @@ AstNode* V3Width::widthGenerateParamsEdit(
|
|||
// No WidthRemoveVisitor, as don't want to drop $signed etc inside gen blocks
|
||||
return nodep;
|
||||
}
|
||||
|
||||
bool V3Width::isCircularType(const AstRefDType* nodep) {
|
||||
std::set<const AstRefDType*> visited;
|
||||
while (nodep) {
|
||||
if (!visited.insert(nodep).second) return true;
|
||||
nodep = VN_CAST(nodep->subDTypep(), RefDType);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
class AstNetlist;
|
||||
class AstNode;
|
||||
class AstNodeDType;
|
||||
class AstRefDType;
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
|
@ -36,6 +37,8 @@ public:
|
|||
// Replace AstSelBit, etc with AstSel/AstArraySel
|
||||
// Returns replacement node if nodep was deleted, or null if none.
|
||||
static AstNode* widthSelNoIterEdit(AstNode* nodep) VL_MT_DISABLED;
|
||||
|
||||
static bool isCircularType(const AstRefDType* nodep);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2025 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
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile()
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2025 by Antmicro.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
class Foo #(type T);
|
||||
endclass
|
||||
|
||||
class Bar #(type T);
|
||||
endclass
|
||||
|
||||
typedef Bar#(string) s_t;
|
||||
|
||||
class Some #(type T);
|
||||
typedef Bar#(string) s_t;
|
||||
endclass
|
||||
|
||||
module t;
|
||||
initial begin
|
||||
Some#(int)::s_t x[string];
|
||||
Bar#(string) y[string];
|
||||
if ($typename(Foo#(s_t)) != $typename(Foo#(Bar#(string)))) $stop;
|
||||
if ($typename(x) != $typename(y)) $stop;
|
||||
$write("*-* All finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -2,4 +2,7 @@
|
|||
8 | typedef a_t b_t;
|
||||
| ^~~
|
||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||
%Error: t/t_typedef_circ_bad.v:9:9: Typedef's type is circular: b_t
|
||||
9 | typedef b_t a_t;
|
||||
| ^~~
|
||||
%Error: Exiting due to
|
||||
|
|
|
|||
Loading…
Reference in New Issue