Thursday, 11 February 2016

uvm_config_db

The uvm_config_db class is the recommended way to access the resource database.
A resource is any piece of information that is shared between more than one component or object.
We use uvm_config_db::set to put something into the database and uvm_config_db::get to retrieve information from the database.
The uvm_config_db class is parameterized, so the database behaves as if it is partitioned into many type-specific "mini databases."
There are no limitations on the the type - it could be a class, a uvm_object, a built in type such as a bit, byte, or a virtual interface.
There are two typical uses for uvm_config_db. The first is to pass virtual interfaces from the DUT to the test, and the second is to pass configuration classes down through the testbench.

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

/*****************ARGUMENTS*****************/
T is the type of the element being configured - usually a virtual interface or a configuration object.

cntxt and inst_name together form a scope that is used to locate the resource within the database.
The scope is formed by appending the instance name to the full hierarchical name of the context.
{cntxt, ".", inst_name}. or {cntxt.get_full_name(),".",inst_name}. //need to confirm
If cntxt is null then inst_name provides the complete scope information of the setting.

field_name supplies the name of the resource or thing. field_name is the key through which you can get that particular object.
field_name must be same during get & set, because while getting from uvm_databse it will find for field_name.

value is the thing or resource which is actually going to be put into the database.
value name can be different but value type must be same for get and set.
Both inst_name and field_name may be glob style or regular expression style expressions.

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

Precedence:

Build Phase:
----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
Example1:
----------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------
 Example2:

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

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

Run Phase:
----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------

Example1:
----------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------
 Example2:
----------------------------------------------------------------------------------------------------------------------

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


/*********************Guideline**************************/
1. Before set anything into database first allocates memory to them and then put into database using set method.

Friday, 5 February 2016

`uvm_info vs uvm_report_info in SystemVerilog

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


How to change verbsity for particular component in UVM

There are two ways to set/control/change verbosity of particular component. 
  1. Using method call 
  2. Through Command line
Here I explained both using example.
Let's go through examples.

1. Using method call
-----------------------------------------------------------------------------------------------------

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

2. Through Command line
-----------------------------------------------------------------------------------------------------

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

Now run with 3 different simulation commands and see the difference.

+uvm_set_verbosity=component,id,verbosity,phase


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


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

Reference:

import vs `include in SystemVerilog

The compiler goes through a pre-processor step. This step processes all the include files, conditionals, and text macros into a single stream of text. Except for error reporting and debugging, the compiler does not care how many files were used to make up that stream of text.

`include directive is just a mechanism for assembling text. The directive provides two key pieces of functionality:

  • Maintain repetitive blocks of text in a single file,
  • Specify file compilation order dependences from within a file instead of on the compiler command line,
SystemVerilog also supports separate compilation units. A compilation unit is one stream of text.
If you have multiple compiler command lines, then you will have at least one compilation unit per command line.
If you have multiple compilation units and have a set of classes that need to be shared across the compilation units, then you must use a package to define those classes or any user defined type.
And then in other compilation you can access that set of classes by importing that package.


Let’s go through one example,
1. Include
----------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------
After `including class A into each package, you wind up with two definitions of class A. Using `include is just a shortcut for cut and pasting text in a file. Importing a name from a package does not duplicate text; it makes that name visible from another package without copying the definition.

2. Import
-----------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------
Class A is declared in package P, and only in package P. The variables R::a1 and S::a1 are type compatible because they are both of type P::A. The fact that class A was `included from another file once it is expanded is no longer relevant once you consider the placement of the text from the file.

Reference:

Thursday, 4 February 2016

$unit vs $root in SystemVerilog



In one line you can say that, $unit represents the top level of each compilation unit, but $root refers to the top level instance.

Now let’s discuss it in little-bit more detail.

$root:

  • $root is the root of the instantiation tree.
  • SystemVerilog introduced the concept of $root as a global scope that allowed any kind of declaration (data types, classes, variables) along with module definitions nested in that global scope.
  • Any un-instantiated module is implicitly instantiated in $root.
  • A top-level module is implicitly instantiated once in $root, and its instance name is the same as the module name.


$unit:

  • A compilation unit formalizes a scope that represents what is visible in a compilation step – called $unit in SystemVerilog.
  • SystemVerilog borrowed the concept of packages from VHDL and standardized the concept of a compilation unit. A package allows you to compile definitions in a separate step and import those definitions into another compilation step.

Basic example of $unit,
-----------------------------------------------------------------------------------------------------------------

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

If you have a design that is compiled as a single compilation unit, there is really no conceptual difference between $unit and $root.

However, once you have a design with multiple compilation units, then $unit represents the top level of each compilation unit, and there is nothing in $root except for the implicitly instantiated module instances.


The only time you need to use $root or $unit is when a local name in the current scope hides a name in a higher level scope. For example,

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

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

Here module “mod2” and module “mod1” has same task called “print”. The ambiguity is resolved by giving priority to the local scope and thereby preventing access to the top-level path. $root allows explicit access to the top level in those cases in which the name of the top-level module is insufficient to uniquely identify the path.

Note that there is no way for compilation unit 1 to directly refer to anything in compilation unit 2, or the other way around.

Reference:
1. https://blogs.mentor.com/verificationhorizons/blog/2009/09/25/unit-vs-root/

Tuesday, 2 February 2016

Process class in SystemVerilog


A process is a built-in class that allows one process to access and control another process once it has started. Users can declare variables of type process and safely pass them through tasks or incorporate them into other objects. The prototype for the process class is:


Objects of type process are created internally when processes are spawned.
Users cannot create objects of type process; attempts to call new shall not create a new process, and instead result in an error.

The process class cannot be extended. Attempts to extend it shall result in a compilation error.

Objects of type process are unique; they become available for reuse once the underlying process terminates and all references to the object are discarded.

The self() function returns a handle to the current process, that is, a handle to the process making the call.

The status() function returns the process status, as defined by the state enumeration:
FINISHED Process terminated normally.
RUNNING Process is currently running (not in a blocking statement).
WAITING Process is waiting in a blocking statement.
SUSPENDED Process is stopped awaiting a resume.
KILLED Process was forcibly killed (via kill or disable).

kill
The kill() task terminates the given process and all its sub-processes, that is, processes spawned using fork statements by the process being killed. If the process to be terminated is not blocked waiting on some other condition, such as an event, wait expression, or a delay then the process shall be terminated at some unspecified time in the current time step.

await
The await() task allows one process to wait for the completion of another process. It shall be an error to call this task on the current process, i.e., a process cannot wait for its own completion. 

suspend
The suspend() task allows a process to suspend either its own execution or that of another process. If the process to be suspended is not blocked waiting on some other condition, such as an event, wait expression, or a delay then the process shall be suspended at some unspecified time in the current time step. Calling this method more than once, on the same (suspended) process, has no effect. 

resume
The resume() task restarts a previously suspended process. Calling resume on a process that was suspended while blocked on another condition shall re-sensitize the process to the event expression, or wait for the wait condition to become true, or for the delay to expire. If the wait condition is now true or the original delay has transpired, the process is scheduled onto the Active or Reactive region, so as to continue its execution in the current time step. Calling resume on a process that suspends itself causes the process to continue to execute at the statement following the call to suspend.

The example below starts an arbitrary number of processes, as specified by the task argument N. Next, the task waits for the last process to start executing, and then waits for the first process to terminate. At that point the parent process forcibly terminates all forked processes that have not completed yet.

USE-CASE:
Consider a case where you have already written a transactor which sends packets according to your requirements. Now you need to change your code to make it work in the low-power-world where you need to stop sending packets whenever the system enters low-power state and resume sending packet once you are out of it. You have coded “HOW” to send your packet, and now you need to incorporate “WHEN” to send it, which itself can be far more complex that the simple “HOW”.

You can directly go and modify the transactor code to incorporate “WHEN” aspect of the packet transmission. There are quite a few reasons why you would rather not touch the code and do the same in another way.

Fine grain process control can be very nicely used in such scenario. You can have a handle of the process of sending packet. Now using this handle, we can stop/resume execution of the process (thereby stopping/resuming sending of packet) by calling suspend/resume method. We can have another piece of code where we can code the logic which will have the logic that shall control “WHEN” to send the packet.