From ca265966957d1028307e295ef1e3bd6dbba4773d Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 12 Jul 2017 20:08:32 -0400 Subject: [PATCH] Fix undefined VL_POW_WWI. --- Changes | 2 ++ include/verilated.cpp | 34 ++++++++++++++++++++++++++ include/verilated.h | 11 +++++++++ test_regress/t/t_math_pow6.pl | 18 ++++++++++++++ test_regress/t/t_math_pow6.v | 46 +++++++++++++++++++++++++++++++++++ 5 files changed, 111 insertions(+) create mode 100755 test_regress/t/t_math_pow6.pl create mode 100644 test_regress/t/t_math_pow6.v diff --git a/Changes b/Changes index bff8a28df..9e5352266 100644 --- a/Changes +++ b/Changes @@ -10,6 +10,8 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Fix compile error on unused VL_VALUEPLUSARGS_IW, bug1181. [Thomas J Whatson] +**** Fix undefined VL_POW_WWI. [Clifford Wolf] + * Verilator 3.906 2017-06-22 diff --git a/include/verilated.cpp b/include/verilated.cpp index 1a34b7117..997929c2a 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -283,6 +283,7 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo } WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp) { + // obits==lbits, rbits can be different owp[0] = 1; for (int i=1; i < VL_WORDS_I(obits); i++) owp[i] = 0; // cppcheck-suppress variableScope @@ -303,8 +304,24 @@ WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDa } return owp; } +WDataOutP VL_POW_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, QData rhs) { + WData rhsw[2]; VL_SET_WQ(rhsw, rhs); + return VL_POW_WWW(obits,lbits,rbits,owp,lwp,rhsw); +} +QData VL_POW_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp) { + // Skip check for rhs == 0, as short-circuit doesn't save time + if (VL_UNLIKELY(lhs==0)) return 0; + QData power = lhs; + QData out = VL_ULL(1); + for (int bit=0; bit0) power = power*power; + if (VL_BITISSET_W(rwp,bit)) out *= power; + } + return out; +} WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool lsign, bool rsign) { + // obits==lbits, rbits can be different if (rsign && VL_SIGN_W(rbits, rwp)) { int words = VL_WORDS_I(obits); VL_ZERO_W(obits, owp); @@ -323,6 +340,23 @@ WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, W } return VL_POW_WWW(obits, rbits, rbits, owp, lwp, rwp); } +WDataOutP VL_POWSS_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lwp, QData rhs, bool lsign, bool rsign) { + WData rhsw[2]; VL_SET_WQ(rhsw, rhs); + return VL_POWSS_WWW(obits,lbits,rbits,owp,lwp,rhsw,lsign,rsign); +} +QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsign, bool rsign) { + // Skip check for rhs == 0, as short-circuit doesn't save time + if (rsign && VL_SIGN_W(rbits, rwp)) { + if (lhs==0) return 0; // "X" + else if (lhs==1) return 1; + else if (lsign && lhs==VL_MASK_I(obits)) { // -1 + if (rwp[0] & 1) return VL_MASK_I(obits); // -1^odd=-1 + else return 1; // -1^even=1 + } + return 0; + } + return VL_POW_QQW(obits, rbits, rbits, lhs, rwp); +} //=========================================================================== // Formatting diff --git a/include/verilated.h b/include/verilated.h index c48e6153b..aae6f1ad8 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -1191,7 +1191,10 @@ static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDa } } +#define VL_POW_IIQ(obits,lbits,rbits,lhs,rhs) VL_POW_QQQ(obits,lbits,rbits,lhs,rhs) +#define VL_POW_IIW(obits,lbits,rbits,lhs,rwp) VL_POW_QQW(obits,lbits,rbits,lhs,rwp) #define VL_POW_QQI(obits,lbits,rbits,lhs,rhs) VL_POW_QQQ(obits,lbits,rbits,lhs,rhs) +#define VL_POW_WWI(obits,lbits,rbits,owp,lwp,rhs) VL_POW_WWQ(obits,lbits,rbits,owp,lwp,rhs) static inline IData VL_POW_III(int, int, int rbits, IData lhs, IData rhs) { if (VL_UNLIKELY(rhs==0)) return 1; @@ -1216,8 +1219,14 @@ static inline QData VL_POW_QQQ(int, int, int rbits, QData lhs, QData rhs) { return out; } WDataOutP VL_POW_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp); +WDataOutP VL_POW_WWQ(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, QData rhs); +QData VL_POW_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp); +#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) +#define VL_POWSS_IIQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) +#define VL_POWSS_IIW(obits,lbits,rbits,lhs,rwp,lsign,rsign) VL_POWSS_QQW(obits,lbits,rbits,lhs,rwp,lsign,rsign) #define VL_POWSS_QQI(obits,lbits,rbits,lhs,rhs,lsign,rsign) VL_POWSS_QQQ(obits,lbits,rbits,lhs,rhs,lsign,rsign) +#define VL_POWSS_WWI(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign) VL_POWSS_WWQ(obits,lbits,rbits,owp,lwp,rhs,lsign,rsign) static inline IData VL_POWSS_III(int obits, int, int rbits, IData lhs, IData rhs, bool lsign, bool rsign) { if (VL_UNLIKELY(rhs==0)) return 1; @@ -1246,6 +1255,8 @@ static inline QData VL_POWSS_QQQ(int obits, int, int rbits, QData lhs, QData rhs return VL_POW_QQQ(obits, rbits, rbits, lhs, rhs); } WDataOutP VL_POWSS_WWW(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool lsign, bool rsign); +WDataOutP VL_POWSS_WWQ(int obits, int, int rbits, WDataOutP owp, WDataInP lwp, QData rhs, bool lsign, bool rsign); +QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsign, bool rsign); //=================================================================== // Concat/replication diff --git a/test_regress/t/t_math_pow6.pl b/test_regress/t/t_math_pow6.pl new file mode 100755 index 000000000..f91289753 --- /dev/null +++ b/test_regress/t/t_math_pow6.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_pow6.v b/test_regress/t/t_math_pow6.v new file mode 100644 index 000000000..b3c88523e --- /dev/null +++ b/test_regress/t/t_math_pow6.v @@ -0,0 +1,46 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2017 by Wilson Snyder. + +module t (/*AUTOARG*/ + // Outputs + i65, j65, i33, j33, i30, j30, q65, r65, q33, r33, q30, r30, w65, x65, w33, + x33, w30, x30, + // Inputs + a, a40, a70 + ); + + input [3:0] a; + input [39:0] a40; + input [69:0] a70; + + // -- Verilator 621c515 creates code that uses the undeclared function VL_POW_WWI() + // verilator lint_off WIDTH + output [3:0] i65 = 65'd3 ** a; // WWI + output [3:0] j65 = a ** 65'd3; // IIW + output [3:0] i33 = 33'd3 ** a; // QQI + output [3:0] j33 = a ** 33'd3; // IIQ + output [3:0] i30 = 30'd3 ** a; // III + output [3:0] j30 = a ** 30'd3; // III + + output [39:0] q65 = 65'd3 ** a40; // WWQ + output [39:0] r65 = a40 ** 65'd3; // WWQ + output [39:0] q33 = 33'd3 ** a40; // QQQ + output [39:0] r33 = a40 ** 33'd3; // QQQ + output [39:0] q30 = 30'd3 ** a40; // QQI + output [39:0] r30 = a40 ** 30'd3; // QQI + + output [69:0] w65 = 65'd3 ** a70; // WWW + output [69:0] x65 = a70 ** 65'd3; // WWW + output [69:0] w33 = 33'd3 ** a70; // WWW + output [69:0] x33 = a70 ** 33'd3; // WWW + output [69:0] w30 = 30'd3 ** a70; // WWW + output [69:0] x30 = a70 ** 30'd3; // WWW + // verilator lint_on WIDTH + + initial begin + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule