uvm_tlm_time

Canonical time type that can be used in different timescales

This time type is used to represent time values in a canonical form that can bridge initiators and targets located in different timescales and time precisions.

For a detailed explanation of the purpose for this class, see Why is this necessary.

Summary
uvm_tlm_time
Canonical time type that can be used in different timescales
Class Declaration
class uvm_tlm_time
set_time_resolutionSet the default canonical time resolution.
newCreate a new canonical time value.
get_nameReturn the name of this instance
resetReset the value to 0
get_realtimeReturn the current canonical time value, scaled for the caller’s timescale
incrIncrement the time value by the specified number of scaled time unit
decrDecrement the time value by the specified number of scaled time unit
get_abstimeReturn the current canonical time value, in the number of specified time unit, reguardless of the current timescale of the caller.
set_abstimeSet the current canonical time value, to the number of specified time unit, reguardless of the current timescale of the caller.
Why is this necessaryIntegers are not sufficient, on their own, to represent time without any ambiguity: you need to know the scale of that integer value.

set_time_resolution

static function void set_time_resolution( real  res )

Set the default canonical time resolution.

Must be a power of 10.  When co-simulating with SystemC, it is recommended that default canonical time resolution be set to the SystemC time resolution.

By default, the default resolution is 1.0e-12 (ps)

new

function new( string  name  =  "uvm_tlm_time",
real  res  =  0 )

Create a new canonical time value.

The new value is initialized to 0.  If a resolution is not specified, the default resolution, as specified by set_time_resolution(), is used.

get_name

function string get_name()

Return the name of this instance

reset

function void reset()

Reset the value to 0

get_realtime

function real get_realtime( time  scaled,   
real  secs  =  1.0e-9 )

Return the current canonical time value, scaled for the caller’s timescale

scaled must be a time literal value that corresponds to the number of seconds specified in secs (1ns by default).  It must be a time literal value that is greater or equal to the current timescale.

#(delay.get_realtime(1ns));
#(delay.get_realtime(1fs, 1.0e-15));

incr

function void incr( real  t,   
time  scaled,   
real  secs  =  1.0e-9 )

Increment the time value by the specified number of scaled time unit

t is a time value expressed in the scale and precision of the caller.  scaled must be a time literal value that corresponds to the number of seconds specified in secs (1ns by default).  It must be a time literal value that is greater or equal to the current timescale.

delay.incr(1.5ns, 1ns);
delay.incr(1.5ns, 1ps, 1.0e-12);

decr

function void decr( real  t,
time  scaled,
real  secs )

Decrement the time value by the specified number of scaled time unit

t is a time value expressed in the scale and precision of the caller.  scaled must be a time literal value that corresponds to the number of seconds specified in secs (1ns by default).  It must be a time literal value that is greater or equal to the current timescale.

delay.decr(200ps, 1ns);

get_abstime

function real get_abstime( real  secs )

Return the current canonical time value, in the number of specified time unit, reguardless of the current timescale of the caller.

secs is the number of seconds in the desired time unit e.g.  1e-9 for nanoseconds.

$write("%.3f ps\n", delay.get_abstime(1e-12));

set_abstime

function void set_abstime( real  t,
real  secs )

Set the current canonical time value, to the number of specified time unit, reguardless of the current timescale of the caller.

secs is the number of seconds in the time unit in the value t e.g.  1e-9 for nanoseconds.

delay.set_abstime(1.5, 1e-12));

Why is this necessary

Integers are not sufficient, on their own, to represent time without any ambiguity: you need to know the scale of that integer value.  That scale is information conveyed outside of that integer.  In SystemVerilog, it is based on the timescale that was active when the code was compiled.  SystemVerilog properly scales time literals, but not integer values.  That’s because it does not know the difference between an integer that carries an integer value and an integer that carries a time value.  The ‘time’ variables are simply 64-bit integers, they are not scaled back and forth to the underlying precision.

`timescale 1ns/1ps

module m();

time t;

initial
begin
   #1.5;
   $write("T=%f ns (1.5)\n", $realtime());
   t = 1.5;
   #t;
   $write("T=%f ns (3.0)\n", $realtime());
   #10ps;
   $write("T=%f ns (3.010)\n", $realtime());
   t = 10ps;
   #t;
   $write("T=%f ns (3.020)\n", $realtime());
end
endmodule

yields

T=1.500000 ns (1.5)
T=3.500000 ns (3.0)
T=3.510000 ns (3.010)
T=3.510000 ns (3.020)

Within SystemVerilog, we have to worry about

  • different time scale
  • different time precision

Because each endpoint in a socket could be coded in different packages and thus be executing under different timescale directives, a simple integer cannot be used to exchange time information across a socket.

For example

`timescale 1ns/1ps

package a_pkg;

class a;
   function void f(inout time t);
      t += 10ns;
   endfunction
endclass

endpackage


`timescale 1ps/1ps

program p;

import a_pkg::*;

time t;

initial
begin
   a A = new;
   A.f(t);
   #t;
   $write("T=%0d ps (10,000)\n", $realtime());
end
endprogram

yeilds

T=10 ps (10,000)

Scaling is needed everytime you make a procedural call to code that may interpret a time value in a different timescale.

Using the uvm_tlm_time type

`timescale 1ns/1ps

   package a_pkg;

import uvm_pkg::*;

class a;
   function void f(uvm_tlm_time t);
      t.incr(10ns, 1ns);
   endfunction
endclass

endpackage


`timescale 1ps/1ps

program p;

import uvm_pkg::*;
import a_pkg::*;

uvm_tlm_time t = new;

initial
   begin
      a A = new;
      A.f(t);
      #(t.get_realtime(1ns));
      $write("T=%0d ps (10,000)\n", $realtime());
end
endprogram

yields

T=10000 ps (10,000)

A similar procedure is required when crossing any simulator or language boundary, such as interfacing between SystemVerilog and SystemC.

class uvm_tlm_time
Canonical time type that can be used in different timescales
static function void set_time_resolution( real  res )
Set the default canonical time resolution.
function new( string  name  =  "uvm_tlm_time",
real  res  =  0 )
Create a new canonical time value.
function string get_name()
Return the name of this instance
function void reset()
Reset the value to 0
function real get_realtime( time  scaled,   
real  secs  =  1.0e-9 )
Return the current canonical time value, scaled for the caller’s timescale
function void incr( real  t,   
time  scaled,   
real  secs  =  1.0e-9 )
Increment the time value by the specified number of scaled time unit
function void decr( real  t,
time  scaled,
real  secs )
Decrement the time value by the specified number of scaled time unit
function real get_abstime( real  secs )
Return the current canonical time value, in the number of specified time unit, reguardless of the current timescale of the caller.
function void set_abstime( real  t,
real  secs )
Set the current canonical time value, to the number of specified time unit, reguardless of the current timescale of the caller.
Integers are not sufficient, on their own, to represent time without any ambiguity: you need to know the scale of that integer value.