There are a number of modelling scenarios where one sequence needs to have exclusive access to a driver via a sequencer. One example of this type of scenario is a sequence which is responding to an interrupt.
In order to accommodate this requirement, the uvm_sequencer provides 2 types of mechanism called lock()-unlock() and grab()-ungrab().
If sequencer is doing some sequence and based on some external events if user wants sequencer to pause the current sequence, he/she can grab/lock sequencer and start another sequence. Once the started sequence finishes sequencer can resume the normal operation, upon ungrab/unlock.
This mechanism is generally used to mimic CPU behavior, where CPU is doing a normal bus operation and when interrupt comes, CPU needs to suspend the normal operation and start interrupt handling. Once interrupt handling is over, CPU should resume the normal operation from where it was suspended.
A lock might be used to model a prioritized interrupt and a grab might be used to model a non-mask able interrupt (NMI).
The lock() and grab() calls have antidote calls to release a lock and these are unlock() and ungrab().
Lock()
1) A lock() request is put in back of the arbitration queue . A lock request will be arbitrated the same as any other request.
2) A lock is granted after all earlier requests are completed and no other locks or grabs are blocking this sequence.
3) A lock() is blocking task and when access is granted, it will unblock.
4) If no argument is supplied, then current default sequencer is chosen.
Grab()
1) A grab() request is put in front of the arbitration queue. A grab() request will be arbitrated before any other requests.
2) A grab() is granted when no other grabs or locks are blocking this sequence. (The only thing that stops a sequence from grabbing a sequencer is a pre-existing lock() or grab() condition.)
3) A grab() is blocking task and when access is granted, it will unblock.
4) If no argument is supplied, then current default sequencer is chosen.
Unlock()
The unlock sequencer function is called from within a sequence to give up its lock or grab. A locking sequence must call unlock before completion; otherwise the sequencer will remain locked.
Ungrab()
An alias of function unlock().
What happens if 2 sequences try to grab or lock the same sequencer?
The most recent grab goes to the front of the queue; the most recent lock goes to the back of the queue.
Priority in lock() and grab().
The most recent grab comes first, then the previous grab... then the oldest lock, then the most recent lock.
In order to accommodate this requirement, the uvm_sequencer provides 2 types of mechanism called lock()-unlock() and grab()-ungrab().
If sequencer is doing some sequence and based on some external events if user wants sequencer to pause the current sequence, he/she can grab/lock sequencer and start another sequence. Once the started sequence finishes sequencer can resume the normal operation, upon ungrab/unlock.
This mechanism is generally used to mimic CPU behavior, where CPU is doing a normal bus operation and when interrupt comes, CPU needs to suspend the normal operation and start interrupt handling. Once interrupt handling is over, CPU should resume the normal operation from where it was suspended.
A lock might be used to model a prioritized interrupt and a grab might be used to model a non-mask able interrupt (NMI).
The lock() and grab() calls have antidote calls to release a lock and these are unlock() and ungrab().
Lock()
1) A lock() request is put in back of the arbitration queue . A lock request will be arbitrated the same as any other request.
2) A lock is granted after all earlier requests are completed and no other locks or grabs are blocking this sequence.
3) A lock() is blocking task and when access is granted, it will unblock.
4) If no argument is supplied, then current default sequencer is chosen.
Grab()
1) A grab() request is put in front of the arbitration queue. A grab() request will be arbitrated before any other requests.
2) A grab() is granted when no other grabs or locks are blocking this sequence. (The only thing that stops a sequence from grabbing a sequencer is a pre-existing lock() or grab() condition.)
3) A grab() is blocking task and when access is granted, it will unblock.
4) If no argument is supplied, then current default sequencer is chosen.
Unlock()
The unlock sequencer function is called from within a sequence to give up its lock or grab. A locking sequence must call unlock before completion; otherwise the sequencer will remain locked.
Ungrab()
An alias of function unlock().
What happens if 2 sequences try to grab or lock the same sequencer?
The most recent grab goes to the front of the queue; the most recent lock goes to the back of the queue.
Priority in lock() and grab().
The most recent grab comes first, then the previous grab... then the oldest lock, then the most recent lock.
Let’s go through basic example of lock() and grab()
1) Lock
---------------------------------------------
---------------------------------------------
2) Grab
---------------------------------------------
---------------------------------------------
From output of above two examples, we can see the difference between lock() and grab() as mentioned above.
When a hierarchical sequence locks/grab a sequencer, then its child sequences will have access to the sequencer.
If one of the child sequences issues a lock/grab, then the parent sequence will not be able to start any parallel sequences or send any sequence_items until the child sequence has unlocked.
---------------------------------------------
---------------------------------------------
A locking or grabbing sequence must always unlock before it completes,
---------------------------------------------
---------------------------------------------
Now let’s go through one example where 2 virtual sequences are running in parallel and one virtual sequence put lock/grab on agent’s sequencer.
---------------------------------------------
---------------------------------------------