From 98cd925fda107fee312d049b0c4afb5d1d6f3618 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 6 Aug 2020 21:56:43 -0400 Subject: [PATCH] Fix non-32 bit conversion to float (#2495). --- Changes | 5 +- include/verilated.cpp | 25 ++++++ include/verilated.h | 25 +++++- src/V3AstNodes.h | 24 ++++- src/V3EmitC.cpp | 9 ++ src/V3Number.cpp | 15 +++- src/V3Number.h | 3 +- src/V3Width.cpp | 35 ++++++-- test_regress/t/t_math_real.v | 128 ++++++++++++++++++++++++++- test_regress/t/t_math_real_random.pl | 21 +++++ test_regress/t/t_math_real_random.v | 100 +++++++++++++++++++++ test_regress/t/t_math_wide_bad.out | 11 ++- test_regress/t/t_math_wide_bad.v | 4 +- test_regress/t/t_sys_file_basic.v | 2 +- test_regress/t/t_wire_types.v | 2 +- 15 files changed, 383 insertions(+), 26 deletions(-) create mode 100755 test_regress/t/t_math_real_random.pl create mode 100644 test_regress/t/t_math_real_random.v diff --git a/Changes b/Changes index 7f929b62d..df1f9f472 100644 --- a/Changes +++ b/Changes @@ -6,9 +6,12 @@ The contributors that suggested a given feature are shown in []. Thanks! *** Fix arrayed interfaces, broke in 4.038 (#2468). [Josh Redford] +**** Support $stable. [Peter Monsson] + **** Fix combining different-width parameters (#2484). [abirkmanis] -**** Support $stable. [Peter Monsson] +**** Fix non-32 bit conversion to float (#2495). [dsvf] + * Verilator 4.038 2020-07-11 diff --git a/include/verilated.cpp b/include/verilated.cpp index 72f3e97c9..459e51935 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -584,6 +584,31 @@ QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsig return VL_POW_QQW(obits, rbits, rbits, lhs, rwp); } +double VL_ITOR_D_W(int lbits, WDataInP lwp) VL_PURE { + int ms_word = VL_WORDS_I(lbits) - 1; + for (; !lwp[ms_word] && ms_word > 0;) --ms_word; + if (ms_word == 0) return static_cast(lwp[0]); + if (ms_word == 1) return static_cast(VL_SET_QW(lwp)); + // We need 53 bits of mantissa, which might mean looking at 3 words + // namely ms_word, ms_word-1 and ms_word-2 + EData ihi = lwp[ms_word]; + EData imid = lwp[ms_word - 1]; + EData ilo = lwp[ms_word - 2]; + double hi = static_cast(ihi) * exp2(2 * VL_EDATASIZE); + double mid = static_cast(imid) * exp2(VL_EDATASIZE); + double lo = static_cast(ilo); + double d = (hi + mid + lo) * exp2(VL_EDATASIZE * (ms_word - 2)); + return d; +} +double VL_ISTOR_D_W(int lbits, WDataInP lwp) VL_PURE { + if (!VL_SIGN_W(lbits, lwp)) return VL_ITOR_D_W(lbits, lwp); + vluint32_t pos[VL_MULS_MAX_WORDS + 1]; // Fixed size, as MSVC++ doesn't allow [words] here + VL_NEGATE_W(VL_WORDS_I(lbits), pos, lwp); + _VL_CLEAN_INPLACE_W(lbits, pos); + double d = VL_ITOR_D_W(lbits, pos); + return -VL_ITOR_D_W(lbits, pos); +} + //=========================================================================== // Formatting diff --git a/include/verilated.h b/include/verilated.h index 29569ba5e..099066ab7 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -764,9 +764,27 @@ static inline QData VL_CVT_Q_D(double lhs) VL_PURE { } // clang-format on -/// Return double from QData (numeric) -static inline double VL_ITOR_D_I(IData lhs) VL_PURE { - return static_cast(static_cast(lhs)); +/// Return double from lhs (numeric) unsigned +double VL_ITOR_D_W(int lbits, WDataInP lwp) VL_PURE; +static inline double VL_ITOR_D_I(int, IData lhs) VL_PURE { + return static_cast(static_cast(lhs)); +} +static inline double VL_ITOR_D_Q(int, QData lhs) VL_PURE { + return static_cast(static_cast(lhs)); +} +/// Return double from lhs (numeric) signed +double VL_ISTOR_D_W(int lbits, WDataInP lwp) VL_PURE; +static inline double VL_ISTOR_D_I(int lbits, IData lhs) VL_PURE { + if (lbits == 32) return static_cast(static_cast(lhs)); + WData lwp[VL_WQ_WORDS_E]; + VL_SET_WI(lwp, lhs); + return VL_ISTOR_D_W(lbits, lwp); +} +static inline double VL_ISTOR_D_Q(int lbits, QData lhs) VL_PURE { + if (lbits == 64) return static_cast(static_cast(lhs)); + WData lwp[VL_WQ_WORDS_E]; + VL_SET_WQ(lwp, lhs); + return VL_ISTOR_D_W(lbits, lwp); } /// Return QData from double (numeric) static inline IData VL_RTOI_I_D(double lhs) VL_PURE { @@ -1453,6 +1471,7 @@ static inline int _VL_CMPS_W(int lbits, WDataInP lwp, WDataInP rwp) VL_MT_SAFE { //========================================================================= // Math +// Output NOT clean static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp, WDataInP lwp) VL_MT_SAFE { EData carry = 1; for (int i = 0; i < words; ++i) { diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 661941ecf..cc4087f93 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -5523,6 +5523,7 @@ public: virtual int instrCount() const { return instrCountDouble(); } }; class AstIToRD : public AstNodeUniop { + // $itor where lhs is unsigned public: AstIToRD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) { @@ -5531,10 +5532,27 @@ public: ASTNODE_NODE_FUNCS(IToRD) virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opIToRD(lhs); } virtual string emitVerilog() { return "%f$itor(%l)"; } - virtual string emitC() { return "VL_ITOR_D_I(%li)"; } + virtual string emitC() { return "VL_ITOR_D_%lq(%lw, %li)"; } virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } // Eliminated before matters - virtual bool sizeMattersLhs() const { return false; } // Eliminated before matters + virtual bool cleanLhs() const { return true; } + virtual bool sizeMattersLhs() const { return false; } + virtual int instrCount() const { return instrCountDouble(); } +}; +class AstISToRD : public AstNodeUniop { + // $itor where lhs is signed +public: + AstISToRD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER(fl, lhsp) { + dtypeSetDouble(); + } + ASTNODE_NODE_FUNCS(ISToRD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opISToRD(lhs); } + virtual string emitVerilog() { return "%f$itor($signed(%l))"; } + virtual string emitC() { return "VL_ISTOR_D_%lq(%lw, %li)"; } + virtual bool emitCheckMaxWords() { return true; } + virtual bool cleanOut() const { return false; } + virtual bool cleanLhs() const { return true; } + virtual bool sizeMattersLhs() const { return false; } virtual int instrCount() const { return instrCountDouble(); } }; class AstRealToBits : public AstNodeUniop { diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 2c78bead9..690b65177 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -877,6 +877,15 @@ public: emitOpName(nodep, nodep->emitC(), NULL, NULL, NULL); } virtual void visit(AstNodeUniop* nodep) VL_OVERRIDE { + if (nodep->emitCheckMaxWords() + && (nodep->widthWords() > VL_MULS_MAX_WORDS + || nodep->lhsp()->widthWords() > VL_MULS_MAX_WORDS)) { + nodep->v3warn( + E_UNSUPPORTED, + "Unsupported: " + << nodep->prettyOperatorName() << " operator of " << nodep->width() + << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); + } if (emitSimpleOk(nodep)) { putbs("("); puts(nodep->emitSimpleOperator()); diff --git a/src/V3Number.cpp b/src/V3Number.cpp index e7b19e4e5..d684b9ed5 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -2232,13 +2232,24 @@ V3Number& V3Number::opSelInto(const V3Number& lhs, int lsbval, int width) { //====================================================================== // Ops - Floating point -V3Number& V3Number::opIToRD(const V3Number& lhs) { +V3Number& V3Number::opIToRD(const V3Number& lhs, bool isSigned) { NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_LOGIC_ARGS1(lhs); // IEEE says we ignore x/z in real conversions V3Number noxz(lhs); noxz.opAssignNonXZ(lhs); - return setDouble(noxz.toSInt()); + double d = 0; + bool negate = isSigned && noxz.isNegative(); + if (negate) { + V3Number noxz_signed = noxz; + noxz.opNegate(noxz_signed); + } + for (int bit = noxz.width() - 1; bit >= 0; bit--) { + // Some precision might be lost in this add, that's what we want + if (noxz.bitIs1(bit)) d += exp2(bit); + } + if (negate) d = -d; + return setDouble(d); } V3Number& V3Number::opRToIS(const V3Number& lhs) { NUM_ASSERT_OP_ARGS1(lhs); diff --git a/src/V3Number.h b/src/V3Number.h index 9245b2dfd..1426cfd6e 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -385,7 +385,8 @@ public: V3Number& opLteS(const V3Number& lhs, const V3Number& rhs); // Signed // "D" - double (aka real) math - V3Number& opIToRD(const V3Number& lhs); + V3Number& opIToRD(const V3Number& lhs, bool isSigned = false); + V3Number& opISToRD(const V3Number& lhs) { return opIToRD(lhs, true); } V3Number& opRToIS(const V3Number& lhs); V3Number& opRToIRoundS(const V3Number& lhs); V3Number& opRealToBits(const V3Number& lhs); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 90c358710..9a256929d 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -332,7 +332,6 @@ private: //======== // Widths: Output real, input integer signed virtual void visit(AstBitsToRealD* nodep) VL_OVERRIDE { visit_Or_Lu64(nodep); } - virtual void visit(AstIToRD* nodep) VL_OVERRIDE { visit_Or_Ls32(nodep); } // Widths: Output integer signed, input real virtual void visit(AstRToIS* nodep) VL_OVERRIDE { visit_Os32_Lr(nodep); } @@ -1549,7 +1548,11 @@ private: } AstNode* newp = nodep->lhsp()->unlinkFrBack(); if (basicp->isDouble() && !newp->isDouble()) { - newp = new AstIToRD(nodep->fileline(), newp); + if (newp->isSigned()) { + newp = new AstISToRD(nodep->fileline(), newp); + } else { + newp = new AstIToRD(nodep->fileline(), newp); + } } else if (!basicp->isDouble() && newp->isDouble()) { if (basicp->isSigned()) { newp = new AstRToIRoundS(nodep->fileline(), newp); @@ -3931,16 +3934,27 @@ private: iterateCheck(nodep, "LHS", nodep->lhsp(), SELF, FINAL, subDTypep, EXTEND_EXP); } } - void visit_Or_Ls32(AstNodeUniop* nodep) { - // CALLER: AstIToRD + virtual void visit(AstIToRD* nodep) VL_OVERRIDE { // Real: Output real // LHS presumed self-determined, then coerced to real if (m_vup->prelim()) { // First stage evaluation nodep->dtypeSetDouble(); - AstNodeDType* subDTypep = nodep->findLogicDType(32, 32, VSigning::SIGNED); - // Self-determined operand + // Self-determined operand (TODO check if numeric type) + userIterateAndNext(nodep->lhsp(), WidthVP(SELF, PRELIM).p()); + if (nodep->lhsp()->isSigned()) { + nodep->replaceWith( + new AstISToRD(nodep->fileline(), nodep->lhsp()->unlinkFrBack())); + VL_DO_DANGLING(nodep->deleteTree(), nodep); + } + } + } + virtual void visit(AstISToRD* nodep) VL_OVERRIDE { + // Real: Output real + // LHS presumed self-determined, then coerced to real + if (m_vup->prelim()) { // First stage evaluation + nodep->dtypeSetDouble(); + // Self-determined operand (TODO check if numeric type) userIterateAndNext(nodep->lhsp(), WidthVP(SELF, PRELIM).p()); - iterateCheck(nodep, "LHS", nodep->lhsp(), SELF, FINAL, subDTypep, EXTEND_EXP); } } void visit_Os32_Lr(AstNodeUniop* nodep) { @@ -4800,7 +4814,12 @@ private: UINFO(6, " spliceCvtD: " << nodep << endl); AstNRelinker linker; nodep->unlinkFrBack(&linker); - AstNode* newp = new AstIToRD(nodep->fileline(), nodep); + AstNode* newp; + if (nodep->dtypep()->skipRefp()->isSigned()) { + newp = new AstISToRD(nodep->fileline(), nodep); + } else { + newp = new AstIToRD(nodep->fileline(), nodep); + } linker.relink(newp); return newp; } else { diff --git a/test_regress/t/t_math_real.v b/test_regress/t/t_math_real.v index 167bd9fbf..dc94b5aa3 100644 --- a/test_regress/t/t_math_real.v +++ b/test_regress/t/t_math_real.v @@ -6,6 +6,7 @@ // Version 2.0. // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.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); `define is_near_real(a,b) (( ((a)<(b)) ? (b)-(a) : (a)-(b)) < (((a)/(b))*0.0001)) module t (/*AUTOARG*/ @@ -16,6 +17,16 @@ module t (/*AUTOARG*/ integer i; reg [63:0] b; + reg [47:0] i48; + reg signed [47:0] is48; + reg [31:0] ci32; + reg signed [31:0] cis32; + reg [47:0] ci48; + reg signed [47:0] cis48; + reg [63:0] ci64; + reg signed [63:0] cis64; + reg [95:0] ci96; + reg signed [95:0] cis96; real r, r2; integer cyc=0; @@ -88,6 +99,41 @@ module t (/*AUTOARG*/ // bug b = 64'h7fe8000000000000; $display("%6.3f", $bitstoreal(b)); + // bug + i48 = 48'hff00_00000000; + r = real'(i48); + if (r != 280375465082880.0) $stop; + r = $itor(i48); + if (r != 280375465082880.0) $stop; + + is48 = 48'shff00_00000000; + r = real'(is48); + if (r != -1099511627776.0) $stop; + r = $itor(is48); + if (r != -1099511627776.0) $stop; + + r = 0; + r = i48; + if (r != 280375465082880.0) $stop; + r = 0; + + r = $itor(-10); + if (r != -10.0) $stop; + + r = real'(4'sb1111); + if (r != -1) $stop; + r = $itor(4'sb1111); + if (r != -1) $stop; + + r = real'(4'b1111); + if (r != 15) $stop; + r = $itor(4'b1111); + if (r != 15) $stop; + + r = real'(96'hf0000000_00000000_00000000); + if (r != 74276402357122816493947453440.0) $stop; + r = real'(96'shf0000000_00000000_00000000); + if (r != -4951760157141521099596496896.0) $stop; end // Test loop @@ -98,8 +144,18 @@ module t (/*AUTOARG*/ cyc <= cyc + 1; if (cyc==0) begin // Setup + ci48 <= '0; + cis48 <= '0; + ci96 <= '0; + cis96 <= '0; end - else if (cyc<90) begin + else if (cyc == 1) begin + ci48 <= 48'hff00_00000000; + cis48 <= 48'shff00_00000000; + ci96 <= 96'hf0000000_00000000_00000000; + cis96 <= 96'shf0000000_00000000_00000000; + end + else if (cyc<80) begin if ($time != {32'h0, $rtoi($realtime)}) $stop; if ($itor(cyc) != cyc) $stop; //Unsup: if ((real `($time)) != $realtime) $stop; @@ -141,6 +197,76 @@ module t (/*AUTOARG*/ != (((cyc-50)!=0) ? 10 : 20)) $stop; // if ((!(r-50.0)) != (!((cyc-50) != 0))) $stop; + // + r = real'(ci48); + `checkr(r, 280375465082880.0); + r = real'(cis48); + `checkr(r, -1099511627776.0); + // + r = real'(ci96); + `checkr(r, 74276402357122816493947453440.0); + r = real'(cis96); + `checkr(r, -4951760157141521099596496896.0); + end + else if (cyc==90) begin + ci32 <= '0; + cis32 <= '0; + ci48 <= '0; + cis48 <= '0; + ci64 <= '0; + cis64 <= '0; + ci96 <= '0; + cis96 <= '0; + end + else if (cyc==91) begin + `checkr(real'(ci32), 0.0); + `checkr(real'(cis32), 0.0); + `checkr(real'(ci48), 0.0); + `checkr(real'(cis48), 0.0); + `checkr(real'(ci64), 0.0); + `checkr(real'(cis64), 0.0); + `checkr(real'(ci96), 0.0); + `checkr(real'(cis96), 0.0); + end + else if (cyc==92) begin + ci32 <= 32'b1; + cis32 <= 32'b1; + ci48 <= 48'b1; + cis48 <= 48'b1; + ci64 <= 64'b1; + cis64 <= 64'b1; + ci96 <= 96'b1; + cis96 <= 96'b1; + end + else if (cyc==93) begin + `checkr(real'(ci32), 1.0); + `checkr(real'(cis32), 1.0); + `checkr(real'(ci48), 1.0); + `checkr(real'(cis48), 1.0); + `checkr(real'(ci64), 1.0); + `checkr(real'(cis64), 1.0); + `checkr(real'(ci96), 1.0); + `checkr(real'(cis96), 1.0); + end + else if (cyc==94) begin + ci32 <= ~ '0; + cis32 <= ~ '0; + ci48 <= ~ '0; + cis48 <= ~ '0; + ci64 <= ~ '0; + cis64 <= ~ '0; + ci96 <= ~ '0; + cis96 <= ~ '0; + end + else if (cyc==95) begin + `checkr(real'(ci32), 4294967295.0); + `checkr(real'(cis32), -1.0); + `checkr(real'(ci48), 281474976710655.0); + `checkr(real'(cis48), -1.0); + `checkr(real'(ci64), 18446744073709551616.0); + `checkr(real'(cis64), -1.0); + `checkr(real'(ci96), 79228162514264337593543950336.0); + `checkr(real'(cis96), -1.0); end else if (cyc==99) begin $write("*-* All Finished *-*\n"); diff --git a/test_regress/t/t_math_real_random.pl b/test_regress/t/t_math_real_random.pl new file mode 100755 index 000000000..9a15dd2cc --- /dev/null +++ b/test_regress/t/t_math_real_random.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 2019 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_math_real_random.v b/test_regress/t/t_math_real_random.v new file mode 100644 index 000000000..02c86774f --- /dev/null +++ b/test_regress/t/t_math_real_random.v @@ -0,0 +1,100 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 Wilson Snyder. +// SPDX-License-Identifier: CC0-1.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); + +module t(/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + integer cyc=0; + reg [63:0] crc; + reg [63:0] sum; + + reg [127:0] in; + + check #(48) check48 (.*); + check #(31) check31 (.*); + check #(32) check32 (.*); + check #(63) check63 (.*); + check #(64) check64 (.*); + check #(96) check96 (.*); + check #(128) check128 (.*); + + always_comb begin + if (crc[2:0] == 0) in = '0; + else if (crc[2:0] == 1) in = ~'0; + else if (crc[2:0] == 2) in = 128'b1; + else if (crc[2:0] == 3) in = ~ 128'b1; + else begin + in = {crc, crc}; + if (crc[3]) in[31:0] = '0; + if (crc[4]) in[63:32] = '0; + if (crc[5]) in[95:64] = '0; + if (crc[6]) in[127:96] = '0; + if (crc[7]) in[31:0] = ~'0; + if (crc[8]) in[63:32] = ~'0; + if (crc[9]) in[95:64] = ~'0; + if (crc[10]) in[127:96] = ~'0; + end + end + + // Test loop + always @ (posedge clk) begin +`ifdef TEST_VERBOSE + $write("[%0t] cyc==%0d in=%x\n",$time, cyc, in); +`endif + cyc <= cyc + 1; + crc <= {crc[62:0], crc[63]^crc[2]^crc[0]}; + if (cyc == 0) begin + // Setup + crc <= 64'h5aef0c8d_d70a4497; + sum <= '0; + end + else if (cyc == 99) begin + `checkr(check48.sum, 14574057015683440.000000); + `checkr(check31.sum, 114141374814.000000); + `checkr(check32.sum, 236547942750.000000); + `checkr(check63.sum, 513694866079917670400.000000); + `checkr(check64.sum, 1002533584033221181440.000000); + `checkr(check96.sum, 4377373669974269260279175970816.000000); + `checkr(check128.sum, 18358899571808044815012294240949812330496.000000); + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule + +module check(/*AUTOARG*/ + // Inputs + in, clk, cyc + ); + parameter WIDTH = 128; + input [127:0] in; + + wire [WIDTH-1:0] ci = in[WIDTH-1:0]; + wire signed [WIDTH-1:0] cis = in[WIDTH-1:0]; + + real r; + real rs; + always_comb r = ci; + always_comb rs = cis; + + input clk; + input integer cyc; + real sum; + + always_ff @ (negedge clk) begin +`ifdef TEST_VERBOSE + $write("[%0t] w%0d in=%h r=%f rs=%f sum=%f\n", $time, WIDTH, ci, r, rs, sum); +`endif + if (cyc < 10) sum <= 0; + else sum <= sum + r + rs; + end +endmodule diff --git a/test_regress/t/t_math_wide_bad.out b/test_regress/t/t_math_wide_bad.out index 12170466c..1c4516c1d 100644 --- a/test_regress/t/t_math_wide_bad.out +++ b/test_regress/t/t_math_wide_bad.out @@ -1,7 +1,10 @@ -%Error-UNSUPPORTED: t/t_math_wide_bad.v:21:18: Unsupported: operator POWSS operator of 576 bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h - 21 | assign z2 = a ** 3; +%Error-UNSUPPORTED: t/t_math_wide_bad.v:22:18: Unsupported: operator POWSS operator of 576 bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h + 22 | assign z2 = a ** 3; | ^~ -%Error-UNSUPPORTED: t/t_math_wide_bad.v:20:17: Unsupported: operator MULS operator of 576 bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h - 20 | assign z = a * b; +%Error-UNSUPPORTED: t/t_math_wide_bad.v:23:15: Unsupported: operator ISTORD operator of 64 bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h + 23 | assign r = real'(a); + | ^~~~ +%Error-UNSUPPORTED: t/t_math_wide_bad.v:21:17: Unsupported: operator MULS operator of 576 bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h + 21 | assign z = a * b; | ^ %Error: Exiting due to diff --git a/test_regress/t/t_math_wide_bad.v b/test_regress/t/t_math_wide_bad.v index 222faca7f..8864a0bfc 100644 --- a/test_regress/t/t_math_wide_bad.v +++ b/test_regress/t/t_math_wide_bad.v @@ -6,7 +6,7 @@ module t (/*AUTOARG*/ // Outputs - z, z2, + z, z2, r, // Inputs a, b ); @@ -16,8 +16,10 @@ module t (/*AUTOARG*/ output signed [17*32 : 0] z; output signed [17*32 : 0] z2; + output real r; assign z = a * b; assign z2 = a ** 3; + assign r = real'(a); endmodule diff --git a/test_regress/t/t_sys_file_basic.v b/test_regress/t/t_sys_file_basic.v index 272574d0d..9497d3a2a 100644 --- a/test_regress/t/t_sys_file_basic.v +++ b/test_regress/t/t_sys_file_basic.v @@ -8,7 +8,7 @@ `define STRINGIFY(x) `"x`" `define ratio_error(a,b) (((a)>(b) ? ((a)-(b)) : ((b)-(a))) /(a)) -`define checkr(gotv,expv) do if (`ratio_error((gotv),(expv))>0.0001) begin $write("%%Error: %s:%0d: got=%g exp=%g\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0); +`define checkr(gotv,expv) do if (`ratio_error((gotv),(expv))>0.0001) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0); `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 checks(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0); diff --git a/test_regress/t/t_wire_types.v b/test_regress/t/t_wire_types.v index 11952324a..fb67e7a7b 100644 --- a/test_regress/t/t_wire_types.v +++ b/test_regress/t/t_wire_types.v @@ -11,7 +11,7 @@ module t (/*AUTOARG*/ input clk; `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=%g exp=%g\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); // IEEE: integer_atom_type wire byte w_byte;