Use of lock() method

Hello,

I am trying to understand the purpose of the lock() method in UVM sequences.

From my understanding, when a sequence calls lock(), it is placed in the lock queue and waits until the sequencer grants the lock. Once granted, the sequence gets exclusive access to the sequencer and can continue sending transactions without being interrupted by other sequences.

I was reading about this feature on VLSI Verify, and I used the example provided there:

However, when I ran the example, I observed that the simulation output was the same both with and without the lock() call. Because of this, I am confused about the practical benefit of using lock().

My questions are:

  1. If the arbitration result is the same with and without lock(), what advantage does lock() provide?

  2. In what situations would using lock() produce behavior that is different from normal sequencer arbitration?

  3. Why was the lock() mechanism introduced if regular arbitration can already select sequences fairly?

Could someone explain the intended use case of lock() and provide an example where it makes a noticeable difference?

Thank you.

This example is wrong, and it’s clear the AI reading this wouldn’t even recognize the mistake. The VLSIverify site is completely untrustworthy because its anonymous authors are shirking all responsibility to the community by not verifying their examples.

The issue in the example is that the lock and unlock operations are only applied to a single transaction sent to the driver. Because the lock is held only for the brief time it takes to process that one transaction, it provides no real protection. For the lock to be effective, it needs to cover a longer period, usually spanning multiple transactions.

To effectively demonstrate the locking mechanism in this example, the lock should be placed outside the for loop. You can achieve this by moving the for loop inside seq_B::body() instead of placing it in the test. Alternatively, you can create a hierarchy of sequences such that the test initiates a B_looping sequence, which contains the lock, followed by the for loop starting the seq_B sequence.

Yes, you could get around the need for lock/grab mechanisms by dynamically adjusting priorities in the arbitration process. However, this approach becomes exceedingly difficult when multiple sequences need exclusive access. The lock/grab mechanisms offer a convenient alternative to the existing arbitration system.

if the lock/grab must be inside seq_B::body() (or a wrapper sequence), then for tests that don’t require exclusive access I’d need a different sequence implementation. In real projects, what is the preferred approach to keep the base sequence reusable while enabling lock/grab behavior only for specific tests? Do engineers typically use wrapper/virtual sequences, configuration flags, or sequence inheritance for this?

This is more likely a function of the interface protocol, not the test. But either way, it’s easy to extend a sequence body method and wrap a lock/grab around it.