From 93c594e18a5d4d910f4922c2ac9ecf23f19d7673 Mon Sep 17 00:00:00 2001 From: Nikolai Kumar Date: Tue, 28 Apr 2026 14:25:37 -0500 Subject: [PATCH] Fix mailbox#(packed_struct) type mismatch with parameterized class (#7494) (#7495) --- docs/CONTRIBUTORS | 1 + src/V3AstNodeDType.h | 4 +- src/V3AstNodes.cpp | 15 +++++++ test_regress/t/t_mailbox_struct_param.py | 18 +++++++++ test_regress/t/t_mailbox_struct_param.v | 51 ++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 3 deletions(-) create mode 100755 test_regress/t/t_mailbox_struct_param.py create mode 100644 test_regress/t/t_mailbox_struct_param.v diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index 1dc86878e..f67c45ae2 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -200,6 +200,7 @@ Nathan Graybeal Nathan Kohagen Nathan Myers Nick Brereton +Nikolai Kumar Nikolay Puzanov Nolan Poe Oleh Maksymenko diff --git a/src/V3AstNodeDType.h b/src/V3AstNodeDType.h index 8265ffa8d..6b9b19bf6 100644 --- a/src/V3AstNodeDType.h +++ b/src/V3AstNodeDType.h @@ -275,9 +275,7 @@ public: int widthAlignBytes() const override; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... int widthTotalBytes() const override; - bool similarDTypeNode(const AstNodeDType* samep) const override { - return this == samep; // We don't compare members, require exact equivalence - } + bool similarDTypeNode(const AstNodeDType* samep) const override; string name() const override VL_MT_STABLE { return m_name; } void name(const string& flag) override { m_name = flag; } bool packed() const VL_MT_SAFE { return m_packed; } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 03696cb55..a5a4da2f5 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -2003,6 +2003,21 @@ bool AstClassRefDType::similarDTypeNode(const AstNodeDType* samep) const { } return !lp && !rp; } +bool AstNodeUOrStructDType::similarDTypeNode(const AstNodeDType* samep) const { + const AstNodeUOrStructDType* const sp = VN_DBG_AS(samep, NodeUOrStructDType); + if (m_packed != sp->m_packed) return false; + if (fileline()->tokenNum() != sp->fileline()->tokenNum()) return false; + const AstMemberDType* lp = membersp(); + const AstMemberDType* rp = sp->membersp(); + while (lp && rp) { + if (lp->name() != rp->name()) return false; + if (lp->width() != rp->width()) return false; + if (!lp->subDTypep()->similarDType(rp->subDTypep())) return false; + lp = VN_CAST(lp->nextp(), MemberDType); + rp = VN_CAST(rp->nextp(), MemberDType); + } + return !lp && !rp; +} void AstNodeCoverOrAssert::dump(std::ostream& str) const { this->AstNodeStmt::dump(str); str << " ["s + this->userType().ascii() + "]"; diff --git a/test_regress/t/t_mailbox_struct_param.py b/test_regress/t/t_mailbox_struct_param.py new file mode 100755 index 000000000..6fe7d000c --- /dev/null +++ b/test_regress/t/t_mailbox_struct_param.py @@ -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() diff --git a/test_regress/t/t_mailbox_struct_param.v b/test_regress/t/t_mailbox_struct_param.v new file mode 100644 index 000000000..3b0d09cc0 --- /dev/null +++ b/test_regress/t/t_mailbox_struct_param.v @@ -0,0 +1,51 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Nikolai Kumar +// SPDX-License-Identifier: CC0-1.0 + +package pkg; + class C #(parameter P = 0); + typedef struct packed { + bit [7:0] x; + } my_t; + + mailbox #(my_t) mb = new(); + + task run(output bit [7:0] got); + my_t v; + mb.get(v); + got = v.x; + endtask + endclass +endpackage + +module top; + import pkg::*; + + initial begin + C #(0) c0; + C #(1) c1; + C#(0)::my_t s0; + C#(1)::my_t s1; + bit [7:0] got0; + bit [7:0] got1; + + c0 = new(); + c1 = new(); + + s0.x = 8'hA5; + s1.x = 8'h5A; + c0.mb.put(s0); + c1.mb.put(s1); + + c0.run(got0); + c1.run(got1); + + if(got0 !== 8'hA5) $stop; + if(got0 !== 8'hA5) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule