I am performing transaction recording in a custom UVM monitor, where the agent has a different timeunit to the rest of the test bench. When I measure the current simulation time, the $time system call correctly reports the time for the current package using the timeunit of that package. However, when I pass that value to the begin_tr() or end_tr() functions, it treats the values as if they are reported for the global timeunit, which doesn’t necessarily match the timeunit of the package. Is there a simple way to obtain the global timeunit to scale the values in a portable manner?
The intention is to create a reusable agent that will exist in test benches of differing timeunits.
In reply to Paul McKechnie:
Communicating time values across multiple timescale domains has been a gotchain Verilog since day one. There is no physical time data type, so it is best if you use real numbers and $realtime to avoid truncation, and then normalize your real time values using a mutually agreed upon time literal. For example, the expression
$realtime / 1ps
always results in value where 1.0 means 1 picosecond, regardless of the current timeunit. If that expression gets passed to another scope having a different timeunit, you can multiply it again by 1ps
timeunit 1ns
real timestamp;
timestamp = $realtime / 1pa;
call_another_timunit(timestamp);
timeunit 1ps;
function void call_another_timeunit(real ts);
$display("time current timescale",, ts * 1ps );
endfunction
Lets say we were at time 100 ps when the fist code snippet executes. $realtime returns 0.1 whereas $time would have rounded to return 0. 1ps returns 0.001 when the timeunit is in nanoseconds. So (0.1/0.001) = 100. Whatever the timeunit, this expression would always return 100.
Now call the function call_another_timunit() with the value 100. If we multiply it by 1ps when the timeunit is 1ps, that results in 100 * 1 = 100.
There’s also a uvm_tlm2_time class that could probably help you here. You’d need to have a config field inside your UVC which tells it what the global precision is:
class uvc_config;
enum { PS, NS } resolution;
function time get_cur_time();
uvm_tlm2_time t = new();
return get_realtime($time(), resolution == PS : 1.0e-12 ? 1.0e-9;
endfunction
endclass
class some_component;
task some_task();
// do stuff
begin_tr(..., .begin_time(cfg.get_cur_time()));
endtask
endclass
DISCLAIMER: I haven’t tested the code and it’s sure to have some problems, but you could probably use it as a starting point.