From 800a789f5065cb580edf2ed36a8c23b8d732caf4 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 6 Oct 2023 21:33:31 -0400 Subject: [PATCH] Fix inlining of real functions miscasting (#4543). --- Changes | 1 + src/V3Cast.cpp | 8 ++++++-- src/V3Const.cpp | 2 +- test_regress/t/t_func_real_exprstmt.pl | 21 +++++++++++++++++++++ test_regress/t/t_func_real_exprstmt.v | 23 +++++++++++++++++++++++ 5 files changed, 52 insertions(+), 3 deletions(-) create mode 100755 test_regress/t/t_func_real_exprstmt.pl create mode 100644 test_regress/t/t_func_real_exprstmt.v diff --git a/Changes b/Changes index 2cf70f114..2b3e63fac 100644 --- a/Changes +++ b/Changes @@ -31,6 +31,7 @@ Verilator 5.017 devel * Fix stream operations with operands of struct type (#4531) (#4532). [Ryszard Rozak, Antmicro Ltd.] * Fix 'this' in a constructor (#4533). [Ryszard Rozak, Antmicro Ltd.] * Fix stream shift operator of 32 bits (#4536). [Julien Faucher] +* Fix inlining of real functions miscasting (#4543). [Andrew Nolte] Verilator 5.016 2023-09-16 diff --git a/src/V3Cast.cpp b/src/V3Cast.cpp index 7362f9c71..4fb3b868e 100644 --- a/src/V3Cast.cpp +++ b/src/V3Cast.cpp @@ -58,7 +58,7 @@ class CastVisitor final : public VNVisitor { private: // NODE STATE // Entire netlist: - // AstNode::user() // bool. Indicates node is of known size + // AstNode::user1() // bool. Indicates node is of known size const VNUser1InUse m_inuser1; // STATE @@ -66,12 +66,12 @@ private: // METHODS void insertCast(AstNodeExpr* nodep, int needsize) { // We'll insert ABOVE passed node - UINFO(4, " NeedCast " << nodep << endl); VNRelinker relinkHandle; nodep->unlinkFrBack(&relinkHandle); // AstCCast* const castp = new AstCCast{nodep->fileline(), nodep, needsize, nodep->widthMin()}; + UINFO(4, " MadeCast " << static_cast(castp) << " for " << nodep << endl); relinkHandle.relink(castp); // if (debug() > 8) castp->dumpTree("- castins: "); // @@ -170,6 +170,10 @@ private: ensureLower32Cast(nodep); nodep->user1(1); } + void visit(AstExprStmt* nodep) override { + iterateChildren(nodep); + nodep->user1(1); + } void visit(AstNegate* nodep) override { iterateChildren(nodep); nodep->user1(nodep->lhsp()->user1()); diff --git a/src/V3Const.cpp b/src/V3Const.cpp index ea0e4bea6..087f4b3af 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -1375,7 +1375,7 @@ private: AstNode* afterComment(AstNode* nodep) { // Ignore comments, such as to determine if a AstIf is empty. // nodep may be null, if so return null. - while (nodep && VN_IS(nodep, Comment)) { nodep = nodep->nextp(); } + while (nodep && VN_IS(nodep, Comment)) nodep = nodep->nextp(); return nodep; } diff --git a/test_regress/t/t_func_real_exprstmt.pl b/test_regress/t/t_func_real_exprstmt.pl new file mode 100755 index 000000000..859050d63 --- /dev/null +++ b/test_regress/t/t_func_real_exprstmt.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2023 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 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_func_real_exprstmt.v b/test_regress/t/t_func_real_exprstmt.v new file mode 100644 index 000000000..4df720960 --- /dev/null +++ b/test_regress/t/t_func_real_exprstmt.v @@ -0,0 +1,23 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder +// SPDX-License-Identifier: CC0-1.0 + +module t; + + function automatic real logWrapper(real x); + return $ln(x); + endfunction + + initial begin + // See bug4543 + $display("bad x=%f, y=%f", logWrapper(10.0), 1.0 * logWrapper(10.0)); + $display("noc x=%f, y=%f", $ln(10.0), 1.0 * $ln(10.0)); + if (logWrapper(10.0) != $ln(10.0)) $stop; + if (logWrapper(10.0) != 1.0 * logWrapper(10.0)) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule