diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 19329eb4c..7ef30f56a 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -514,22 +514,31 @@ class TaskVisitor final : public VNVisitor { AstNodeExpr* postRhsp = new AstVarRef{newvscp->fileline(), newvscp, VAccess::READ}; if (AstResizeLValue* soutPinp = VN_CAST(outPinp, ResizeLValue)) { outPinp = soutPinp->lhsp(); - if (AstNodeUniop* aoutPinp = VN_CAST(outPinp, Extend)) { - outPinp = aoutPinp->lhsp(); - } else if (AstNodeUniop* aoutPinp = VN_CAST(outPinp, ExtendS)) { - outPinp = aoutPinp->lhsp(); - } else if (AstSel* aoutPinp = VN_CAST(outPinp, Sel)) { - outPinp = aoutPinp->fromp(); - } else { - outPinp->v3fatalSrc("Inout pin resizing should have had extend or select"); - } - if (outPinp->width() < portp->width()) { - postRhsp = new AstSel{pinp->fileline(), postRhsp, 0, pinp->width()}; - } else { // pin width > port width - if (pinp->isSigned() && postRhsp->isSigned()) { - postRhsp = new AstExtendS{pinp->fileline(), postRhsp}; + if (VN_IS(outPinp, RToIRoundS) || VN_IS(outPinp, RToIS)) { + outPinp = VN_AS(outPinp, NodeUniop)->lhsp(); + if (postRhsp->isSigned()) { + postRhsp = new AstISToRD{pinp->fileline(), postRhsp}; } else { - postRhsp = new AstExtend{pinp->fileline(), postRhsp}; + postRhsp = new AstIToRD{pinp->fileline(), postRhsp}; + } + } else { + if (AstNodeUniop* aoutPinp = VN_CAST(outPinp, Extend)) { + outPinp = aoutPinp->lhsp(); + } else if (AstNodeUniop* aoutPinp = VN_CAST(outPinp, ExtendS)) { + outPinp = aoutPinp->lhsp(); + } else if (AstSel* aoutPinp = VN_CAST(outPinp, Sel)) { + outPinp = aoutPinp->fromp(); + } else { + outPinp->v3fatalSrc("Inout pin resizing should have had extend or select"); + } + if (outPinp->width() < portp->width()) { + postRhsp = new AstSel{pinp->fileline(), postRhsp, 0, pinp->width()}; + } else { // pin width > port width + if (pinp->isSigned() && postRhsp->isSigned()) { + postRhsp = new AstExtendS{pinp->fileline(), postRhsp}; + } else { + postRhsp = new AstExtend{pinp->fileline(), postRhsp}; + } } } postRhsp->dtypeFrom(outPinp); diff --git a/test_regress/t/t_inout_pin_resizing.py b/test_regress/t/t_inout_pin_resizing.py new file mode 100755 index 000000000..8a938befd --- /dev/null +++ b/test_regress/t/t_inout_pin_resizing.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() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_inout_pin_resizing.v b/test_regress/t/t_inout_pin_resizing.v new file mode 100644 index 000000000..ff1a71ae6 --- /dev/null +++ b/test_regress/t/t_inout_pin_resizing.v @@ -0,0 +1,62 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Antmicro +// SPDX-License-Identifier: CC0-1.0 + +// verilog_format: off +`define stop $stop +`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); +`define checkr(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); +// verilog_format: on + +// verilator lint_off WIDTHTRUNC +// verilator lint_off REALCVT + +module t; + real src_r; + + bit unsigned [7:0] src_u2; + bit signed [7:0] src_s2; + real dst_r; + + task cp_u2(output bit unsigned [7:0] dst, input bit unsigned [7:0] src); + dst = src; + endtask + + task cp_s2(output bit signed [7:0] dst, input bit signed [7:0] src); + dst = src; + endtask + + task cp_io_u2(inout bit unsigned [7:0] io, input bit unsigned [7:0] src); + io = io + src; + endtask + + task cp_io_s2(inout bit signed [7:0] io, input bit signed [7:0] src); + io = io + src; + endtask + + initial begin + src_u2 = 7; + cp_u2(dst_r, src_u2); + `checkr(dst_r, 7.0); + + src_s2 = -7; + cp_s2(dst_r, src_s2); + `checkr(dst_r, -7.0); + + src_u2 = 7; + dst_r = 5.0; + cp_io_u2(dst_r, src_u2); + `checkr(dst_r, 12.0); + + src_s2 = -7; + dst_r = -3.0; + cp_io_s2(dst_r, src_s2); + `checkr(dst_r, -10.0); + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule