0% found this document useful (0 votes)
20 views

UVM Notes

The document provides an overview of reporting mechanisms in UVM (Universal Verification Methodology), detailing various macros such as UVM_INFO, UVM_WARNING, and UVM_ERROR for communicating messages to the console. It explains the use of verbosity levels to control the output of messages and the importance of constructors in UVM components. Additionally, it covers how to manage logging, error handling, and the distinction between static and dynamic components within a UVM testbench environment.

Uploaded by

GH
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views

UVM Notes

The document provides an overview of reporting mechanisms in UVM (Universal Verification Methodology), detailing various macros such as UVM_INFO, UVM_WARNING, and UVM_ERROR for communicating messages to the console. It explains the use of verbosity levels to control the output of messages and the importance of constructors in UVM components. Additionally, it covers how to manage logging, error handling, and the distinction between static and dynamic components within a UVM testbench environment.

Uploaded by

GH
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 63

UVM NOTES

Anoushka Tripathi
Reporting mechanisms

UVM provides us multiple reporting mechanisms that can be use to communicate data to
console

SV

$display

$strobe

$monitor

UVM_INFO

We use it to send info to terminal

UVM_INFO(ID,MSG,redundancy level)

ID → which class is sending the data

MSG → Message which we have to send to the terminal.

Redundancy level→ default : 200

Multiple verbosity levels

Typedef enum

UVM_NONE =0,

UVM_LOW=100,

UVM_MEDIUM=200,

UVM_HIGH=300,

UVM_FULL=400,

UVM_DEBUG=500,

}UVM_verbosity;
To display message on Console : Simulator

Configure Verbosity >= `uvm_info Verbosity

Formats

UVM_WARNING(ID,MSG)

UVM_ERROR(ID,MSG)

UVM_FATAL(ID,MSG)

CODE

`include "uvm_macros.svh" //All definitions of MACROS

import uvm_pkg::*;//All definitions of classes

module tb;

initial begin

#50;

`uvm_info("TB_TOP","Hello World", UVM_LOW);

$display("Hello World with Display");

end

endmodule

Output
Sending values of variable to console

`include "uvm_macros.svh"

import uvm_pkg::*;

module tb;

int data = 56;

initial begin

`uvm_info("TB_TOP", $sformatf("Value of data : %0d",data), UVM_NONE);

end

Verbosity
Message id
level

endmodule

Output
Working with Verbosity level and ID

`include "uvm_macros.svh"
import uvm_pkg::*;

module tb;

initial begin

uvm_top.set_report_verbosity_level(UVM_HIGH);

$display("Default Verbosity level : %0d ", uvm_top.get_report_verbosity_level);

`uvm_info("TB_TOP", "String", UVM_HIGH);

end

endmodule

uvm_top : Default component which we will execute when we call a run test

Since verbosity level is set to UVM_MEDIUM, all verbosity level set below than UVM_MEDIUM
will send data to console anything higher than that will not be displayed.

This helps in changing default verbosity level

uvm_top.set_report_verbosity_level(UVM_HIGH);
UVM_ROOT is parent to all the classes that we add in UVM Testbench environment(UVM Tree)

Because UVM_ROOT returns a null pointer, we cannot directly access it. However, in a few

situations, we may need to access or configure the default settings of UVM_ROOT.

In such a case, UVM provides a global variable UVM_TOP which is accessible to all classes of

environment. UVM_TOP could be used whenever we need to work with the UVM root.
`include "uvm_macros.svh"

import uvm_pkg::*;

//////////////////////////////////////////////////

class driver extends uvm_driver; //we extend the uvm driver to create a uvm driver class, we can
override method as per requirement

`uvm_component_utils(driver)// we register a class to a factory


Path name/string type Allow us to create uvm tree

function new(string path , uvm_component parent);///whenever we extend a uvm component,


the constructor have 2 arguments

super.new(path, parent); // this is how we add a constructor to a child class

endfunction

task run();

`uvm_info("DRV1", "Executed Driver1 Code", UVM_HIGH);

`uvm_info("DRV2", "Executed Driver2 Code", UVM_HIGH);

endtask

endclass

///////////////////

module tb;

driver drv; //here we create a instance of driver, this is not required if we call a run test as run
test will automatically create an instance of component in build phase

initial begin PATH NAME, AS THIS IS A STRING WE HAVE USED “ “


drv = new("DRV", null);

drv.set_report_id_verbosity("DRV1",UVM_HIGH);//Change verbosity (first start with class


name), WE CAN HAVE DRV2 also here

drv.run();

end

endmodule

OUTPUT:
In the context of UVM (Universal Verification Methodology), the function new(string path,
uvm_component parent) is a constructor for a child class that extends a uvm_component. Let's
break down the parts:

1. Constructor Definition

function new(string path, uvm_component parent);

• new: This is the constructor function, used to create and initialize an instance of the
class.

• string path: This is typically the hierarchical path of the UVM component. It helps
uniquely identify the component in the UVM hierarchy.

• uvm_component parent: This is a reference to the parent component in the UVM


hierarchy. Each component in UVM has a parent unless it is the top-level component.

2. Calling the Parent Class Constructor

super.new(path, parent);

• super.new(path, parent): This calls the constructor of the parent class (which is also a
uvm_component), passing the path and parent arguments to ensure that the parent
class is properly initialized before the child class starts its own initialization. This is
required when extending any UVM component, as the base class (uvm_component)
needs to be set up with a name (path) and its hierarchical location (parent).

Why is this necessary?

Whenever you extend a uvm_component, you must ensure that the base class
(uvm_component) is initialized with proper arguments for its path and parent, which are
essential for building and managing the UVM testbench hierarchy.

In summary, this code is defining a constructor for a child class that extends uvm_component
and ensures that the parent class constructor is called to correctly initialize the component in
the UVM environment.
Super.new()

Will refer to base/parent class constructor

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

class parent; // parent/ base class property

int a;

function new (int b) ; // parent class constructor // default argument are i/p and logic type

a=b; // assign b to a

$display ("value of a is 40d", a);

endfunction: new

endclass: parent

class child extends parent;

function new(int c); // child class constructor default argument are i/p and logic type

super.now (c) ; // refer to the base/parent class constructor

endfunction: new

endclass: child

module eg () ;

child c1: // handle for child class

WORKING WITH INDIVIUAL COMPONENT:

Let us see if we have multiple components than how we will change the verbosity of individual
component
`include "uvm_macros.svh"

import uvm_pkg::*;

//////////////////////////////////////////////////

class driver extends uvm_driver;

`uvm_component_utils(driver)
function new(string path , uvm_component parent);

super.new(path, parent);

endfunction

task run();

`uvm_info("DRV1", "Executed Driver1 Code", UVM_HIGH);

`uvm_info("DRV2", "Executed Driver2 Code", UVM_HIGH);

endtask

endclass

//////////////////////////////////////////////////

class env extends uvm_env;

`uvm_component_utils(env)

function new(string path , uvm_component parent);

super.new(path, parent);

endfunction

task run();

`uvm_info("ENV1", "Executed ENV1 Code", UVM_HIGH);

`uvm_info("ENV2", "Executed ENV2 Code", UVM_HIGH);

endtask

endclass

////////////////////

module tb;
driver drv;

env e;

initial begin

drv = new("DRV", null); //add constructor for both driver and env

e = new("ENV", null);

e.set_report_verbosity_level(UVM_HIGH);//here we change the verbosity of env class

drv.run();

e.run();

end

endmodule

WORKING WITH HIERARCHY:

If we want to change the verbosity of entire hierarchy, than also we have a specific method for it

`include "uvm_macros.svh"

import uvm_pkg::*;

//////////////////////////////////////////////////

class driver extends uvm_driver;

`uvm_component_utils(driver)

function new(string path , uvm_component parent);

super.new(path, parent);

endfunction

task run();

`uvm_info("DRV", "Executed Driver Code", UVM_HIGH);

endtask
endclass

///////////////////////////////////////////////////

class monitor extends uvm_monitor;

`uvm_component_utils(monitor)

function new(string path , uvm_component parent);

super.new(path, parent);

endfunction

task run();

`uvm_info("MON", "Executed Monitor Code", UVM_HIGH);

endtask

endclass

//////////////////////////////////////////////////

class env extends uvm_env;

`uvm_component_utils(env)

driver drv;

monitor mon;

function new(string path , uvm_component parent);

super.new(path, parent);

endfunction
task run();

drv = new("DRV", this);//2nd argument is the parent component,env will serve as a parent for
both driver and monitor

mon = new("MON", this);

drv.run();//main task for both drv and env

mon.run();

endtask

endclass

////////////////////

module tb;

env e;

initial begin

e = new("ENV", null);

e.set_report_verbosity_level_hier(UVM_HIGH);

e.run();

end

endmodule
We have env class in which there is drv class
OUTPUT

ENV class is a parent class here Path of hierarchy

MON and DRV are the child class here


MORE REPORTING MACROS

`include "uvm_macros.svh"

import uvm_pkg::*;

//////////////////////////////////////////////////

class driver extends uvm_driver;

`uvm_component_utils(driver)

function new(string path , uvm_component parent);

super.new(path, parent);

endfunction

task run();

`uvm_info("DRV", "Informational Message", UVM_NONE);

`uvm_warning("DRV", "Potential Error");

`uvm_error("DRV", "Real Error");

#10;

`uvm_fatal("DRV", "Simulation cannot continue");

endtask

endclass

/////////////////////////////////////////////

module tb;

driver d;

initial begin

d = new("DRV", null);

d.run();

end

endmodule
SEVERITY OF MACROS
Functions are available to change the capability to change macros.

Override functions help us change the severity.

`include "uvm_macros.svh"

import uvm_pkg::*;

//////////////////////////////////////////////////

class driver extends uvm_driver;

`uvm_component_utils(driver)

function new(string path , uvm_component parent);

super.new(path, parent);

endfunction

task run();

`uvm_info("DRV", "Informational Message", UVM_NONE);

`uvm_warning("DRV", "Potential Error");

`uvm_error("DRV", "Real Error");

#10;
`uvm_fatal("DRV", "Simulation cannot continue DRV1");

#10;

`uvm_fatal("DRV1", "Simulation Cannot Continue DRV1");

endtask

endclass

/////////////////////////////////////////////

module tb;

driver d;

initial begin

d = new("DRV", null);

// d.set_report_severity_override(UVM_FATAL, UVM_ERROR);// we wish to change uvm fatal


severity to uvm error

// change the severity of all uvm fatal to uvm error

Output with this program line

d.set_report_severity_id_override(UVM_FATAL, "DRV", UVM_ERROR);

d.run();

end

endmodule
CHANGING ASSOCIATED ACTIONS OF MACROS

UVM_ACTION : this macro simply remove all the default actions associated with a reporting
macros.

UVM_DISPLAY: Allows to send report to standard terminal

UVM_LOG: helps to send message to log file

`include "uvm_macros.svh"

import uvm_pkg::*;

//////////////////////////////////////////////////

class driver extends uvm_driver;

`uvm_component_utils(driver)

function new(string path , uvm_component parent);

super.new(path, parent);

endfunction

task run();

`uvm_info("DRV", "Informational Message", UVM_NONE);

`uvm_warning("DRV", "Potential Error");


`uvm_error("DRV", "Real Error"); ///uvm_count

`uvm_error("DRV", "Second Real Error");

/*

#10;

`uvm_fatal("DRV", "Simulation cannot continue DRV1"); /// uvm_exit

#10;

`uvm_fatal("DRV1", "Simulation Cannot Continue DRV1");

*/

endtask

endclass

////////////////////////////////////////////

module tb;

driver d;

initial begin

d = new("DRV", null);

d.set_report_max_quit_count(3);

d.run();

end

endmodule

d.set_report_severity_action(UVM_INFO,UVM_NO_ACTION)

this helps us override the function of UVM_INFO, uvm_info message will not be sent to console

d.set_report_severity_action(UVM_INFO,UVM_NO_DISPLAY | UVM_EXIT)

With this command it will send data to console and also terminate the simulation

OUTPUT of this command

We will not get other output as UVM_EXIT was executed


d.set_report_severity_action(UVM_FATAL,UVM_NO_DISPLAY)

we have changed the action of uvm_fatal for the entire class

OUTPUT of this command

WORKING WITH quit_count and UVM_ERROR


By default UVM_ERROR is considered for a quit count

Helps in setting the maximum threshold for maximum error, as soon as we reach that threshold
we will exit the simulation.

`include "uvm_macros.svh"

import uvm_pkg::*;

//////////////////////////////////////////////////

class driver extends uvm_driver;

`uvm_component_utils(driver)

function new(string path , uvm_component parent);


super.new(path, parent);

endfunction

task run();

`uvm_info("DRV", "Informational Message", UVM_NONE);

`uvm_warning("DRV", "Potential Error");

`uvm_error("DRV", "Real Error"); ///uvm_count

`uvm_error("DRV", "Second Real Error");

/*

#10;

`uvm_fatal("DRV", "Simulation cannot continue DRV1"); /// uvm_exit

#10;

`uvm_fatal("DRV1", "Simulation Cannot Continue DRV1");

*/

endtask

endclass

/////////////////////////////////////////////

module tb;

driver d;

initial begin

d = new("DRV", null);

d.set_report_max_quit_count(3);//setting the threshold

d.run();

end

endmodule
WORKING WITH LOG FILE:
Here our agenda is to store data from console to a file

`include "uvm_macros.svh"

import uvm_pkg::*;

//////////////////////////////////////////////////

class driver extends uvm_driver;

`uvm_component_utils(driver)

function new(string path , uvm_component parent);

super.new(path, parent);

endfunction

task run();

`uvm_info("DRV", "Informational Message", UVM_NONE);

`uvm_warning("DRV", "Potential Error");

`uvm_error("DRV", "Real Error");

`uvm_error("DRV", "Second Real Error");

endtask

endclass

/////////////////////////////////////////////

module tb;

driver d;

int file;//we create a int variable which will store the file descriptor id

initial begin

file = $fopen("log.txt", "w");

d = new("DRV", null);

//d.set_report_default_file(file); //this will send all the data for which you have enabled
UVM_LOG,allows data from all severity to a single file
d.set_report_severity_file(UVM_ERROR, file);

// d.set_report_severity_action(UVM_INFO, UVM_DISPLAY|UVM_LOG);//we have to display


data as well as log data into file

// d.set_report_severity_action(UVM_WARNING, UVM_DISPLAY|UVM_LOG);

d.set_report_severity_action(UVM_ERROR, UVM_DISPLAY|UVM_LOG);

d.run();

#10;

$fclose(file);

end

endmodule

BASE CLASSES : UVM_OBJECT


STATIC COMPONENTS

Few components in testbench enviournment will be there for entire simulation such
components are referred to as static components.

1. Scoreboard
2. Monitor
3. Driver

Whereas each transaction have life,until we compare that with expected data such components
are dynamic components.

Static components are made using uvm_component

Dynamic components are made using uvm_object. All dynamic components will be built by
extending uvm_object

Transaction → uvm_sequence_item

Uvm_component is built by deriving uvm_object, so we get all the properties of uvm_object in a


uvm_component

UVM_ COMPONENT

➔ UVM_TREE
➔ Phases

All these are not with uvm_object


UVM PROVIDES AUTOMATION.

We can specify the method without describing the method

Instead of using these we can use our own methods and describe them as well these are the
do_methods.
In library the do_copy is specified with virtual extern that means we will have to specify how we
want to use do_copy.

CREATING CLASS
TYPICAL WAY OF CREATING COMPONENTS IN SYSTEM VERILOG

class first;

rand bit[3:0} data;

endclass

module tb;

first f;

initial begin

f=new();

f.randomize();

$display(“VALUE OF DATA :%d,” f.data);

end

endmodule
`include "uvm_macros.svh"

import uvm_pkg::*;

class obj extends uvm_object;//We create obj class by extending uvm_object

`uvm_object_utils(obj) //register a class to factory,this gives us capability to perform some of


method automatically,it help us to perform factory override

function new(string path = "obj");//add a constructor

super.new(path);

endfunction

rand bit [3:0] a;

endclass

module tb;

obj o;

initial begin

o = new("obj");

o.randomize();

`uvm_info("TB_TOP", $sformatf("Value of a : %0d", o.a), UVM_NONE);

end

endmodule
`include "uvm_macros.svh"

import uvm_pkg::*;

class obj extends uvm_object;//We create obj class by extending uvm_object

function new(string path = "obj");//add a constructor

super.new(path);

endfunction

rand bit [3:0] a;

` uvm_object_utils_begin(obj)

`uvm_field_int(a, UVM_DEFAULT):

` uvm_object_utils_end

endclass

module tb;

obj o;

initial begin

o = new("obj");

o.randomize();

o.print();

end
endmodule

OUTPUT

Change the radix of data on console

If we want to change the format in which data is display


o.print();

As here in o.print() we have not choosen any method here so by default it will use
uvm_table_printer

OUTPUT : Tree format data

ENUM,REAL
`include "uvm_macros.svh"

import uvm_pkg::*;

class obj extends uvm_object;

// `uvm_object_utils(obj)

typedef enum bit [1:0] {s0 , s1, s2, s3} state_type;//We are expecting 4 states of fsm, if we don’t
provide value to these states, it will take default values

rand state_type state; //variable which will be working for state type is state

real temp = 12.34;

string str = "UVM";

function new(string path = "obj");

super.new(path);

endfunction

`uvm_object_utils_begin(obj)

`uvm_field_enum(state_type, state, UVM_DEFAULT);

`uvm_field_string(str,UVM_DEFAULT);

`uvm_field_real(temp, UVM_DEFAULT);

`uvm_object_utils_end

endclass

module tb;
obj o;

initial begin

o = new("obj");

o.randomize();

o.print(uvm_default_table_printer);

end

endmodule

OUTPUT

We have initialized this in typedef enum

MACROS FOR A INSTANCE OF A CLASS:


`include "uvm_macros.svh"

import uvm_pkg::*;

class parent extends uvm_object;

function new(string path = "parent");

super.new(path);

endfunction

rand bit [3:0] data;

`uvm_object_utils_begin(parent)
`uvm_field_int(data,UVM_DEFAULT);

`uvm_object_utils_end

endclass

class child extends uvm_object;

parent p;

function new(string path = "child");

super.new(path);

p = new("parent");

endfunction

`uvm_object_utils_begin(child)

`uvm_field_object(p,UVM_DEFAULT);

`uvm_object_utils_end

endclass

module tb;

child c;

initial begin

c = new("child");

c.p.randomize();

c.print();

end

endmodule

If we use c.randomize we will perform randomization of only the child class

With c.randomize
With c.p.randomize

ARRAYS
MACRO FOR STATIC ARRAY
`include "uvm_macros.svh"

import uvm_pkg::*;

class array extends uvm_object;

////////static array

int arr1[3] = {1,2,3};

///////Dynamic array

int arr2[];

///////Queue

int arr3[$];

////////Associative array

int arr4[int];

function new(string path = "array");

super.new(path);
endfunction

`uvm_object_utils_begin(array)//registering array to factory

`uvm_field_sarray_int(arr1, UVM_DEFAULT);//for static array

`uvm_field_array_int(arr2, UVM_DEFAULT);

`uvm_field_queue_int(arr3, UVM_DEFAULT);

`uvm_field_aa_int_int(arr4, UVM_DEFAULT);

`uvm_object_utils_end

task run(); Data type

///////////////////Dynamic array value update

arr2 = new[3];//initialize size of array allocate space for array

arr2[0] = 2;

arr2[1] = 2;

arr2[2] = 2;

///////////////////Queue

arr3.push_front(3);

arr3.push_front(3);

////////////////////Associative arrays

arr4[1] = 4;

arr4[2] = 4;

arr4[3] = 4;

arr4[4] = 4;

endtask

endclass
////////////////////////////////////////////

module tb;

array a;

initial begin

a = new("array");

a.run();

a.print();

end

endmodule

OUTPUT

COPY CLONE METHOD:


`include "uvm_macros.svh"

import uvm_pkg::*;

class first extends uvm_object;


rand bit [3:0] data;

function new(string path = "first");

super.new(path);

endfunction

`uvm_object_utils_begin(first)

`uvm_field_int(data, UVM_DEFAULT);

`uvm_object_utils_end

endclass

////////////////////////////////////////////

module tb;

first f;

first s;

/*

initial begin

f = new("first");

s = new("second");

f.randomize();

s.copy(f);

f.print();

s.print();

end

*/

initial begin
f = new("first");

f.randomize();

$cast(s, f.clone());

f.print();

s.print();

end

endmodule

OUTPUT

Both instance have same data

Cloning
initial begin

f=new(“first”);

f.randomize():
s=f.clone(); //incompatibility type error

f.print();

s.print();

end

endmodule
Why are we getting incompatibility type error??

The return of f.clone() is a parent class which is a uvm_object type, whereas s is of first type i.e
derived type.

How do we correct it?

initial begin

f=new(“first”);

f.randomize():

$cast(s,f.clone());

f.print();

s.print();

end

endmodule

OUTPUT

SHALLOW COPY Vs DEEP COPY


Copying using copy constructor.

OUTPUT

We created d1 object

We copied the d1 data into d2,this is called as copy.

This is a shallow copy example


-copy constructor

-implicit copy assignment operator

Here we used the copy assignment operator

SHALLOW COPY

Creating copy of object by copying data of all member variables as it is.

We will create a pointer in same code


Now in set data we will pass 3 arguments
Now if we do shallow copy of d1 block to d2
If 2 pointers ,point to same resource that is not desirable,that is why memory resource for d2
and d1 should be separate.
DEEP COPY and SHALLOW COPY IN UVM
`include "uvm_macros.svh"

import uvm_pkg::*;

class first extends uvm_object;

rand bit [3:0] data;

function new(string path = "first");

super.new(path);

endfunction

`uvm_object_utils_begin(first)

`uvm_field_int(data, UVM_DEFAULT);

`uvm_object_utils_end

endclass

///////////////////////////////////////
class second extends uvm_object;

first f;

function new(string path = "second");

super.new(path);

f = new("first");

endfunction

`uvm_object_utils_begin(second)

`uvm_field_object(f, UVM_DEFAULT);

`uvm_object_utils_end

endclass

////////////////////////////////////////////

module tb;

second s1, s2; ///shallow

initial begin

s1 = new("s1");//adding constructor for both instance

s2 = new("s2");

s1.f.randomize();

s1.print();

s2 = s1;

s2.print();

s2.f.data = 12;
s1.print();

s2.print();

end

endmodule

……………………………………………………………………………………………………………………………

initial begin

s1 = new("s1");//adding constructor for both instance

s2 = new("s2");

s1.f.randomize();

s1.print();

s2=s1;

s2.print();

end

initial begin

s1 = new("s1");//adding constructor for both instance

s2 = new("s2");

s1.f.randomize();

s1.print();

s2=s1;

s2.print();

s2.f.data =12;
s1.print

end

COMPARE METHOD
`include "uvm_macros.svh"

import uvm_pkg::*;

class first extends uvm_object;

rand bit [3:0] data;

function new(string path = "first");

super.new(path);

endfunction

`uvm_object_utils_begin(first)

`uvm_field_int(data, UVM_DEFAULT);

`uvm_object_utils_end

endclass

////////////////////////////////////////////
module tb;

first f1,f2;

int status = 0;

initial begin

f1 = new("f1");

f2 = new("f2");

f1.randomize();

f2.copy(f1);

f1.print();

f2.print();

status = f1.compare(f2);

$display("Value of status : %0d", status);

end

endmodule

If comparison is miscompared
If both instance have same data

CREATE METHOD
`include "uvm_macros.svh"

import uvm_pkg::*;

class first extends uvm_object;

rand bit [3:0] data;

function new(string path = "first");

super.new(path);

endfunction

`uvm_object_utils_begin(first)

`uvm_field_int(data, UVM_DEFAULT);
`uvm_object_utils_end

endclass

////////////////////////////////////////////

module tb;

first f1,f2;

initial begin

f1 = first::type_id::create("f1");//this will create object for first class,standard method of


creating object in UVM

f2 = first::type_id::create("f2");

f1.randomize();

f2.randomize();

f1.print();

f2.print();

end

endmodule

OUTPUT

FACTORY OVERRIDE
What are the advantages we get when we register our class to factory and use create method for
creating our object

For this we consider a example

Let us assume we are working on a certain project,we have completed the development of
entire testbench env , In our second release we will add one more control signal in our
transaction in class,Instead of changing the existing transaction we will extend the transaction
class and add new signal to it,now our agenda is all the places where we use the old transaction
class we need to replace that with new transaction class.

Factory can help us handle this situation easily,

In the next release of this testbench we want to add ACK to this TB.

`include "uvm_macros.svh"

import uvm_pkg::*;

class first extends uvm_object;

rand bit [3:0] data;

function new(string path = "first");

super.new(path);

endfunction

`uvm_object_utils_begin(first)

`uvm_field_int(data, UVM_DEFAULT);

`uvm_object_utils_end

endclass

/////////////////////////////////////

class first_mod extends first; // first modification to tb made by extending the first class

rand bit ack; //we added ack,which we want to add to recent version of code

function new(string path = "first_mod");

super.new(path);

endfunction

`uvm_object_utils_begin(first_mod)

`uvm_field_int(ack, UVM_DEFAULT);
`uvm_object_utils_end

endclass

////////////////////////////////////////////

class comp extends uvm_component;

`uvm_component_utils(comp)//register class to factory

first f;

function new(string path = "second", uvm_component parent = null);

super.new(path, parent);

f = first::type_id::create("f");//creating object

f.randomize();

f.print();

endfunction

endclass

/////////////////////////////////////////////

module tb;

comp c;

initial begin

c = comp::type_id::create("comp", null); //create object of component

end

endmodule
We still did not get ack here

So to get it we will use

//c.set_type_override_by_type( first ::get_type, first_mod ::get_type);

New class with the changes we want to introduce

Class which we want to override

After doing this change to our testbench.

module tb;

comp c;

initial begin

c.set_type_override_by_type( first ::get_type, first_mod ::get_type);

c = comp::type_id::create("comp", null); //create object of component

end

endmodule
do_print method
1) If we plan to use do methods, Field Macros are not required but

registering class to factory is mandatory to get capabilities of Factory

Override.

2) If we plan to use inbuilt implementation of the core methods then

registering class to factory as well as adding field macros to the data

members is mandatory
//////////////////////////////////////////////

`include "uvm_macros.svh"

import uvm_pkg::*;
class obj extends uvm_object;

`uvm_object_utils(obj)

function new(string path = "OBJ");

super.new(path);

endfunction

bit [3:0] a = 4;

string b = "UVM";

real c = 12.34;

virtual function void do_print(uvm_printer printer);

Source of value
super.do_print(printer);

printer.print_field_int("a", a, $bits(a), UVM_HEX);//$bits calculate total number of bits

printer.print_string("b", b);

printer.print_real("c", c);
What we want to print

endfunction

endclass

module tb;

obj o;

initial begin

o = obj::type_id::create("o");

o.print();

end

endmodule
convert2string
display values of data in single line
`include "uvm_macros.svh"

import uvm_pkg::*;

class obj extends uvm_object;

`uvm_object_utils(obj)

function new(string path = "OBJ");

super.new(path);

endfunction

bit [3:0] a = 4;

string b = "UVM";

real c = 12.34;

virtual function string convert2string();

string s = super.convert2string();

s = {s, $sformatf("a : %0d ", a)};

s = {s, $sformatf("b : %0s ", b)};


s = {s, $sformatf("c : %0f ", c)};

////a : 4 b : UVM c : 12.3400

return s;

endfunction

endclass

module tb;

obj o;

initial begin

o = obj::type_id::create("o");

//$display("%0s", o.convert2string());

`uvm_info("TB_TOP", $sformatf("%0s", o.convert2string()), UVM_NONE);

end

endmodule

do_compare

`include "uvm_macros.svh"

import uvm_pkg::*;
class obj extends uvm_object;

`uvm_object_utils(obj)

function new(string path = "obj");

super.new(path);

endfunction

rand bit [3:0] a;

rand bit [4:0] b;

virtual function void do_print(uvm_printer printer);

super.do_print(printer);

printer.print_field_int("a :", a, $bits(a), UVM_DEC);

printer.print_field_int("b :", b, $bits(b), UVM_DEC);

endfunction

virtual function void do_copy(uvm_object rhs);

obj temp;

$cast(temp, rhs);

super.do_copy(rhs);

this.a = temp.a;

this.b = temp.b;

endfunction

endclass
module tb;

obj o1,o2;

initial begin

o1 = obj::type_id::create("o1");

o2 = obj::type_id::create("o2");

o1.randomize();

o1.print();

o2.copy(o1);

o2.print();

end

endmodule

You might also like