diff --git a/Changes b/Changes index 8bd8d4c19..69beabd23 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,8 @@ indicates the contributor was also the author of the fix; Thanks! * Verilator 3.82*** +*** Support $ceil, $floor, etc. [Alex Solomatnikov] + **** Fix MSVC compile warning with trunc/round, bug394. [Amir Gonnen] diff --git a/src/V3Ast.h b/src/V3Ast.h index 08841d4e4..d07fe7835 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -27,6 +27,7 @@ #include "V3Error.h" #include "V3Number.h" #include <vector> +#include <cmath> #include "V3Ast__gen_classes.h" // From ./astgen // Things like: @@ -825,6 +826,7 @@ public: static int instrCountPli() { return 20; } ///< Instruction cycles to call pli routines static int instrCountDouble() { return 8; } ///< Instruction cycles to convert or do floats static int instrCountDoubleDiv() { return 40; } ///< Instruction cycles to divide floats + static int instrCountDoubleTrig() { return 200; } ///< Instruction cycles to do triganomics static int instrCountCall() { return instrCountBranch()+10; } ///< Instruction cycles to call subroutine static int instrCountTime() { return instrCountCall()+5; } ///< Instruction cycles to determine simulation time diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index e9713bff4..cc36ea172 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -2832,6 +2832,90 @@ struct AstFGetC : public AstNodeUniop { AstNode* filep() const { return lhsp(); } }; +struct AstCeilD : public AstNodeUniop { + AstCeilD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { + numeric(AstNumeric::DOUBLE); } + ASTNODE_NODE_FUNCS(CeilD, CEILD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(ceil(lhs.toDouble())); } + virtual string emitVerilog() { return "%f$ceil(%l)"; } + virtual string emitC() { return "ceil(%li)"; } + virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;} + virtual bool sizeMattersLhs() {return false;} + virtual int instrCount() const { return instrCountDoubleTrig(); } + virtual bool doubleFlavor() const { return true; } +}; + +struct AstExpD : public AstNodeUniop { + AstExpD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { + numeric(AstNumeric::DOUBLE); } + ASTNODE_NODE_FUNCS(ExpD, EXPD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(exp(lhs.toDouble())); } + virtual string emitVerilog() { return "%f$exp(%l)"; } + virtual string emitC() { return "exp(%li)"; } + virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;} + virtual bool sizeMattersLhs() {return false;} + virtual int instrCount() const { return instrCountDoubleTrig(); } + virtual bool doubleFlavor() const { return true; } +}; + +struct AstFloorD : public AstNodeUniop { + AstFloorD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { + numeric(AstNumeric::DOUBLE); } + ASTNODE_NODE_FUNCS(FloorD, FLOORD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(floor(lhs.toDouble())); } + virtual string emitVerilog() { return "%f$floor(%l)"; } + virtual string emitC() { return "floor(%li)"; } + virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;} + virtual bool sizeMattersLhs() {return false;} + virtual int instrCount() const { return instrCountDoubleTrig(); } + virtual bool doubleFlavor() const { return true; } +}; + +struct AstLogD : public AstNodeUniop { + AstLogD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { + numeric(AstNumeric::DOUBLE); } + ASTNODE_NODE_FUNCS(LogD, LOGD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(log(lhs.toDouble())); } + virtual string emitVerilog() { return "%f$ln(%l)"; } + virtual string emitC() { return "log(%li)"; } + virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;} + virtual bool sizeMattersLhs() {return false;} + virtual int instrCount() const { return instrCountDoubleTrig(); } + virtual bool doubleFlavor() const { return true; } +}; + +struct AstLog10D : public AstNodeUniop { + AstLog10D(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { + numeric(AstNumeric::DOUBLE); } + ASTNODE_NODE_FUNCS(Log10D, LOG10D) + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(log10(lhs.toDouble())); } + virtual string emitVerilog() { return "%f$log10(%l)"; } + virtual string emitC() { return "log10(%li)"; } + virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;} + virtual bool sizeMattersLhs() {return false;} + virtual int instrCount() const { return instrCountDoubleTrig(); } + virtual bool doubleFlavor() const { return true; } +}; + +struct AstSqrtD : public AstNodeUniop { + AstSqrtD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { + numeric(AstNumeric::DOUBLE); } + ASTNODE_NODE_FUNCS(SqrtD, SQRTD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) { + out.setDouble(sqrt(lhs.toDouble())); } + virtual string emitVerilog() { return "%f$sqrt(%l)"; } + virtual string emitC() { return "sqrt(%li)"; } + virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;} + virtual bool sizeMattersLhs() {return false;} + virtual int instrCount() const { return instrCountDoubleTrig(); } + virtual bool doubleFlavor() const { return true; } +}; + //====================================================================== // Binary ops diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index e7c9181dc..d04e16943 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -546,7 +546,7 @@ public: } ofp()->printf(",0x%08" VL_PRI64 "x)", (vluint64_t)(nodep->num().dataWord(0))); } else if (nodep->isDouble()) { - ofp()->printf("%g", nodep->num().toDouble()); + ofp()->printf("%.17g", nodep->num().toDouble()); } else if (nodep->isQuad()) { vluint64_t num = nodep->toUQuad(); if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", num); diff --git a/src/V3Number.cpp b/src/V3Number.cpp index 653d2631a..67f7f5d97 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -25,6 +25,7 @@ #include <cstdio> #include <cstdarg> #include <algorithm> +#include <iomanip> #include "V3Number.h" #define MAX_SPRINTF_DOUBLE_SIZE 100 // Maximum characters with a sprintf %e/%f/%g (probably < 30) @@ -337,6 +338,7 @@ string V3Number::ascii(bool prefixed, bool cleanVerilog) const { ostringstream out; if (isDouble()) { + out.precision(17); out<<toDouble(); return out.str(); } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 53bd58bdb..8371d2051 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -208,6 +208,13 @@ private: virtual void visit(AstPowD* nodep, AstNUser* vup) { visit_math_Or_LRr(nodep,vup); } // Signed/Real: Output real or signed iff LHS signed/real virtual void visit(AstNegateD* nodep, AstNUser* vup) { visit_math_Or_Lr(nodep,vup); } + // Real: Output real + virtual void visit(AstCeilD* nodep, AstNUser* vup) { visit_math_Or_Lr(nodep,vup); } + virtual void visit(AstExpD* nodep, AstNUser* vup) { visit_math_Or_Lr(nodep,vup); } + virtual void visit(AstFloorD* nodep, AstNUser* vup) { visit_math_Or_Lr(nodep,vup); } + virtual void visit(AstLogD* nodep, AstNUser* vup) { visit_math_Or_Lr(nodep,vup); } + virtual void visit(AstLog10D* nodep, AstNUser* vup) { visit_math_Or_Lr(nodep,vup); } + virtual void visit(AstSqrtD* nodep, AstNUser* vup) { visit_math_Or_Lr(nodep,vup); } // Widths: out signed/unsigned width = lhs width, input un|signed virtual void visit(AstSigned* nodep, AstNUser* vup) { visit_Ous_Lus_Wforce(nodep,vup,AstNumeric::SIGNED); } @@ -1188,14 +1195,14 @@ private: nodep->taskp()->iterate(*this); // // And do the arguments to the task/function too - for (int accept_mode=1; accept_mode>=0; accept_mode--) { // Avoid duplicate code; just do inner stuff twice + for (int accept_mode=0; accept_mode<3; accept_mode++) { // Avoid duplicate code; just do inner stuff several times + reloop: V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp()); - bool lastloop = false; - for (V3TaskConnects::iterator it=tconnects.begin(); !lastloop && it!=tconnects.end(); ++it) { + for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) { AstVar* portp = it->first; AstNode* pinp = it->second; if (pinp!=NULL) { // Else argument error we'll find later - if (accept_mode) { + if (accept_mode==0) { // Prelim may cause the node to get replaced; we've lost our // pointer, so need to iterate separately later if (portp->attrSFormat() @@ -1214,7 +1221,7 @@ private: } handle.relink(newp); // Connection list is now incorrect (has extra args in it). - lastloop = true; // so exit early; next loop will correct it + goto reloop; // so exit early; next loop will correct it } else if (portp->basicp() && portp->basicp()->keyword()==AstBasicDTypeKwd::STRING && !pinp->castCvtPackString() @@ -1228,7 +1235,12 @@ private: pinp = newp; } pinp->accept(*this,WidthVP(portp->width(),portp->widthMin(),PRELIM).p()); pinp=NULL; - } else { + } else if (accept_mode==1) { + // Change data types based on above accept completion + if (portp->isDouble()) { + spliceCvtD(pinp); pinp=NULL; + } + } else if (accept_mode==2) { // Do PRELIM again, because above accept may have exited early due to node replacement pinp->accept(*this,WidthVP(portp->width(),portp->widthMin(),BOTH).p()); if ((portp->isOutput() || portp->isInout()) @@ -1585,20 +1597,18 @@ private: } void visit_math_Or_LRr(AstNodeBiop* nodep, AstNUser* vup) { if (vup->c()->prelim()) { // First stage evaluation + nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); + nodep->rhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); checkCvtD(nodep->lhsp()); checkCvtD(nodep->rhsp()); nodep->numeric(AstNumeric::DOUBLE); - // Determine expression widths only relying on what's in the subops - nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); - nodep->rhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); } } void visit_math_Or_Lr(AstNodeUniop* nodep, AstNUser* vup) { if (vup->c()->prelim()) { // First stage evaluation + nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); checkCvtD(nodep->lhsp()); nodep->numeric(AstNumeric::DOUBLE); - // Determine expression widths only relying on what's in the subops - nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p()); } } diff --git a/src/verilog.l b/src/verilog.l index 0df0d81a5..37bafd47e 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -175,7 +175,9 @@ word [a-zA-Z0-9_]+ "$c"[0-9]* { FL; return yD_C; } /*Verilator only*/ /* System Tasks */ "$bitstoreal" { FL; return yD_BITSTOREAL; } + "$ceil" { FL; return yD_CEIL; } "$display" { FL; return yD_DISPLAY; } + "$exp" { FL; return yD_EXP; } "$fclose" { FL; return yD_FCLOSE; } "$fdisplay" { FL; return yD_FDISPLAY; } "$feof" { FL; return yD_FEOF; } @@ -183,14 +185,18 @@ word [a-zA-Z0-9_]+ "$fgetc" { FL; return yD_FGETC; } "$fgets" { FL; return yD_FGETS; } "$finish" { FL; return yD_FINISH; } + "$floor" { FL; return yD_FLOOR; } "$fopen" { FL; return yD_FOPEN; } "$fscanf" { FL; return yD_FSCANF; } "$fullskew" { FL; return yaTIMINGSPEC; } "$fwrite" { FL; return yD_FWRITE; } "$hold" { FL; return yaTIMINGSPEC; } "$itor" { FL; return yD_ITOR; } + "$ln" { FL; return yD_LN; } + "$log10" { FL; return yD_LOG10; } "$nochange" { FL; return yaTIMINGSPEC; } "$period" { FL; return yaTIMINGSPEC; } + "$pow" { FL; return yD_POW; } "$random" { FL; return yD_RANDOM; } "$readmemb" { FL; return yD_READMEMB; } "$readmemh" { FL; return yD_READMEMH; } @@ -204,6 +210,7 @@ word [a-zA-Z0-9_]+ "$setuphold" { FL; return yaTIMINGSPEC; } "$sformat" { FL; return yD_SFORMAT; } "$skew" { FL; return yaTIMINGSPEC; } + "$sqrt" { FL; return yD_SQRT; } "$sscanf" { FL; return yD_SSCANF; } "$stime" { FL; return yD_STIME; } "$stop" { FL; return yD_STOP; } diff --git a/src/verilog.y b/src/verilog.y index 9e176bc1c..f314b811e 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -386,10 +386,12 @@ class AstSenTree; %token<fl> yD_BITS "$bits" %token<fl> yD_BITSTOREAL "$bitstoreal" %token<fl> yD_C "$c" +%token<fl> yD_CEIL "$ceil" %token<fl> yD_CLOG2 "$clog2" %token<fl> yD_COUNTONES "$countones" %token<fl> yD_DISPLAY "$display" %token<fl> yD_ERROR "$error" +%token<fl> yD_EXP "$exp" %token<fl> yD_FATAL "$fatal" %token<fl> yD_FCLOSE "$fclose" %token<fl> yD_FDISPLAY "$fdisplay" @@ -398,14 +400,18 @@ class AstSenTree; %token<fl> yD_FGETC "$fgetc" %token<fl> yD_FGETS "$fgets" %token<fl> yD_FINISH "$finish" +%token<fl> yD_FLOOR "$floor" %token<fl> yD_FOPEN "$fopen" %token<fl> yD_FSCANF "$fscanf" %token<fl> yD_FWRITE "$fwrite" %token<fl> yD_INFO "$info" %token<fl> yD_ISUNKNOWN "$isunknown" %token<fl> yD_ITOR "$itor" +%token<fl> yD_LN "$ln" +%token<fl> yD_LOG10 "$log10" %token<fl> yD_ONEHOT "$onehot" %token<fl> yD_ONEHOT0 "$onehot0" +%token<fl> yD_POW "$pow" %token<fl> yD_RANDOM "$random" %token<fl> yD_READMEMB "$readmemb" %token<fl> yD_READMEMH "$readmemh" @@ -414,6 +420,7 @@ class AstSenTree; %token<fl> yD_RTOI "$rtoi" %token<fl> yD_SFORMAT "$sformat" %token<fl> yD_SIGNED "$signed" +%token<fl> yD_SQRT "$sqrt" %token<fl> yD_SSCANF "$sscanf" %token<fl> yD_STIME "$stime" %token<fl> yD_STOP "$stop" @@ -2152,6 +2159,13 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func) | yaD_DPI parenE { $$ = new AstFuncRef($<fl>1,*$1,NULL); } | yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); } // + | yD_CEIL '(' expr ')' { $$ = new AstCeilD($1,$3); } + | yD_EXP '(' expr ')' { $$ = new AstExpD($1,$3); } + | yD_FLOOR '(' expr ')' { $$ = new AstFloorD($1,$3); } + | yD_LN '(' expr ')' { $$ = new AstLogD($1,$3); } + | yD_LOG10 '(' expr ')' { $$ = new AstLog10D($1,$3); } + | yD_POW '(' expr ',' expr ')' { $$ = new AstPowD($1,$3,$5); } + | yD_SQRT '(' expr ')' { $$ = new AstSqrtD($1,$3); } | yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); } | yD_BITS '(' data_type ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); } | yD_BITSTOREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); } diff --git a/test_regress/t/t_func_bad.pl b/test_regress/t/t_func_bad.pl index 866eb1b72..3444759bd 100755 --- a/test_regress/t/t_func_bad.pl +++ b/test_regress/t/t_func_bad.pl @@ -13,9 +13,11 @@ compile ( expect=> q{%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add' %Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add' +%Error: t/t_func_bad.v:\d+: Too few arguments in function call to FUNC 'add' %Error: t/t_func_bad.v:\d+: Too many arguments in function call to FUNC 'add' %Error: t/t_func_bad.v:\d+: Too few arguments in function call to TASK 'x' %Error: t/t_func_bad.v:\d+: Too few arguments in function call to TASK 'x' +%Error: t/t_func_bad.v:\d+: Too few arguments in function call to TASK 'x' %Error: Exiting due to}, ); diff --git a/test_regress/t/t_math_trig.pl b/test_regress/t/t_math_trig.pl new file mode 100755 index 000000000..7058e622f --- /dev/null +++ b/test_regress/t/t_math_trig.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_trig.v b/test_regress/t/t_math_trig.v new file mode 100644 index 000000000..3b2c549a6 --- /dev/null +++ b/test_regress/t/t_math_trig.v @@ -0,0 +1,155 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2011 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. + +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + real r, r2; + integer cyc=0; + + task check(integer line, real got, real ex); + if (got != ex) begin + if ((got - ex) > 0.000001) begin + $display("%%Error: Line %0d: Bad result, got=%0.99g expect=%0.99g",line,got,ex); + $stop; + end + end + endtask + + initial begin + // Check constant propagation + check(`__LINE__, $ceil(-1.2), -1); + check(`__LINE__, $ceil(1.2), 2); + check(`__LINE__, $exp(1.2), 3.3201169227365472380597566370852291584014892578125); + check(`__LINE__, $exp(0.0), 1); + check(`__LINE__, $exp(-1.2), 0.301194211912202136627314530414878390729427337646484375); + check(`__LINE__, $floor(-1.2), -2); + check(`__LINE__, $floor(1.2), 1); + check(`__LINE__, $ln(1.2), 0.1823215567939545922460098381634452380239963531494140625); + //check(`__LINE__, $ln(0), 0); // Bad value + //check(`__LINE__, $ln(-1.2), 0); // Bad value + check(`__LINE__, $log10(1.2), 0.07918124604762481755226843915806966833770275115966796875); + //check(`__LINE__, $log10(0), 0); // Bad value + //check(`__LINE__, $log10(-1.2), 0); + check(`__LINE__, $pow(2.3,1.2), 2.71689843249914897427288451581262052059173583984375); + check(`__LINE__, $pow(2.3,-1.2), 0.368066758785732861536388327294844202697277069091796875); + //check(`__LINE__, $pow(-2.3,1.2),0); // Bad value + check(`__LINE__, $sqrt(1.2), 1.095445115010332148841598609578795731067657470703125); + //check(`__LINE__, $sqrt(-1.2), 0); // Bad value +`ifndef VERILATOR + check(`__LINE__, $acos (0.2), 1.369438406); // Arg1 is -1..1 + check(`__LINE__, $acosh(1.2), 0.622362503); + check(`__LINE__, $asin (0.2), 0.201357920); // Arg1 is -1..1 + check(`__LINE__, $asinh(1.2), 1.015973134); + check(`__LINE__, $atan (0.2), 0.197395559); + check(`__LINE__, $atan2(0.2,2.3), 0.086738338); // Arg1 is -1..1 + check(`__LINE__, $atanh(0.2), 0.202732554); // Arg1 is -1..1 + check(`__LINE__, $cos (1.2), 0.362357754); + check(`__LINE__, $cosh (1.2), 1.810655567); + check(`__LINE__, $hypot(1.2,2.3), 2.594224354); + check(`__LINE__, $sin (1.2), 0.932039085); + check(`__LINE__, $sinh (1.2), 1.509461355); + check(`__LINE__, $tan (1.2), 2.572151622); + check(`__LINE__, $tanh (1.2), 0.833654607); +`endif + end + + real sum_ceil; + real sum_exp; + real sum_floor; + real sum_ln; + real sum_log10; + real sum_pow1; + real sum_pow2; + real sum_sqrt; + + real sum_acos; + real sum_acosh; + real sum_asin; + real sum_asinh; + real sum_atan; + real sum_atan2; + real sum_atanh; + real sum_cos ; + real sum_cosh; + real sum_hypot; + real sum_sin; + real sum_sinh; + real sum_tan; + real sum_tanh; + + // Test loop + always @ (posedge clk) begin + r = $itor(cyc)/10.0 - 5.0; // Crosses 0 +`ifdef TEST_VERBOSE + $write("[%0t] cyc==%0d r=%g s_ln=%0.12g\n",$time, cyc, r, sum_ln); +`endif + cyc <= cyc + 1; + if (cyc==0) begin + end + else if (cyc<90) begin + // Setup + sum_ceil += 1.0+$ceil(r); + sum_exp += 1.0+$exp(r); + sum_floor += 1.0+$floor(r); + if (r > 0.0) sum_ln += 1.0+$ln(r); + if (r > 0.0) sum_log10 += 1.0+$log10(r); + // Pow requires if arg1<0 then arg1 integral + sum_pow1 += 1.0+$pow(2.3,r); + if (r >= 0.0) sum_pow2 += 1.0+$pow(r,2.3); + if (r >= 0.0) sum_sqrt += 1.0+$sqrt(r); + +`ifndef VERILATOR + if (r>=-1.0 && r<=1.0) sum_acos += 1.0+$acos (r); + if (r>=1.0) sum_acosh += 1.0+$acosh(r); + if (r>=-1.0 && r<=1.0) sum_asin += 1.0+$asin (r); + sum_asinh += 1.0+$asinh(r); + sum_atan += 1.0+$atan (r); + if (r>=-1.0 && r<=1.0) sum_atan2 += 1.0+$atan2(r,2.3); + if (r>=-1.0 && r<=1.0) sum_atanh += 1.0+$atanh(r); + sum_cos += 1.0+$cos (r); + sum_cosh += 1.0+$cosh (r); + sum_hypot += 1.0+$hypot(r,2.3); + sum_sin += 1.0+$sin (r); + sum_sinh += 1.0+$sinh (r); + sum_tan += 1.0+$tan (r); + sum_tanh += 1.0+$tanh (r); +`endif + end + else if (cyc==99) begin + check (`__LINE__, sum_ceil, 85); + check (`__LINE__, sum_exp, 608.06652950); + check (`__LINE__, sum_floor, 4); + check (`__LINE__, sum_ln, 55.830941633); + check (`__LINE__, sum_log10, 46.309585076); + check (`__LINE__, sum_pow1, 410.98798177); + check (`__LINE__, sum_pow2, 321.94765689); + check (`__LINE__, sum_sqrt, 92.269677253); +`ifndef VERILATOR + check (`__LINE__, sum_acos, 53.986722862); + check (`__LINE__, sum_acosh, 72.685208498); + check (`__LINE__, sum_asin, 21); + check (`__LINE__, sum_asinh, 67.034973416); + check (`__LINE__, sum_atan, 75.511045389); + check (`__LINE__, sum_atan2, 21); + check (`__LINE__, sum_atanh, 0); + check (`__LINE__, sum_cos, 72.042023124); + check (`__LINE__, sum_cosh, 1054.0178222); + check (`__LINE__, sum_hypot, 388.92858406); + check (`__LINE__, sum_sin, 98.264184989); + check (`__LINE__, sum_sinh, 0); + check (`__LINE__, sum_tan, 1.7007946043); + check (`__LINE__, sum_tanh, 79.003199681); +`endif + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule