From e00403351c104ea1ff2900b313da95437abb5dc4 Mon Sep 17 00:00:00 2001 From: Ryszard Rozak Date: Wed, 22 Oct 2025 08:37:43 +0200 Subject: [PATCH] Fix references to interfaces containing generate blocks (#6579) --- src/V3LinkDot.cpp | 9 +- .../t/t_virtual_interface_gen_for_ref.py | 18 ++++ .../t/t_virtual_interface_gen_for_ref.v | 82 +++++++++++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100755 test_regress/t/t_virtual_interface_gen_for_ref.py create mode 100644 test_regress/t/t_virtual_interface_gen_for_ref.v diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 51c4b211b..56a2d23bd 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -3597,10 +3597,17 @@ class LinkDotResolveVisitor final : public VNVisitor { m_ds.m_dotSymp = foundp; m_ds.m_dotPos = DP_SCOPE; UINFO(9, indent() << " cell -> iface varref " << foundp->nodep()); - AstNodeVarRef* newp; + AstNodeExpr* newp; if (m_ds.m_dotText != "") { newp = new AstVarXRef{nodep->fileline(), ifaceRefVarp, m_ds.m_dotText, VAccess::READ}; + if (m_ds.m_unresolvedCell && m_ds.m_unlinkedScopep) { + newp = new AstUnlinkedRef{nodep->fileline(), newp, newp->name(), + m_ds.m_unlinkedScopep->unlinkFrBack()}; + m_ds.m_unlinkedScopep = nullptr; + m_ds.m_unresolvedCell = false; + m_ds.m_dotText = ""; + } } else { newp = new AstVarRef{nodep->fileline(), ifaceRefVarp, VAccess::READ}; } diff --git a/test_regress/t/t_virtual_interface_gen_for_ref.py b/test_regress/t/t_virtual_interface_gen_for_ref.py new file mode 100755 index 000000000..d4f986441 --- /dev/null +++ b/test_regress/t/t_virtual_interface_gen_for_ref.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_gen_for_ref.v b/test_regress/t/t_virtual_interface_gen_for_ref.v new file mode 100644 index 000000000..2d8b30a86 --- /dev/null +++ b/test_regress/t/t_virtual_interface_gen_for_ref.v @@ -0,0 +1,82 @@ +// 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 + +package uvm_pkg; + class uvm_resource_db #( + type T = int + ); + static T interf; + + static function void set(input T accessor); + interf = accessor; + endfunction + endclass + + class uvm_config_db #( + type T = int + ) extends uvm_resource_db #(T); + endclass +endpackage + + +interface iface (); + int x = 1; +endinterface + +module t; + import uvm_pkg::*; + + bind bound iface if_bind (); + dut i_dut (); + + initial begin + uvm_config_db#(virtual iface)::set( + t.i_dut.first_gen[0].i_fail.i_a.i_b.i_c.second_gen[0].i_d.i_bound.if_bind); + + if (uvm_config_db#(virtual iface)::interf.x != 1) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule + +module bound (); +endmodule + +module dut (); + genvar g_core; + generate + for (g_core = 0; g_core < 1; g_core++) begin : first_gen + fail_mod i_fail (); + end + endgenerate +endmodule + +module fail_mod (); + a i_a (); +endmodule + +module a (); + b i_b (); +endmodule +; + +module b (); + c i_c (); +endmodule + +module c (); + genvar gi; + generate + for (gi = 0; gi < 1; gi++) begin : second_gen + d i_d (); + end + endgenerate +endmodule + +module d (); + bound i_bound (); +endmodule