From 5d561f3ef1a05f504aae94c481483de53082975f Mon Sep 17 00:00:00 2001 From: Cary R Date: Sat, 9 Dec 2023 12:49:25 -0800 Subject: [PATCH] Fix time issue in FreeBSD (pow() bug) --- elab_sig.cc | 4 +-- ivtest/ivltests/timeliteral.v | 50 ++++++++++++++++++++++++++++++++++- parse.y | 14 ++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/elab_sig.cc b/elab_sig.cc index 0c8ec6f39..68818474d 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -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; } diff --git a/ivtest/ivltests/timeliteral.v b/ivtest/ivltests/timeliteral.v index 219d1cda9..a08119d47 100644 --- a/ivtest/ivltests/timeliteral.v +++ b/ivtest/ivltests/timeliteral.v @@ -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 diff --git a/parse.y b/parse.y index 66f98064c..0b9b61454 100644 --- a/parse.y +++ b/parse.y @@ -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