Time literals need to be rounded using the time precision

This commit is contained in:
Cary R 2021-02-13 01:10:38 -08:00
parent 5530fbac9f
commit 7bb8a4463f
3 changed files with 20 additions and 4 deletions

16
parse.y
View File

@ -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);

View File

@ -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;

View File

@ -594,6 +594,7 @@ extern void parm_to_defparam_list(const string&param);
*/
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);
/*