Thursday, 23 March 2017

Automatic raise/drop objection with UVM-1.2

Variable uvm_sequence_base::starting_phase is deprecated and replaced by two new methods set_starting_phase and get_starting_phase, which prevent starting_phase from being modified in the middle of a phase. This change is not backward-compatible with UVM 1.1, though variable starting_phase, although deprecated, has not yet been removed from the base class library.

New method uvm_sequence_base::set_automatic_phase_objection causes raise_objection and drop_objection to be called automatically around a sequence, avoiding the need to call raise/drop_objection manually in one common situation.

Lets understand it trough below mentioned example.
------------------------------------------------

------------------------------------------------


Ref:
1) https://www.doulos.com/knowhow/sysverilog/uvm/uvm-1.2/

Simulation timeout in UVM using set_timeout and +UVM_TIMEOUT

Default timeout for simulation or you can say timeout for run_phase (as rest all phases are non-time consuming) is `UVM_DEFAULT_TIMEOUT, if not overridden by uvm_root::set_timeout or uvm_cmdline_processor::+UVM_TIMEOUT.

Default value of `UVM_DEFAULT_TIMEOUT is 9200 second.
-------------------------------------------------
-------------------------------------------------

Example 1 (Timeout at default time which is 9200 second):
-------------------------------------------------
-------------------------------------------------

1) Overridden by uvm_root::set_timeout

-------------------------------------------------
-------------------------------------------------
-------------------------------------------------
-------------------------------------------------

Example 2 (Timeout at specified time which is specified using set_timeout):
-------------------------------------------------
-------------------------------------------------


2) Overridden by uvm_cmdline_processor::+UVM_TIMEOUT

+UVM_TIMEOUT=, allows users to change the global timeout of the UVM framework.  The argument (‘YES’ or ‘NO’) specifies whether user code can subsequently change this value.  If set to ‘NO’ and the user code tries to change the global timeout value, a warning message will be generated.

Example 3 (Timeout at 100s using simulation switch +UVM_TIMEOUT=100000000000):
Note: Here you need to give simulation time in format of timescale defined in simulation
-------------------------------------------------
-------------------------------------------------

Tuesday, 21 February 2017

Lock and Grab of sequencer in UVM

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.

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.

---------------------------------------------
---------------------------------------------

Thursday, 16 February 2017

Difference between @event and wait(event.triggered) in SystemVerilog and usage of non-blocking event

The event data type provides a handle to a synchronization object.

There are two ways through which we can wait for particular event to be triggered.
So let's understand what is the exact difference between those 2 ways.

-----------------------------------------------

-----------------------------------------------

An event trigger ->e is an instantaneous event. The event waiting process @ shall execute before the triggering process -> executes. If the trigger executes first, then the waiting process remains blocked.

The triggered event property evaluates to true (1'b1) if the given event has been triggered in the current time step and false (1'b0) otherwise.
Now you no longer have to worry which came first, the triggering process –> or the waiting process @ statement. But you still have to execute the waiting process @ in the current time slot to catch the event.

Let’s see the behavior with examples,
-----------------------------------------------

-----------------------------------------------

-----------------------------------------------

-----------------------------------------------

The other workaround is to use nonblocking event

Non-blocking event ->>
Nonblocking events are triggered using the ->> operator.

The effect of the ->> operator is that the statement executes without blocking, and it creates a nonblocking assign update event in the time in which the delay control expires or the event control occurs. The effect of this update event shall be to trigger the referenced event in the nonblocking assignment region of the simulation cycle.

-----------------------------------------------
-----------------------------------------------