Fixes #7236
This commit is contained in:
parent
56ed47ee7c
commit
e7a644a3fc
|
|
@ -233,6 +233,7 @@ private:
|
|||
string m_dotted; // Dotted part of scope the name()ed task/func is under or ""
|
||||
string m_inlinedDots; // Dotted hierarchy flattened out
|
||||
bool m_pli = false; // Pli system call ($name)
|
||||
bool m_containsGenBlock = false; // Contains gen block reference
|
||||
VIsCached m_purity; // Pure state
|
||||
|
||||
protected:
|
||||
|
|
@ -259,6 +260,8 @@ public:
|
|||
void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
|
||||
bool pli() const { return m_pli; }
|
||||
void pli(bool flag) { m_pli = flag; }
|
||||
bool containsGenBlock() const { return m_containsGenBlock; }
|
||||
void containsGenBlock(const bool flag) { m_containsGenBlock = flag; }
|
||||
bool isPure() override;
|
||||
|
||||
string emitVerilog() final override { V3ERROR_NA_RETURN(""); }
|
||||
|
|
|
|||
|
|
@ -3111,6 +3111,7 @@ void AstActive::dumpJson(std::ostream& str) const { dumpJsonGen(str); }
|
|||
void AstNodeFTaskRef::dump(std::ostream& str) const {
|
||||
this->AstNodeExpr::dump(str);
|
||||
if (classOrPackagep()) str << " pkg=" << nodeAddr(classOrPackagep());
|
||||
if (containsGenBlock()) str << " [GENBLK]";
|
||||
str << " -> ";
|
||||
if (dotted() != "") str << ".=" << dotted() << " ";
|
||||
if (taskp()) {
|
||||
|
|
@ -3121,6 +3122,7 @@ void AstNodeFTaskRef::dump(std::ostream& str) const {
|
|||
}
|
||||
void AstNodeFTaskRef::dumpJson(std::ostream& str) const {
|
||||
dumpJsonStrFunc(str, dotted);
|
||||
dumpJsonBoolFuncIf(str, containsGenBlock);
|
||||
dumpJsonGen(str);
|
||||
}
|
||||
void AstNodeFTask::dump(std::ostream& str) const {
|
||||
|
|
|
|||
|
|
@ -5067,6 +5067,17 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
m_ds.m_dotPos = DP_MEMBER;
|
||||
} else if (m_ds.m_dotp && m_ds.m_dotPos == DP_FINAL) {
|
||||
nodep->dotted(m_ds.m_dotText); // Maybe ""
|
||||
// Only flag FTaskRefs under generate-if/case blocks that may be
|
||||
// pruned. GenFor and plain begin-blocks won't be pruned by V3Param.
|
||||
// VarXRef uses the broader m_genBlk flag (set for all GenBlocks)
|
||||
// because genfor unrolling also removes variables.
|
||||
if (m_ds.m_genBlk && m_ds.m_dotSymp) {
|
||||
const AstNode* const blkp = m_ds.m_dotSymp->nodep();
|
||||
if (VN_IS(blkp, GenBlock)
|
||||
&& (VN_IS(blkp->backp(), GenIf) || VN_IS(blkp->backp(), GenCase))) {
|
||||
nodep->containsGenBlock(true);
|
||||
}
|
||||
}
|
||||
} else if (m_ds.m_dotp && m_ds.m_dotPos == DP_MEMBER) {
|
||||
// Found a Var, everything following is method call.
|
||||
// {scope}.{var}.HERE {method} ( ARGS )
|
||||
|
|
|
|||
|
|
@ -2529,6 +2529,14 @@ class ParamVisitor final : public VNVisitor {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
void visit(AstNodeFTaskRef* nodep) override {
|
||||
if (nodep->containsGenBlock()) {
|
||||
// Needs relink, as may remove pointed-to task/func
|
||||
nodep->taskp(nullptr);
|
||||
return;
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstVarXRef* nodep) override {
|
||||
if (nodep->containsGenBlock()) {
|
||||
// Needs relink, as may remove pointed-to var
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# 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-FileCopyrightText: 2026 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(verilator_flags2=["--binary"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// DESCRIPTION: Verilator: Verify function calls through generate-if block references
|
||||
//
|
||||
// When a function is defined inside a generate-if block and called via a
|
||||
// dotted reference (e.g. defs.foo()), the FUNCREF must survive generate
|
||||
// pruning. Previously the FUNCREF could point to the deleted else-branch
|
||||
// function, causing a broken-link internal error.
|
||||
//
|
||||
// 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-FileCopyrightText: 2026 Wilson Snyder
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
module t(/*AUTOARG*/);
|
||||
generate
|
||||
if (1) begin : defs
|
||||
function automatic logic foo;
|
||||
foo = 1'b1;
|
||||
endfunction
|
||||
end else begin : defs
|
||||
function automatic logic foo;
|
||||
foo = 1'b0;
|
||||
endfunction
|
||||
end
|
||||
endgenerate
|
||||
|
||||
initial begin
|
||||
if (defs.foo() !== 1'b1) begin
|
||||
$display("%%Error: defs.foo() returned wrong value");
|
||||
$stop;
|
||||
end
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue