From 7bb8a4463f4602b50e17786e66f3cf2e8e2e0541 Mon Sep 17 00:00:00 2001 From: Cary R Date: Sat, 13 Feb 2021 01:10:38 -0800 Subject: [PATCH] Time literals need to be rounded using the time precision --- parse.y | 16 ++++++++++++---- pform.cc | 7 +++++++ pform.h | 1 + 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/parse.y b/parse.y index a350cc5b9..cab94a7fb 100644 --- a/parse.y +++ b/parse.y @@ -3195,7 +3195,7 @@ delay_value_simple : DEC_NUMBER { verinum*tmp = $1; if (tmp == 0) { - yyerror(@1, "internal error: delay."); + yyerror(@1, "internal error: decimal delay."); $$ = 0; } else { $$ = new PENumber(tmp); @@ -3206,7 +3206,7 @@ delay_value_simple | REALTIME { verireal*tmp = $1; if (tmp == 0) { - yyerror(@1, "internal error: delay."); + yyerror(@1, "internal error: real time delay."); $$ = 0; } else { $$ = new PEFNumber(tmp); @@ -3225,7 +3225,7 @@ delay_value_simple based_size = 0; $$ = 0; if ($1 == 0 || !get_time_unit($1, unit)) - yyerror(@1, "internal error: delay."); + yyerror(@1, "internal error: time literal delay."); else { double p = pow(10.0, (double)(unit - pform_get_timeunit())); @@ -3832,10 +3832,18 @@ expr_primary based_size = 0; $$ = 0; if ($1 == 0 || !get_time_unit($1, unit)) - yyerror(@1, "internal error: delay."); + yyerror(@1, "internal error: time literal."); else { double p = pow(10.0, (double)(unit - pform_get_timeunit())); double time = atof($1) * p; + // The time value needs to be rounded at the correct digit + // since this is a normal real value and not a delay that + // will be rounded later. This style of rounding is not safe + // for all real values! + int rdigit = pform_get_timeunit() - pform_get_timeprec(); + assert(rdigit >= 0); + double scale = pow(10.0, (double)rdigit); + time = round(time*scale)/scale; verireal *v = new verireal(time); $$ = new PEFNumber(v); diff --git a/pform.cc b/pform.cc index 30be384d7..b91f61165 100644 --- a/pform.cc +++ b/pform.cc @@ -1213,6 +1213,13 @@ int pform_get_timeunit() return scopex->time_unit; } +int pform_get_timeprec() +{ + PScopeExtra*scopex = find_nearest_scopex(lexical_scope); + assert(scopex); + return scopex->time_precision; +} + void pform_set_timeprec(const char*txt, bool initial_decl) { int val; diff --git a/pform.h b/pform.h index 98a00684c..f4a8c04ed 100644 --- a/pform.h +++ b/pform.h @@ -594,6 +594,7 @@ extern void parm_to_defparam_list(const string¶m); */ extern bool get_time_unit(const char*cp, int &unit); extern int pform_get_timeunit(); +extern int pform_get_timeprec(); extern void pform_set_timeunit(const char*txt, bool initial_decl); extern void pform_set_timeprec(const char*txt, bool initial_decl); /*