diff --git a/Changes b/Changes index aa9d7fc0e..eb0f0c933 100644 --- a/Changes +++ b/Changes @@ -25,6 +25,8 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Fix part select error when multipling by power-of-two (#2413). [Conor McCullough] +**** Fix division exception (#2460) [Kuoping Hsu] + * Verilator 4.036 2020-06-06 diff --git a/include/verilated.h b/include/verilated.h index 60fd02949..e1ccdb6e3 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -1571,12 +1571,16 @@ static inline WDataOutP VL_MULS_WWW(int, int lbits, int, WDataOutP owp, WDataInP static inline IData VL_DIVS_III(int lbits, IData lhs, IData rhs) VL_PURE { if (VL_UNLIKELY(rhs == 0)) return 0; + // -MAX / -1 cannot be represented in twos complement, and will cause SIGFPE + if (VL_UNLIKELY(lhs == 0x80000000 && rhs == 0xffffffff)) return 0; vlsint32_t lhs_signed = VL_EXTENDS_II(VL_IDATASIZE, lbits, lhs); vlsint32_t rhs_signed = VL_EXTENDS_II(VL_IDATASIZE, lbits, rhs); return lhs_signed / rhs_signed; } static inline QData VL_DIVS_QQQ(int lbits, QData lhs, QData rhs) VL_PURE { if (VL_UNLIKELY(rhs == 0)) return 0; + // -MAX / -1 cannot be represented in twos complement, and will cause SIGFPE + if (VL_UNLIKELY(lhs == 0x8000000000000000ULL && rhs == 0xffffffffffffffffULL)) return 0; vlsint64_t lhs_signed = VL_EXTENDS_QQ(VL_QUADSIZE, lbits, lhs); vlsint64_t rhs_signed = VL_EXTENDS_QQ(VL_QUADSIZE, lbits, rhs); return lhs_signed / rhs_signed; diff --git a/test_regress/t/t_math_div0.v b/test_regress/t/t_math_div0.v index 6cc635a9c..4da2cae21 100644 --- a/test_regress/t/t_math_div0.v +++ b/test_regress/t/t_math_div0.v @@ -3,13 +3,19 @@ // any use, without warranty, 2020 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 -module t(y); +module t(y, y2); output [3:0] y; + output [31:0] y2; // bug775 // verilator lint_off WIDTH assign y = ((0/0) ? 1 : 2) % 0; + // bug2460 + reg [31:0] b; + assign y2 = $signed(32'h80000000) / $signed(b); + initial begin + b = 32'hffffffff; $write("*-* All Finished *-*\n"); $finish; end