From 20c906261b176d1c149863dce1e4bb860eeca79b Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 9 Aug 2020 20:59:06 -0400 Subject: [PATCH] Fix casting non-self-determined subexpressions (#2493). --- Changes | 2 ++ src/V3Width.cpp | 9 +++++-- test_regress/t/t_math_shift_extend.pl | 19 ++++++++++++++ test_regress/t/t_math_shift_extend.v | 37 +++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 2 deletions(-) create mode 100755 test_regress/t/t_math_shift_extend.pl create mode 100644 test_regress/t/t_math_shift_extend.v diff --git a/Changes b/Changes index df1f9f472..5258e8914 100644 --- a/Changes +++ b/Changes @@ -12,6 +12,8 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Fix non-32 bit conversion to float (#2495). [dsvf] +**** Fix casting non-self-determined subexpressions (#2493). [phantom-killua] + * Verilator 4.038 2020-07-11 diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 9a256929d..6d4de0cde 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1531,7 +1531,8 @@ private: virtual void visit(AstCast* nodep) VL_OVERRIDE { nodep->dtypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); // if (debug()) nodep->dumpTree(cout, " CastPre: "); - userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); + userIterateAndNext(nodep->lhsp(), WidthVP(SELF, PRELIM).p()); + // When more general casts are supported, the cast elimination will be done later. // For now, replace it ASAP, so widthing can propagate easily // The cast may change signing, but we don't know the sign yet. Make it so. @@ -1544,7 +1545,11 @@ private: // Note widthCheckSized might modify nodep->lhsp() AstNodeDType* subDTypep = nodep->findLogicDType(nodep->width(), nodep->width(), nodep->lhsp()->dtypep()->numeric()); - widthCheckSized(nodep, "Cast", nodep->lhsp(), subDTypep, EXTEND_EXP, false); + iterateCheck(nodep, "value", nodep->lhsp(), CONTEXT, FINAL, subDTypep, EXTEND_EXP, + false); + } else { + iterateCheck(nodep, "value", nodep->lhsp(), SELF, FINAL, nodep->lhsp()->dtypep(), + EXTEND_EXP, false); } AstNode* newp = nodep->lhsp()->unlinkFrBack(); if (basicp->isDouble() && !newp->isDouble()) { diff --git a/test_regress/t/t_math_shift_extend.pl b/test_regress/t/t_math_shift_extend.pl new file mode 100755 index 000000000..763e64f5b --- /dev/null +++ b/test_regress/t/t_math_shift_extend.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 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(); + +ok(1); +1; diff --git a/test_regress/t/t_math_shift_extend.v b/test_regress/t/t_math_shift_extend.v new file mode 100644 index 000000000..b0f4707de --- /dev/null +++ b/test_regress/t/t_math_shift_extend.v @@ -0,0 +1,37 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + + logic in1 = 1; + logic [1:0] in2 = 2'b11; + logic [31:0] out; + + typedef logic [7:0] data_t; + + // verilator lint_off WIDTH + initial begin + in1 = 1; + in2 = 0; + out = data_t'(in1 << in2); + if (out != 8'b1) $stop; + + in2 = 1; + out = data_t'(in1 << in2); + if (out != 8'b10) $stop; + + in2 = 2; + out = data_t'(in1 << in2); + if (out != 8'b100) $stop; + + in2 = 3; + out = data_t'(in1 << in2); + if (out != 8'b1000) $stop; + + $write("*-* All Finished *-*\n"); + $finish(); + end +endmodule