Uses 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
- wait_for : Waits for enough processes to reach the barrier before continuing.
- reset : Resets the barrier. This sets the waiter count back to zero.
- set_auto_reset : Determines if the barrier should reset itself after the threshold is reached. Default is on
- set_threshold : Sets the process threshold.
- get_threshold : Gets the current threshold setting for the barrier.
- get_num_waiters : Returns the number of processes currently waiting at the barrier.
- 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
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
