diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 20ac29fea..d41eef7d7 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -516,30 +516,39 @@ public: } else { ifacerefp->v3fatalSrc("Unlinked interface"); } - } else if (ifacerefp->ifaceViaCellp()->dead()) { - if (varp->isIfaceRef()) { - if (forPrimary() && !varp->isIfaceParent() - && !v3Global.opt.topIfacesSupported()) { - // Only AstIfaceRefDType's at this point correspond to ports; - // haven't made additional ones for interconnect yet, so assert is simple - // What breaks later is we don't have a Scope/Cell representing - // the interface to attach to - varp->v3warn(E_UNSUPPORTED, - "Unsupported: Interfaced port on top level module"); - } - ifacerefp->v3error("Parent instance's interface is not found: " - << AstNode::prettyNameQ(ifacerefp->ifaceName()) << '\n' - << ifacerefp->warnMore() - << "... Perhaps intended an interface instantiation but " - "are missing parenthesis (IEEE 1800-2023 25.3)?"); - } else { - ifacerefp->v3warn( - E_UNSUPPORTED, - "Unsupported: virtual interface never assigned any actual interface"); - varp->dtypep(ifacerefp->findCHandleDType()); - VL_DO_DANGLING(ifacerefp->unlinkFrBack()->deleteTree(), ifacerefp); + } else if (ifacerefp->ifaceViaCellp()->dead() && varp->isIfaceRef()) { + if (forPrimary() && !varp->isIfaceParent() && !v3Global.opt.topIfacesSupported()) { + // Only AstIfaceRefDType's at this point correspond to ports; + // haven't made additional ones for interconnect yet, so assert is simple + // What breaks later is we don't have a Scope/Cell representing + // the interface to attach to + varp->v3warn(E_UNSUPPORTED, + "Unsupported: Interfaced port on top level module"); } + ifacerefp->v3error("Parent instance's interface is not found: " + << AstNode::prettyNameQ(ifacerefp->ifaceName()) << '\n' + << ifacerefp->warnMore() + << "... Perhaps intended an interface instantiation but " + "are missing parenthesis (IEEE 1800-2023 25.3)?"); continue; + } else if (ifacerefp->ifaceViaCellp()->dead() + || !existsNodeSym(ifacerefp->ifaceViaCellp())) { + // virtual interface never assigned any actual interface + ifacerefp->ifacep()->dead(false); + varp->dtypep(ifacerefp->dtypep()); + // Create dummy cell to keep the virtual interface alive + // (later stages assume that non-dead interface has associated cell) + AstCell* const ifacecellp + = new AstCell{ifacerefp->ifacep()->fileline(), + ifacerefp->ifacep()->fileline(), + ifacerefp->ifacep()->name() + "__02E" + varp->name(), + ifacerefp->ifaceName(), + nullptr, + nullptr, + nullptr}; + ifacecellp->modp(ifacerefp->ifacep()); + VSymEnt* const symp = new VSymEnt{&m_syms, ifacecellp}; + ifacerefp->ifacep()->user1p(symp); } VSymEnt* const ifaceSymp = getNodeSym(ifacerefp->ifaceViaCellp()); VSymEnt* ifOrPortSymp = ifaceSymp; @@ -2787,7 +2796,7 @@ class LinkDotResolveVisitor final : public VNVisitor { void visit(AstTypeTable*) override {} void visit(AstConstPool*) override {} void visit(AstNodeModule* nodep) override { - if (nodep->dead()) return; + if (nodep->dead() || !m_statep->existsNodeSym(nodep)) return; LINKDOT_VISIT_START(); UINFO(8, indent() << "visit " << nodep); checkNoDot(nodep); diff --git a/test_regress/t/t_interface_virtual_unused_bad.py b/test_regress/t/t_interface_virtual_unused.py similarity index 83% rename from test_regress/t/t_interface_virtual_unused_bad.py rename to test_regress/t/t_interface_virtual_unused.py index 31228c9a7..d4f986441 100755 --- a/test_regress/t/t_interface_virtual_unused_bad.py +++ b/test_regress/t/t_interface_virtual_unused.py @@ -9,8 +9,10 @@ import vltest_bootstrap -test.scenarios('linter') +test.scenarios('simulator') -test.lint(fails=True, expect_filename=test.golden_filename) +test.compile() + +test.execute() test.passes() diff --git a/test_regress/t/t_interface_virtual_unused_bad.v b/test_regress/t/t_interface_virtual_unused.v similarity index 100% rename from test_regress/t/t_interface_virtual_unused_bad.v rename to test_regress/t/t_interface_virtual_unused.v diff --git a/test_regress/t/t_interface_virtual_unused_bad.out b/test_regress/t/t_interface_virtual_unused_bad.out deleted file mode 100644 index 5775cfc79..000000000 --- a/test_regress/t/t_interface_virtual_unused_bad.out +++ /dev/null @@ -1,5 +0,0 @@ -%Error-UNSUPPORTED: t/t_interface_virtual_unused_bad.v:14:12: Unsupported: virtual interface never assigned any actual interface - 14 | virtual QBus q8; - | ^~~~ - ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest -%Error: Exiting due to