From 94f8181cff52cd93b958a00418902cb1a457f0a0 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 19 Mar 2026 20:29:02 -0400 Subject: [PATCH] Fix null assignment to virtual interfaces (#5974) (#5990). [Maxim Fonarev] Fixes #5974. Co-authored-by: Maksim Fonarev --- Changes | 1 + docs/CONTRIBUTORS | 1 + include/verilated_types.h | 5 ++++- src/V3Width.cpp | 4 +++- test_regress/t/t_interface_virtual.v | 15 +++++++++++++-- 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Changes b/Changes index 44a0ca304..927c23232 100644 --- a/Changes +++ b/Changes @@ -46,6 +46,7 @@ Verilator 5.047 devel * Fix recursive default assignment for sub-arrays (#4589) (#7202). [Julian Carrier] * Fix shift width mismatch in constraint solver SMT emission (#5420) (#7265). [Yilou Wang] * Fix randomize size+element queue constraints (#5582) (#7225). [Rahul Behl, Testorrent USA, Inc.] +* Fix null assignment to virtual interfaces (#5974) (#5990). [Maxim Fonarev] * Fix lambda coroutines (#6106) (#7135). [Nick Brereton] * Fix super constructor calls with local variables (#6214) (#6933). [Igor Zaworski, Antmicro Ltd.] * Fix false recursive definition error (#6769) (#7118). [Alex Zhou] diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index d04f9760f..ef669d945 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -176,6 +176,7 @@ Mateusz Gancarz Matt Stroud Matthew Ballance Max Wipfli +Maxim Fonarev Michael Bedford Taylor Michael Bikovitsky Michael Killough diff --git a/include/verilated_types.h b/include/verilated_types.h index 90e2b9b78..c50cc044a 100644 --- a/include/verilated_types.h +++ b/include/verilated_types.h @@ -1931,7 +1931,10 @@ public: struct VlNull final { operator bool() const { return false; } - bool operator==(const void* ptr) const { return !ptr; } + template + operator T*() const { + return nullptr; + } }; inline bool operator==(const void* ptr, VlNull) { return !ptr; } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index ab54eb30e..606382e36 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -8676,7 +8676,9 @@ class WidthVisitor final : public VNVisitor { = VN_CAST(expDTypep->skipRefp(), IfaceRefDType)) { const AstIfaceRefDType* underIfaceRefp = VN_CAST(underp->dtypep()->skipRefp(), IfaceRefDType); - if (!underIfaceRefp) { + if (VN_IS(underp, Const) && VN_AS(underp, Const)->num().isNull()) { + // '= null' is ok + } else if (!underIfaceRefp) { underp->v3error(ucfirst(parentp->prettyOperatorName()) << " expected " << expIfaceRefp->ifaceViaCellp()->prettyNameQ() << " interface on " << side << " but " << underp->prettyNameQ() diff --git a/test_regress/t/t_interface_virtual.v b/test_regress/t/t_interface_virtual.v index 266465594..0bd84dc24 100644 --- a/test_regress/t/t_interface_virtual.v +++ b/test_regress/t/t_interface_virtual.v @@ -34,10 +34,21 @@ module t; Clsgen #(virtual PBus) gen; initial begin + if (va != null) $stop; + if (null != va) $stop; + va = null; + if (va != null) $stop; + if (null != va) $stop; va = ia; - vb = ia; - if (va == null) $stop; + if (null == va) $stop; + va = null; + if (va != null) $stop; + if (null != va) $stop; + va = ia; + if (va != ia) $stop; + + vb = ia; $display("va==vb? %b", va == vb); $display("va!=vb? %b", va != vb);