Fix time issue in FreeBSD (pow() bug)

This commit is contained in:
Cary R 2023-12-09 12:49:25 -08:00
parent 58dcf39db3
commit 5d561f3ef1
3 changed files with 65 additions and 3 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2021 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2023 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -1189,7 +1189,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
cerr << get_fileline() << ": debug: Create signal " << wtype;
if (set_data_type_)
cout << " " << *set_data_type_;
cout << name_ << unpacked_dimensions << " in scope "
cout << " " << name_ << unpacked_dimensions << " in scope "
<< scope_path(scope) << endl;
}

View File

@ -16,6 +16,8 @@ module same;
timeunit 1ps;
timeprecision 1ps;
logic passed;
function logic check_time;
realtime result;
@ -45,12 +47,29 @@ module same;
check_time = 1'b0;
end
endfunction
initial begin
passed = 1'b1;
#0.499ps;
if ($realtime() != 0.0) begin
$display("Failed: Expected a 0.499ps delay to scale to 0ps of delay, got %f", $realtime());
passed = 1'b0;
end
#0.5ps;
if ($realtime() != 1.0) begin
$display("Failed: Expected a 0.5ps delay to scale to 1ps of delay, got %f", $realtime());
passed = 1'b0;
end
end
endmodule
module max;
timeunit 100s;
timeprecision 1fs;
bit passed;
function logic check_time;
realtime result;
@ -74,6 +93,21 @@ module max;
check_time = 1'b0;
end
endfunction
initial begin
passed = 1'b1;
#0.499fs;
if ($realtime() != 0.0) begin
$display("Failed: Expected a 0.499fs delay to scale to 0s of delay, got %f", $realtime());
passed = 1'b0;
end
#0.5fs;
if ($realtime() != 1e-17) begin
$display("Failed: Expected a 0.5fs delay to scale to 1e-17s of delay, got %f", $realtime());
passed = 1'b0;
end
end
endmodule
module top;
@ -119,6 +153,20 @@ module top;
passed &= same.check_time();
passed &= max.check_time();
if (passed) $display("PASSED");
#0.499ps;
if ($realtime() != 0.0) begin
$display("Failed: Expected a 0.499fs delay to scale to 0ns of delay, got %f", $realtime());
passed = 1'b0;
end
#0.5ps;
if ($realtime() != 0.001) begin
$display("Failed: Expected a 0.5fs delay to scale to 0.001ns of delay, got %f", $realtime());
passed = 1'b0;
end
#1; // Make sure all the delay tests have completed
if (passed && max.passed && same.passed) $display("PASSED");
end
endmodule

14
parse.y
View File

@ -3178,7 +3178,14 @@ delay_value_simple
if ($1 == 0 || !get_time_unit($1, unit))
yyerror(@1, "internal error: time literal delay.");
else {
#ifdef __FreeBSD__
// Using raw pow() in FreeBSD gives a value that is off by one and this causes
// rounding issues later, so for now use powl() to get the correct result.
long double ldp = powl(10.0, (long double)(unit - pform_get_timeunit()));
double p = (double) ldp;
#else
double p = pow(10.0, (double)(unit - pform_get_timeunit()));
#endif
double time = atof($1) * p;
verireal *v = new verireal(time);
@ -3825,7 +3832,14 @@ expr_primary
if ($1 == 0 || !get_time_unit($1, unit))
yyerror(@1, "internal error: time literal.");
else {
#ifdef __FreeBSD__
// Using raw pow() in FreeBSD gives a value that is off by one and this causes
// rounding issues below, so for now use powl() to get the correct result.
long double ldp = powl(10.0, (double)(unit - pform_get_timeunit()));
double p = (double) ldp;
#else
double p = pow(10.0, (double)(unit - pform_get_timeunit()));
#endif
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