Wednesday, 23 November 2016

Kill process in SystemVerilog using "disable fork" and "disable LABEL"

Most of us, have faced these some issues at least one time in our SystemVerilog programming while using "disable fork" and "disable LABEL".

Let's first go through below example,
------------------------------------------------------------------------------

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

As shown in above example, "Process:1" is running continuously. Two different processes, "Process:2" and "Process:3" should run in parallel and any of two processes is completed, other process shall stop its execution due to join_any statement.

While simulating above code, you may face that when the disable fork is executed, "Process:1" also stop it's execution. So, to avoid this kind of situation, it's better to use "disable LABEL" statement.
------------------------------------------------------------------------------

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

Above code works fine with a single instance of that class. But when there are multiple instances of the same class in the test-bench and all the instances are executing their threads simultaneously then the simulation will stop after executing "disable LABEL" statement of any instance.
------------------------------------------------------------------------------

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

There are two ways to handle these kind of situations.
1) Limiting scope of "disable fork" by adding one extra hierarchy of fork...join.
2) Using "process" class of SystemVerilog

Let's see both ways through example,
------------------------------------------------------------------------------

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


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

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

Wait for more than one processes of fork...join_none to complete

In our project some time we want to wait for more than one process which is invoked from fork...join_none or join_any before proceeding further.

How to achieve this using SystemVerilog constructs, that we will understand through an example.

Let's go through below code,
-------------------------------------------------------------------------------------

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

In above code, class abc is having one method named multiple_process().
In API, within fork...join_none 4 process are invoked in parallel.
Each process puts one key into semaphore just before it's completed (Initially semaphore doesn't have any key).

After fork...join_none, I am waiting for semaphore to get at least two key ().

Friday, 26 August 2016

Callback vs Factory in UVM

Callbacks and factory address different areas of re-usability.

Callback: Add functionality to existing logic.

Factory: Change the existing component before build, keeps environment same.

Although the callback and factory can be interchangeably used to address the same problem. Depending on the need and demand, a wise decision should be made while adopting either of the techniques as they have their own merits and demerits.



Wednesday, 22 June 2016

Strength in Verilog

Strengths can be used to resolve which value should appear on a net or gate output.
A strength specification shall have the following two components:
The strength of the 0 portion of the net value, called strength0, designated as one of the following:
supply0 strong0 pull0 weak0 highz0
The strength of the 1 portion of the net value, called strength1, designated as one of the following:
supply1 strong1 pull1 weak1 highz1
The combinations (highz0, highz1) and (highz1, highz0) shall be considered illegal.

There are four driving strengths: supply strong pull weak
Signals with driving strengths shall propagate from gate outputs and continuous assignment outputs.

There are three charge storage strengths: large medium small
Signals with the charge storage strengths shall originate in the trireg net type.

It is possible to think of the strengths of signals as locations on the scale

When signals combine, their strengths and values shall determine the strength and value of the resulting signal in accordance with the principle.

1) If two or more drivers drive a signal with different strength then it will have the value of the strongest driver
Ex-1:
buf (strong1, weak0) g1 (y, a);
buf (pull1, supply0) g2 (y, b);
If a = 0 and b = 0 then y will be 0 with supply strength because both gates will set y to 0 and supply (7) strength has bigger value than weak (3) strength.
If a = 0 and b = 1 then y will be 1 with pull strength because g1 will set y to 0 with weak (3) strength and g2 will set y to 1 with pull (5) strength (pull strength is stronger than the weak strength).
If a = 1 and b = 0 then y will be 0 with supply strength because g1 will set y to 1 with strong (6) strength and g2 will set y to 0 with supply (7) strength (supply strength is stronger than the strong strength).
If a = 1 and b = 1 then y will be 1 with strong strength because g1 will set y to 1 with strong (6) strength and g2 will set y to 1 with pull (5) strength.

2) The combination of signals identical in strength and value shall result in the same signal (If two drivers of a net have the same strength and value, then the net result will have the same value and strength)
Ex-2:
buf (strong1, weak0) g1 (y, a);
buf (strong1, weak0) g1 (y, b);
If a = 0 and b = 0 then y will be 0 with weak strength.
If a = 1 and b = 1 then y will be 1 with strong strength.

3) If two drivers of a net have the same strength but different values then signal value will be unknown and it will have the same strength as both drivers
Ex-3:
buf (strong1, weak0) g1 (y, a);
buf (weak1, strong0) g1 (y, b);
If a = 1 and b = 0 then y will be x with strong strength.

Important Notes:
If one of the drivers has an H or L value, then the output value will be X.

Reference:
1) http://verilog.renerta.com/source/vrg00047.htm
2) System Verilog LRM (1800-2012)

Saturday, 30 April 2016

Override in UVM using factory with Example

One of the main advantage of UVM is Creating each components using factory enables them to be overridden in different tests or environments without changing underlying code base.

uvm_factory provides four different methods to override particular instance or all instances of particular class.
set_inst_override_by_type
set_inst_override_by_name
set_type_override_by_type
set_type_override_by_name


Let's go through example of each one of above four ways.

set_inst_override_by_type
-------------------------------------------------------

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

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

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


set_inst_override_by_name

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

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

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

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


set_type_override_by_type
-------------------------------------------------------

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

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

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


set_type_override_by_name
-------------------------------------------------------

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

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

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

set_inst_override_* has high precedence than set_type_override_*.
i.e. If any particular instance of class is override by using set_inst_override_* and type of same class is overridden by using set_type_override_* then that particular instance of class is overridden by set_inst_override_* and rest other instances are overridden by set_type_override_*

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

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

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

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



UVM also support override through command line,
+uvm_set_inst_override=,,
+uvm_set_type_override=,[,]

work like the name based overrides in the factory--factory.set_inst_override_by_name() and factory.set_type_override_by_name().

Let's implement same example as above using command line arguments.
-------------------------------------------------------

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

Simulation time argument:
+uvm_set_inst_override=A,A_override,uvm_test_top.env.a3 \
+uvm_set_inst_override=B,B_ovr,path1.b1 \
+uvm_set_type_override=A,A_ovr \
+uvm_set_type_override=B,B_override
-------------------------------------------------------

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

Singleton class in System Verilog

Sometimes it is required to have only one object of some classes like configuration classes. For this purpose we create singleton classes.
Only one object is created for a singleton class and whenever we try to create a new object, same object is returned.

System verilog does not provide construct to create a singleton class. But we can create it with some manipulation.

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

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


uvm_root class defined as a singleton class in UVM source code.
---------------------------------------------------------------------

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

Monday, 25 April 2016

UVM FAQ2



Why phasing is used? What are the different phases in uvm?
UVM Phases is used to control the behavior of simulation in a systematic way & execute in a sequential ordered to avoid race condition. This could also be done in system verilog but manually.

 



Which phases of UVM are Top-Down?
build_phase() & final_phase() are Top-Down, rest all phases are Bottom-Up.



Which phases of UVM are task?
run_phase(),
pre_reset_phase(), reset_phase(), post_reset_phase(),
pre_configure_phase(), configure_phase(), post_configure_phase(),
pre_main_phase(), main_phase(), post_main_phase(),
pre_shutdown_phase(), shutdown_phase(), post_shutdown_phase()



How do uvm phases initiate?
Calling run_test() constructs the UVM environment root component and then initiates the UVM phasing.



Why is the build_phase() in UVM executed in a Top - Down fashion and the other phases in Bottom - Up fashion?
The build phase has to be that way because the parent component's build_phase constructs the child components. You couldn't call the child's build_phase before the parent's build_phase because they the child objects haven't been constructed yet. You need a constructed object to call its method.
The build_phase() is also executed top-down so that the parent can provide override setting that the children will use when they execute their build_phase()
The ordering within the other phases should not matter, except you might want know that the top level's report_phase comes last.



What is the order of execution of run_phase() ?
The run_phase() of each component is executed concurrently with no defined order you can depend on.



During the run_phase() is there something like super.run_phase(phase) called?
You only need to call super.method() if you are extending a class an need the functionality of the base method. There is nothing inside the run_phase() of a uvm_component, so there is no need to call super.run_phase() when extending from it.
You may want to call it when extending your classes from your base classes.





What is the difference between run_phase and main_phase in uvm_component?
Actually, you can start a sequence in any phase. It is more important to understand the domain/scheduling relationships between the task based (i.e. runtime) phases.
UVM undergoes a number of pre-simulation phases (build, connect, end_of_elaboration, start_of_simulation) that are all implemented with functions. Once those are completed, the task based phases begin.
The standard includes two schedules.

  • One is simply the run_phase, which starts executing at time zero and continues until all components have dropped their objections within the run_phase.
  • The other schedule contains twelve phases that execute parallel to the run phase. They are: pre_reset, reset, post_reset, pre_config, config, post_config, pre_main, main, post_main, pre_shutdown, shutdown, and post_shutdown. They execute in sequence.

Every component has the opportunity to define or not define tasks to execute these phases. A phase starts only when all components in the previous phase have dropped their objections. A phase continues to execute until all components have dropped their objections in the current phase.



Why connect_phase() is bottom-up?

 

Sunday, 24 April 2016

Difference between m_sequencer and p_sequencer in UVM

To understand difference between m_sequencer and p_sequencer, let's first go through couple of classes from UVM library.
-------------------------------------------------------------------------------------

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


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

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

When you call `uvm_declare_p_sequencer from sequence, it overrides m_set_p_sequencer function.
When you call start method of sequence, it calls set_item_context method,
Then set_item_context method calls set_sequencer method,
Then set_sequencer method assign handle of sequencer (which you pass in start method of sequence) to m_sequencer,
set_sequencer also calls m_set_p_sequencer method, but you have override the m_set_p_sequencer method by declaring `uvm_declare_p_sequencer macro.
So m_set_p_sequencer defined in macro will be executed, and it casts m_sequencer into p_sequencer,
where p_sequencer's type is specified by the argument of `uvm_declare_p_sequencer macro.


Conclusion:

m_sequencer and p_sequencer both point to the same thing (the sequencer on which the sequence is running). However, there are some important differences:
m_sequencer is a generic uvm sequencer pointer of type uvm_sequencer_base. It will always exist for an uvm_sequence and is initialized when the sequence is started.

p_sequencer is a reference to uvm_sequencer#(REQ,RSP), the user derived parameterized sequencer class.
Other way you can say that p_sequencer is a type specific sequencer pointer.
p_sequencer will not exist if the `uvm_declare_p_sequencer macros aren't used.

Advantage of p_sequencer over m_sequencer:
Being type specific, you will be able to access anything added to the sequencer (i.e. pointers to other sequencers, handle of environment class (which is defined in user derived virtual sequencer class) etc.).

Drawback of p_sequencer over m_sequencer:
p_sequencer creates an additional dependency, means sequence which use p_sequencer may not be executed on all the sequencers. Sequence requires resource in sequencer class which is declared as p_sequencer (i.e. pointers to other sequencers, handle of environment class, etc.)

Saturday, 23 April 2016

Randomize Non-random (State) variable using randomize() method of Class



The randomize() method can be used to temporarily control the set of random and state variables within a class instance or object.
When randomize is called with arguments, those arguments designate the complete set of random variables within that object; all other variables in the object are considered state variables.
The randomize method accepts the special argument null to indicate no random variables for the duration of the call. In other words, all class members behave as state variables.
Consider following Example:
----------------------------------------------------
----------------------------------------------------

rand_mode and constraint_mode in System Verilog



rand_mode:

The random nature of variables declared as rand or randc can be turned on or off dynamically by using in-built method called rand_mode().  rand_mode() can be called as function or task.

In below example, rand_mode of all variable of class is disabled and enabled.
---------------------------------------------------------------------
---------------------------------------------------------------------

We can also change rand_mode of specific variable. Consider below example,
---------------------------------------------------------------------
---------------------------------------------------------------------

When rand_mode method is called as function, it returns the active status of the specified random variable.
When called as a function, rand_mode() returns the current active state of the specified random variable. It returns 1 if the variable is active (ON) and 0 if the variable is inactive (OFF).
---------------------------------------------------------------------
---------------------------------------------------------------------

A compiler error shall be issued if the specified variable does not exist within the class hierarchy or even though it exists but not declared as rand or randc. The following example illustrates the second case.

rand_mode of rand static variable,
---------------------------------------------------------------------
---------------------------------------------------------------------

 
constraint_mode


SystemVerilog supports to change the status of constraint block dynamically.
The constraint_mode() method can be used to active/inactive constraint. By default all the constraint blocks are active. When a constraint is inactive, it is not considered by the randomize() method.

It can be used as task or function.
When called as a task, the argument to the constraint_mode task method determines the operation to be performed. 
When called as a function, constraint_mode() returns the current active state of the specified constraint block. It returns 1 if the constraint is active (ON) and 0 if the constraint is inactive (OFF).

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