From af2327aaf45721a778bfbdde5367c8cbd4790ca9 Mon Sep 17 00:00:00 2001 From: Ryszard Rozak Date: Fri, 17 Oct 2025 15:06:46 +0200 Subject: [PATCH] Fix hierarchical references with parameterized modules and interfaces (#5649) (#6566) --- src/V3LinkDot.cpp | 10 ++++-- test_regress/t/t_interface_wire_bad_param.out | 7 +++-- test_regress/t/t_virtual_interface_param.py | 18 +++++++++++ test_regress/t/t_virtual_interface_param.v | 31 +++++++++++++++++++ .../t/t_virtual_interface_param_bind.py | 18 +++++++++++ .../t/t_virtual_interface_param_bind.v | 30 ++++++++++++++++++ 6 files changed, 108 insertions(+), 6 deletions(-) create mode 100755 test_regress/t/t_virtual_interface_param.py create mode 100644 test_regress/t/t_virtual_interface_param.v create mode 100755 test_regress/t/t_virtual_interface_param_bind.py create mode 100644 test_regress/t/t_virtual_interface_param_bind.v diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 33232de65..d0b9ca48e 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -3596,12 +3596,16 @@ class LinkDotResolveVisitor final : public VNVisitor { = findIfaceTopVarp(nodep, parentEntp, nodep->name()); // ok = true; - m_ds.m_dotText = VString::dot(m_ds.m_dotText, ".", nodep->name()); m_ds.m_dotSymp = foundp; m_ds.m_dotPos = DP_SCOPE; UINFO(9, indent() << " cell -> iface varref " << foundp->nodep()); - AstNode* const newp - = new AstVarRef{nodep->fileline(), ifaceRefVarp, VAccess::READ}; + AstNodeVarRef* newp; + if (m_ds.m_dotText != "") { + newp = new AstVarXRef{nodep->fileline(), ifaceRefVarp, m_ds.m_dotText, + VAccess::READ}; + } else { + newp = new AstVarRef{nodep->fileline(), ifaceRefVarp, VAccess::READ}; + } nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } else if (VN_IS(cellp->modp(), NotFoundModule)) { diff --git a/test_regress/t/t_interface_wire_bad_param.out b/test_regress/t/t_interface_wire_bad_param.out index 9362c2667..144b8372f 100644 --- a/test_regress/t/t_interface_wire_bad_param.out +++ b/test_regress/t/t_interface_wire_bad_param.out @@ -1,5 +1,6 @@ -%Error: Internal Error: t/t_interface_wire_bad_param.v:17:20: ../V3Broken.cpp:#: Broken link in node (or something without maybePointedTo): 'm_varp && !m_varp->brokeExists()' @ ./V3Ast__gen_impl.h:# - : ... note: In instance 't' +%Error: t/t_interface_wire_bad_param.v:17:20: Operator ASSIGNW expected non-interface on Assign RHS but 'a' is an interface. + : ... note: In instance 't' 17 | wire wbad = sub.a; | ^ - ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. + ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. +%Error: Exiting due to diff --git a/test_regress/t/t_virtual_interface_param.py b/test_regress/t/t_virtual_interface_param.py new file mode 100755 index 000000000..d4f986441 --- /dev/null +++ b/test_regress/t/t_virtual_interface_param.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 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() diff --git a/test_regress/t/t_virtual_interface_param.v b/test_regress/t/t_virtual_interface_param.v new file mode 100644 index 000000000..674f2c7c9 --- /dev/null +++ b/test_regress/t/t_virtual_interface_param.v @@ -0,0 +1,31 @@ +// 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 + +interface b_if #( + parameter p +); + int x = p; +endinterface + +module t; + m #(.p(2)) m_i (); + + initial begin + virtual b_if#(2) vif = m_i.b; + int y = m_i.b.x; + + if (vif.x != 2) $stop; + if (y != 2) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule + +module m #( + parameter p = 1 +) (); + b_if #(p) b (); +endmodule diff --git a/test_regress/t/t_virtual_interface_param_bind.py b/test_regress/t/t_virtual_interface_param_bind.py new file mode 100755 index 000000000..d4f986441 --- /dev/null +++ b/test_regress/t/t_virtual_interface_param_bind.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 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() diff --git a/test_regress/t/t_virtual_interface_param_bind.v b/test_regress/t/t_virtual_interface_param_bind.v new file mode 100644 index 000000000..9b70d86cc --- /dev/null +++ b/test_regress/t/t_virtual_interface_param_bind.v @@ -0,0 +1,30 @@ +// 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 + +interface b_if; + int x = 1; +endinterface + +module t; + bind m b_if if_bind (); + m #(.p(2)) m_i (); + + typedef virtual b_if vif_t; + initial begin + vif_t vif = t.m_i.if_bind; + int y = t.m_i.if_bind.x; + + if (vif.x != 1) $stop; + if (y != 1) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule + +module m #( + parameter p = 1 +) (); +endmodule