Wednesday, 30 September 2015

Barrier in UVM and Usage of uvm_barrier

uvm_barrier can be used to force a set of independently executing processes (e.g. virtual sequences) to wait until they have all reached a particular point.
The barrier provides a flexible synchronization mechanism between the processes: its threshold can be programmed to set the number of processes that must reach the synchronization point before the barrier is 'lifted'.

A barrier is like a semaphore in reverse. It simply blocks until a threshold number of requests.

The uvm_barrier class provides a multi-process synchronization mechanism.  It enables a set of processes to block until the desired number of processes get to the synchronization point, at which time all of the processes are released.

APIs of uvm_barrier class
  1. wait_for : Waits for enough processes to reach the barrier before continuing. 
  2. reset : Resets the barrier. This sets the waiter count back to zero. 
  3. set_auto_reset : Determines if the barrier should reset itself after the threshold is reached. Default is on 
  4. set_threshold : Sets the process threshold. 
  5. get_threshold : Gets the current threshold setting for the barrier. 
  6. get_num_waiters : Returns the number of processes currently waiting at the barrier. 
  7. cancel : Decrements the waiter count by one. This is used when a process that is waiting on the barrier is killed or activated by some other means.
Consider following examples,

module top();
import uvm_pkg::*;
uvm_barrier b;
task delay(
input uvm_barrier _b,
input int unsigned _delay,
input string _name
);
automatic string _s = _name;
#_delay;
_b.wait_for();
$display("%s Process @%0t", _s, $realtime);
endtask : delay
initial begin
b = new("Barrier",2); // Wait for 2 process to be completed
fork
delay(._b(b), ._delay(10), ._name("A"));
delay(._b(b), ._delay(35), ._name("B"));
delay(._b(b), ._delay(50), ._name("C"));
delay(._b(b), ._delay(20), ._name("D"));
delay(._b(b), ._delay(80), ._name("E"));
delay(._b(b), ._delay(70), ._name("F"));
join
$display("outside Fork-Join @%0t", $realtime);
end
endmodule
//Output:
// A Process @20
// D Process @20
// B Process @50
// C Process @50
// F Process @80
// E Process @80
// outside Fork-Join @80

module top();
import uvm_pkg::*;
uvm_barrier b;
task delay(
input uvm_barrier _b,
input int unsigned _delay,
input string _name
);
automatic string _s = _name;
#_delay;
_b.wait_for();
$display("%s Process @%0t", _s, $realtime);
endtask : delay
initial begin
b = new("Barrier",3); // Wait for 3 process to be completed
fork
delay(._b(b), ._delay(10), ._name("A"));
delay(._b(b), ._delay(35), ._name("B"));
delay(._b(b), ._delay(50), ._name("C"));
delay(._b(b), ._delay(20), ._name("D"));
delay(._b(b), ._delay(80), ._name("E"));
delay(._b(b), ._delay(70), ._name("F"));
join
$display("outside Fork-Join @%0t", $realtime);
end
endmodule
//Output:
// D Process @35
// A Process @35
// B Process @35
// F Process @80
// C Process @80
// E Process @80
// outside Fork-Join @80


1 comment: