Fix $time not rounding up (#4790) (#4792)

This commit is contained in:
Paul Wright 2024-01-02 01:11:46 +00:00 committed by GitHub
parent 3eaed3b6f5
commit 3adb31f53b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 100 additions and 1 deletions

View File

@ -305,7 +305,8 @@ uint64_t VerilatedContext::time() const VL_MT_SAFE {
// Time scaled from 1-per-precision into a module's time units ("Unit"-ed, not "United")
// Optimized assuming scale is always constant.
// Can't use multiply in Q flavor, as might lose precision
#define VL_TIME_UNITED_Q(scale) (VL_TIME_Q() / static_cast<QData>(scale))
#define VL_TIME_ROUND(t, p) (((t) + ((p) / 2)) / (p))
#define VL_TIME_UNITED_Q(scale) VL_TIME_ROUND(VL_TIME_Q(), static_cast<QData>(scale))
#define VL_TIME_UNITED_D(scale) (VL_TIME_D() / static_cast<double>(scale))
// Return time precision as multiplier of time units

23
test_regress/t/t_time.pl Executable file
View File

@ -0,0 +1,23 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2019 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(linter => 1);
compile(
verilator_flags2 => ["--exe --main --timing"],
make_main => 0,
);
execute(
check_finished => 1,
);
ok(1);
1;

75
test_regress/t/t_time.v Normal file
View File

@ -0,0 +1,75 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Paul Wright.
// SPDX-License-Identifier: CC0-1.0
/* Working through the $time example from IEEE Std 1364-2005
** Section 17.7.1
** The example uses a 10ns timeunit with a 1ns timeprecision
** For 16ns $time should return 2
** For 32ns $time should return 3
**/
module t ();
timeunit 10ns;
timeprecision 1ns;
longint should_be_2, should_be_3;
real should_be_1p6, should_be_3p2;
initial
begin : initial_blk1
should_be_2 = 0;
should_be_3 = 0;
#(16ns);
$display("$time=%d, $realtime=%g", $time(), $realtime());
should_be_2 = $time();
should_be_1p6 = $realtime();
#(16ns);
$display("$time=%d, $realtime=%g", $time(), $realtime());
should_be_3 = $time();
should_be_3p2 = $realtime();
#(16ns);
$finish(1);
end
initial
begin : initial_blk2
#(100ns);
$display("%%Error: We should not get here");
$finish(1);
end
function bit real_chk(input real tvar, input real evar);
begin
real diff;
diff = tvar - evar;
return (diff < 1e-9) && (diff > -1e-9);
end
endfunction
final
begin : last_blk
if (should_be_2 != 2)
begin
$display("%%Error: should_be_2 = %0d",
should_be_2);
$stop;
end
if (should_be_3 != 3)
begin
$display("%%Error: should_be_3 = %0d",
should_be_3);
$stop;
end
$display("Info: should_be_2 = %0d", should_be_2);
$display("Info: should_be_3 = %0d", should_be_3);
chk_2 : assert(should_be_2 == 2);
chk_3 : assert(should_be_3 == 3);
chk_1p6 : assert(real_chk(should_be_1p6, 1.6));
chk_3p2 : assert(real_chk(should_be_3p2, 3.2));
$write("*-* All Finished *-*\n");
end
endmodule