diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 9434c7486..fefd746cf 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -2232,15 +2232,15 @@ private: AstNodeBiop* iterate_shift_final(AstNodeBiop* nodep, AstNUser* vup) { // Nodep maybe edited if (vup->c()->final()) { + AstNodeDType* expDTypep = vup->c()->dtypeOverridep(nodep->dtypep()); + AstNodeDType* subDTypep = expDTypep; + nodep->dtypeFrom(expDTypep); // ShiftRS converts to ShiftR, but not vice-versa if (nodep->castShiftRS()) { if (AstNodeBiop* newp=replaceWithUOrSVersion(nodep, nodep->isSigned())) { nodep=NULL; nodep = newp; // Process new node instead } } - AstNodeDType* expDTypep = vup->c()->dtypeOverridep(nodep->dtypep()); - AstNodeDType* subDTypep = expDTypep; - nodep->dtypeFrom(expDTypep); iterateCheck(nodep,"LHS",nodep->lhsp(),CONTEXT,FINAL,subDTypep,EXTEND_EXP); if (nodep->rhsp()->width()>32) { AstConst* shiftp = nodep->rhsp()->castConst(); diff --git a/test_regress/t/t_math_signed5.pl b/test_regress/t/t_math_signed5.pl new file mode 100755 index 000000000..f91289753 --- /dev/null +++ b/test_regress/t/t_math_signed5.pl @@ -0,0 +1,18 @@ +#!/usr/bin/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. + +compile ( + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_math_signed5.v b/test_regress/t/t_math_signed5.v new file mode 100644 index 000000000..9110f6671 --- /dev/null +++ b/test_regress/t/t_math_signed5.v @@ -0,0 +1,111 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2014 by Wilson Snyder. + +`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); fail='1; end while(0) +`define checkf(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); fail='1; end while(0) + + module t (/*AUTOARG*/); + + bit fail; + + reg signed [3:0] w4_s; + reg signed [4:0] w5_s; + reg [3:0] w4_u; + reg [4:0] w5_u; + real r; + + reg signed [4:0] bug754_a; + + integer i; + + //verilator lint_off WIDTH + wire a = (5'b0 == (5'sb11111 >>> 3'd7)); + wire b = (5'sb11111 == (5'sb11111 >>> 3'd7)); + wire c = (1'b0+(5'sb11111 >>> 3'd7)); + wire d = (1'sb0+(5'sb11111 >>> 3'd7)); + wire e = (5'b0 == (5'sb11111 / 5'sd3)); + wire f = (5'sb0 == (5'sb11111 / 5'sd3)); + wire g = (5'b01010 == (5'b11111 / 5'sd3)); + initial begin + // verilator lint_off STMTDLY + #1; +`ifdef VCS // I-2014.03 + `checkh({a, b, c, d, e, f, g}, 7'b1101111); +`else + `checkh({a, b, c, d, e, f, g}, 7'b1101011); +`endif + + //====================================================================== + + if ((-1 >>> 3) != -1) $stop; // Decimals are signed + + i = 3'sb111 >>> 3; + `checkh(i, -1); + i = -1 >>> 3; + `checkh(i, -1); + + bug754_a = -1; + w4_u = |0 != (bug754_a >>> 3'd7); + `checkh(w4_u, 4'b0); + + // Sanity check: -1>>7 == -1 + w5_u = (5'sb11111 >>> 3'd7); + `checkh(w5_u, 5'b11111); + + // bug756 + w4_u = (5'b0 == (5'sb11111 >>> 3'd7)); + `checkh(w4_u, 4'b0001); + w4_u = ((5'b0 == (5'sb11111 >>> 3'd7))); // Exp 0 Vlt 0 + `checkh(w4_u, 4'b0001); + w4_u = ((5'b01111 == (5'sb11111 / 5'sd2))); // Strength-reduces to >>> +`ifdef VCS // I-2014.03 + `checkh(w4_u, 4'b0000); // Wrong, gets 5'b0==..., unsigned does not propagate +`else + `checkh(w4_u, 4'b0001); // NC-Verilog, Modelsim, XSim, ... +`endif + + // Does == sign propagate from lhs to rhs? Yes, but not in VCS + w4_u = ((5'b01010 == (5'sb11111 / 5'sd3))); // Exp 0 Vlt 0 // Must be signed result (-1/3) to make this result zero +`ifdef VCS // I-2014.03 + `checkh(w4_u, 4'b0000); // Wrong, gets 5'b0==..., unsigned does not propagate +`else + `checkh(w4_u, 4'b0001); // NC-Verilog, Modelsim, XSim, ... +`endif + + w4_u = (1'b0+(5'sb11111 >>> 3'd7)); // Exp 00000 Vlt 000000 Actually the signedness of result does NOT matter + `checkh(w4_u, 4'b0000); + + w4_u = (5'sb0 == (5'sb11111 / 5'sd3)); // Must be signed result (-1/3) to make this result zero + `checkh(w4_u, 4'b0001); + // Does == width propagate from lhs to rhs? Yes + w4_u = (3'b100==(3'b111 << 2)); + `checkh(w4_u, 4'b0001); + w4_u = (4'b100==(3'b111 << 2)); + `checkh(w4_u, 4'b0000); + w4_u = (4'b1100==(3'b111 << 2)); + `checkh(w4_u, 4'b0001); + + // Does >>> sign propagate from input same as for +? Yes + w4_u = (1'b0+(5'sb11111 >>> 3'd7)); + `checkh(w4_u, 4'b0000); + w4_u = (1'sb0+(5'sb11111 >>> 3'd7)); + `checkh(w4_u, 4'b1111); + + // Does << width propagate from input same as for +? Yes + w4_u = (3'b0+(3'b111 << 2)); + `checkh(w4_u, 4'b1100); // width 4 =='s LHS + w4_u = (4'b0+(3'b111 << 2)); + `checkh(w4_u, 4'b1100); + + w4_u = (5'sb11111 == (5'sb11111 >>> 3'd7)); // WHAT? Signedness does propagate across ==????? + `checkh(w4_u, 4'b0001); + w4_u = ((5'b0 == (5'sb11111 >>> 3'd7))); + `checkh(w4_u, 4'b0001); + + if (fail) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule