A sequence may need exclusive access to the driver which sequencer is arbitrating among multiple sequence. Some operations require that a series of transaction needs to be driven without any other transaction in between them. Then a exclusive access to the driver will allow to a sequence to complete its operation with out any other sequence operations in between them.
There are 2 mechanisms to get exclusive access:
Lock-unlcok
Grab-ungrab
Using lock() method , a sequence can requests for exclusive access. A lock request will be arbitrated the same as any other request. A lock is granted after all earlier requests are completed and no other locks or grabs are blocking this sequence. A lock() is blocking task and when access is granted, it will unblock.
Using unlock(), removes any locks or grabs obtained by this sequence on the specified sequencer.
If sequencer is null, the lock/unlock will be applied on the current default sequencer.
Lets see an example,
In this example there are 3 sequences with each sequence generating 4 transactions. All these 3 sequences will be called in parallel in another sequence.
(S)Sequence 1 code:
virtualtask body();
repeat(4) begin `ovm_do_with(req, { inst == PUSH_A; });
end endtask
(S)Sequence 2 code: virtualtask body();
repeat(4) begin `ovm_do_with(req, { inst == POP_C; });
end endtask
(S)Sequence 3 code:
In this sequence , call the lock() method to get the exclusive access to driver.
After completing all the transaction driving, then call the unclock() method.
virtualtask body();
lock();
repeat(4) begin `ovm_do_with(req, { inst == PUSH_B; });
end unlock();
endtask
grab() method requests a lock on the specified sequencer. A grab() request is put in front of the arbitration queue. It will be arbitrated before any other requests. A grab() is granted when no other grabs or locks are blocking this sequence.
A grab() is blocking task and when access is granted, it will unblock.
Ungrab() method removes any locks or grabs obtained by this sequence on the specified sequencer.
If no argument is supplied, then current default sequencer is chosen.
Example:
virtualtask body();
#25;
grab();
repeat(4) begin `ovm_do_with(req, { inst == PUSH_B; });
end ungrab();
endtask