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

UVM - Reference Material

The document describes the Universal Verification Methodology (UVM). It introduces UVM and why a verification methodology is needed. It then provides an overview of earlier methodologies before focusing on UVM. Key aspects of UVM include universal verification components like agents, drivers, monitors and the environment. The document also describes the UVM class library and base classes used to build verification components.

Uploaded by

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

UVM - Reference Material

The document describes the Universal Verification Methodology (UVM). It introduces UVM and why a verification methodology is needed. It then provides an overview of earlier methodologies before focusing on UVM. Key aspects of UVM include universal verification components like agents, drivers, monitors and the environment. The document also describes the UVM class library and base classes used to build verification components.

Uploaded by

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

Universal Verification Methodology

(UVM)

Presenting by
Chanda Prasanthi
Introduction
Why we need Methodology?

⚫ Functional Verification consumes more that 60% of time and


effort in a product life cycle.

⚫ Engineers are constantly looking for new and better ways to


perform functional verification.

⚫ There are many proven and promising technologies for


enhanced verification such as coverage-based verification,
assertion-based verification, etc.

⚫ Now the issue is which one to choose and henceforth we require


a methodology which tells us what to do at what time.
What Methodology should provide?

⚫ The methodology should provide guidance on when, where and


what techniques to apply in order to achieve maximum
efficiency.

⚫ The methodology should provide basic building blocks, coding


guidelines and advice on reusing verification components.

⚫ It Should help in achieving better verification results as


measured by engineer productivity, schedule predictability and
profitability for the chip being verified.
Overview of Methodologies

eRM (e-Reuse Methodology) from Verisity.


2002 Provided rules for building reusable, consistent,
extensible and Plug and Play verification environments.

RVM (Reuse Verification Methodology) from Synopsis for


Vera verification language.
2003
It included base classes, message capabilities, packing
guidelines. Overtime was converted to VMM for SV.

AVM (Advanced Verification Methodology) from Mentor.


2006 It was first open source Verification solution.
Concept of TLM ports were adopted from SystemC to
communicate between Verification Components.
Overview of Methodologies

URM (Universal Reuse Methodology) from Cadence.


2007 Modified eRM with added features such as factory,
configuration and class automation for SV.

OVM (Open Verification Methodology) from Cadence


and Mentor.
2008
Provided multi-vendor verification solution. Integration of
multi-language testbenches was also added.

UVM (Universal Verification Methodology) from Mentor,


2010 Cadence and Synopsis.
Based on OVM proven library industry wide verification
methodology was created.
Universal Verification Components
UVM Test Bench

⚫ A UVM testbench is composed of reusable UVM-compliant


universal verification component (UVC).

⚫ A UVC is an encapsulated, ready to use and configurable


verification environment.

⚫ UVM Test Benches are layered and structured test benches,


where each structure has a specific role to play.
Universal Verification Components

⚫ A standard structure of UVC includes following elements:

o Data Items
✔ It represents stimulus transaction that are input to the DUT.
✔ In a test, many data items are generated and sent in to the DUT.
✔ Examples: Network Packets, Instructions.

o Driver (Bus Functional Model)


✔ It is an active entity which emulates logic that drives the DUT.
✔ A driver repeatedly pulls data items generated by sequencer and
drives it to DUT.
Universal Verification Components

o Sequencer
✔ It is an advance stimulus generator that generates and returns data
items upon request from the driver.
✔ A sequencer has an ability to react to the current state of DUT and
generate more useful data items by changing randomization weights.

o Monitor
✔ It is a passive entity that samples DUT signals but does not drive them.
✔ They are useful in collecting coverage and checking performance.
✔ It can also be used to predict result based on sampled inputs and
verifying them against sampled outputs.
Universal Verification Components

o Agent
✔ They are used to encapsulate driver, sequencer and monitor.
✔ An UVC can contain more than one agent.
✔ Different agents can be used to target different protocols in an
SOC based example.
✔ Agents can be configured as active and passive.
✔ Active agents are one which emulates devices and drives DUT’s
ports.
✔ Passive agents only monitors DUT activity.
Universal Verification Components

o Environment
✔ It is top-level component of an UVC.
✔ It can contain one or more agents.
✔ It can also contain Score Boards that are used to perform
end-to-end transmission checks or perform checks against
reference models.
Test Bench Hierarchy
Test Bench Hierarchy

Top Test Score Board Env


Config

A1 A2
Sq S C S C

D M1 D M2

DUT
UVM Class Library
UVM Library

⚫ The UVM library provides all the building blocks that we


require to build modular, scalable, reusable, verification
environments.

⚫ This library contains base classes, utilities and macros to support


the entire verification process.

⚫ In order to use UVM Library, user needs to:


o Compile uvm_pkg.sv file.
o Import uvm_pkg into the desired scope.
o Include file that contains uvm macros.
Hello World

`include “uvm_pkg.sv”
//include for compiling if not available by default
import uvm_pkg :: *;
//importing definitions inside uvm_pkg

module hello_world;
initial
`uvm_info(“info1”, “Hello World”, UVM_LOW);
endmodule
UVM Library : Base Classes

uvm_void

uvm_object
Copy(), print() etc uvm_transaction

uvm_report_object uvm_sequence_item

uvm_component
all phases uvm_sequence
task body()
user component
uvm_test, uvm_env
etc
Features of Base Classes

⚫ uvm_void class is the base class for all UVM classes. It is an


abstract class with no data members or functions.

⚫ uvm_object class is the base class for all UVM data and
hierarchical classes.
o Defines set of methods for common operations such as create,
copy, compare, print, etc.
Features of Base Classes

⚫ uvm_transaction class is base class for all UVM Transactions.


o It inherits all features of uvm_object.
o Use of this class is depreciated and instead of using this class,
it’s subtype uvm_sequence_item should be used.

⚫ uvm_report_object class provides an interface to UVM reporting


facility.
o It allows UVM Components to issue various messages during
simulation time.
Features of Base Classes

⚫ uvm_component is the base class for all UVM Components.


o Components are quasi-static objects that exists throughout the
simulation.
o This class inherits features from both uvm_object and
uvm_report_object.
o In addition it provides following features:
✔ Hierarchy, searching and traversing component hierarchy.
✔ Phasing, defines test flow of all the components.
✔ Configuration, allows configuring component topology.
✔ Factory, for creating and overriding components.
UVM Object
uvm_object methods

⚫ Following are important methods defined inside uvm_object class.

o new() create new uvm_object for a given instance.

function new (string name=“ ”)

o set_name() set/override instance name of this object.

virtual function void set_name (string name)

o get_name() returns the name of the object

virtual function string get_name()


uvm_object methods

o get_full_name() returns full hierarchal name of this object

virtual function string get_full_name()


uvm_object methods

o create() allocates a new object as same type as this object and


returns it via base uvm_object_handler.

virtual function uvm_object create(string name=“ ”)

class my_object extends uvm_object;


function uvm_object create (string name=“ ”);
my_object = new (name);
return my_object;
endfunction
………….
endclass
uvm_object methods

o copy() method makes this object a copy of other object.


✔ copying is same as deep copy.
✔ copy method should not be overridden in derived class.

function void copy (uvm_object rhs)

o clone() method creates and returns the exact copy of this


object.
virtual function uvm_object clone()
uvm_object methods

o print() method performs deep print of object properties in a


format governed by its argument.
Example1

typedef enum bit [1:0] {READ, WRITE, RD_WR, NOP} direction;

class mem_transaction extends uvm_object;


rand bit [7:0] data; //data
rand bit [3:0] addr; //address
rand direction dir; //direction

//Control field (Knob)


rand bit [3:0] delay; //delay between transactions

………………….…… //on Next slide


endclass
Example1

//Registering user class to UVM Factory and including given


//field in implementation of print, copy, etc
`uvm_object_utils_begin (mem_transaction)
`uvm_field_int (data, UVM_DEFAULT)
`uvm_field_int (addr, UVM_DEFAULT)
`uvm_field_enum (direction, dir, UVM_DEFAULT)
`uvm_field_int (delay, UVM_DEFAULT | UVM_NOCOMPARE)
`uvm_object_utils_end

//Class constructor
function new (string name=“mem_transaction”);
super.new(name);
endfunction
Example2

module top;
import uvm_pkg:: *; //importing UVM Library
`include “uvm_macros.svh” //including UVM Macros
`include “mem_transaction.sv” //including user-defined class

mem_transaction a1, a2, a3;

initial begin
a1=mem_transaction :: type_id :: create(“a1”);
//creating object using factory create method, which supports
//overriding, using new will restrict overriding
…………………………………. //On Next slide
endmodule
Example2

assert(a1.randomize()) else
`uvm_fatal(“RFAIL”, “Randomization Failed”)
a2=mem_transaction :: type_id :: create(“a2”);
a2.copy(a1); //copy a1 to a2
$cast(a3, a1.clone()); //create new object of type a1
//and then copy to a3
if(!a3.compare(a2))
`uvm_error(“CFAIL”, “Comparison Failed”)
a1.print();
a2.print(default_line_printer);
a3.print(default_line_printer);
end
Result

Table Printer :
# -------------------------------------
# Name Type Size Value
# -------------------------------------
# a1 mem_transaction - @457
# data integral 8 'h50
# addr integral 4 'he
# dir direction 2 READ
#delay integral 4 'hb
# -------------------------------------
Result

Tree Printer :
# a2: (mem_transaction@458) {
# data: 'h50
# addr: 'he
# dir: READ
# delay: 'hb
#}

Line Printer :
# a1: (mem_transaction@459) { data: 'h50 addr: 'he dir: READ
delay: 'hb }
uvm_transaction

uvm_transaction

uvm_sequence_item

uvm_sequence
uvm_sequence methods

⚫ uvm_sequence class provides the interfaces to create streams of


sequence items or other sequences.
o start() executes the given sequence on a sequencer and returns
once sequence is over.
o pre_body() is user-defined callback which is called before
execution of body only if sequence is started using start.
o body() is user-defined task where the main sequence code resides.
o post_body() is user-defined callback which is called after
execution of body only if sequence is started using start.
uvm_sequence methods

virtual task start ( uvm_sequencer_base sequencer,


uvm_sequence_base parent_sequence = null,
int this_priority = -1,
bit call_pre_post = 1 )

✔ sequencer: specifies the sequencer on which the given sequence


runs.
uvm_sequence methods

o create_item() will create and initialize a sequence or sequence


item using the factory.

o start_item() and finish_item() are used together to initiate


operation of a sequence item.

o Body of a sequence contains following in given order:


✔ start_item()
✔ create sequence item using factory.
✔ Randomize sequence item (useful for late randomization)
✔ finish_item()
UVM Component
uvm_component

⚫ All the infrastructure components in a UVM verification environment


(like monitor, driver, agent, etc.) are derived from uvm_component.

⚫ This component class is quasi-static in nature and object creation is


not allowed after build_phase.

⚫ Key functionality provided by uvm_component class are:


o Phasing and Execution control.
o Hierarchy information function.
o Configuration methods.
o Factory convenience methods.
o Hierarchal reporting control.
uvm_component

uvm_component

uvm_agent uvm_root uvm_env

uvm_driver uvm_sequencer uvm_monitor

uvm_test uvm_scoreboard uvm_subscriber


Example1

class my_component extends uvm_component;

//Registering user-defined class to UVM Factory


`uvm_component_utils (my_component)

//Constructer for UVM Components


function new (string name, uvm_component parent);
super.new(name, parent);
endfunction

//some additional properties and methods


endclass
uvm_root and uvm_top

⚫ The uvm_root class serves as the implicit top-level and phase


controller for all UVM components.
⚫ UVM automatically creates a single instance of uvm_root called
uvm_top.
⚫ uvm_top manages phasing for all UVM components.
⚫ uvm_top can be to globally configure report verbosity and as a
global reporter.
Features of uvm_root

⚫ Following are few methods and variables defined inside


uvm_root.
o run_test() phases all the components through all the registered
phases.
✔ Test name can be passed as an argument or can be part of
command line argument +UVM_TESTNAME=TEST_NAME

virtual task run_test (string test_name = "")

o top_levels variable contains the list of all top level components


in UVM. It includes uvm_test_top variable that is created by
run_test.
Features of uvm_root

o print_topology() prints the verification environment’s component


topology.

function void print_topology (uvm_printer printer = null)


UVM Factory
UVM Factory

⚫ uvm_factory (UVM Factory) is a class which is used to create UVM


objects and components .

⚫ Only one instance of UVM Factory can exist during entire simulation
(singleton).

⚫ User defined objects and components can be registered with the


factory via typedef or macros invocation.
Registering with Factory

⚫ Non-Parameterized Objects:
class packet extends uvm_object;
`uvm_object_utils(packet)
endclass

⚫ Parameterized Objects:
class packet #(type T=int, int Width=32)extends uvm_object;
`uvm_object_param_utils(packet #(T, Width))
endclass
Registering with Factory

⚫ Non-Parameterized Components:
class comp extends uvm_component;
`uvm_component_utils(comp)
endclass

⚫ Parameterized Components:
class comp #(type T=int, int Width=32) extends
uvm_component;
`uvm_component_param_utils(comp #(T, Width))
endclass
UVM Field Macros

⚫ `uvm_field macro includes the given field in implementation of


print(), copy(), clone(), pack(), unpack(), compare() and record()
methods for an object.
`uvm_field_* (field_name, flags)

⚫ field_name must be an existing property identifier of the class.

⚫ flags specifies the automation required for a field.

⚫ Flags are numeric values and can be combined using bitwise OR


or + operator.
UVM Field Macros

Macros Implements operations for

`uvm_field_int any packed integral property

`uvm_field_string a string property

`uvm_field_enum an enumerated property

`uvm_field_real any real property

`uvm_field_object an uvm_object-based property

`uvm_field_event an event property


UVM Field Macros

Macros Implements operations for

`uvm_field_array_int()
`uvm_field_array_object() Dynamic and Static Arrays
`uvm_field_array_string()

`uvm_field_queue_int()
`uvm_field_queue_object() Queues
`uvm_field_queue_string()
Flag Arguments

Flags Description
UVM_ALL_ON Set all operations on (default)
UVM_DEFAULT Use the default flag settings
UVM_NOCOPY Do not copy this field
UVM_NOCOMPARE Do not compare this field
UVM_NOPRINT Do not print this field
UVM_NODEFPRINT Do not print the field if it does not change
UVM_NOPACK Do not pack or unpack this field
UVM Phases
Why we require Phases

⚫ In Verilog and VHDL, static elaboration of instances occur before


simulation starts.
⚫ This ensures that all instances are placed and connected properly
before simulation starts.
⚫ In System Verilog classes are instantiated at run-time.

⚫ This leads to questions like what is the good time to start data
generation and transfer, assuming all UVC components have been
created and connected properly.
⚫ UVM Provides concept of Phases to solve this issue. Each phase has
a defined order of execution.
Phases in UVM

Build Connect End of Elaboration

Start of Simulation

Run

Extract

Final Report Check


Execution of Phases

0 Time End of Simulation

build_phase()
connect_phase() extract_phase()
end_of_elaboration_phase() check_phase()
start_of_simulation_phase() report_phase()
run_phase() final_phase()

Pre Run Phases Time Consuming Phase Post Run Phases

Time Consumed: 0 Time Consumed: 0


build_phase

⚫ build_phase is called for all the uvm_components in a Top-down


fashion.

⚫ This method is used to optionally configure and then create child


components for a given components.

⚫ If components are created after build phase then UVM will


generate error message.

⚫ Configuration settings for descendant components should be set


before calling create methods.
Example

class myagent extends uvm_agent;


mydriver dr;
…………… //component registration and constructor

function void build_phase (uvm_phase phase);


super.build_phase(phase);
dr=mydriver::type_id::create(“driver”, this);
endfunction
endclass
connect_phase

⚫ Connect phase executes in Bottom-Up fashion.

⚫ This phase is used to specify connection between UVC’s.

⚫ Use connect_phase method to make TLM Connections, assign pointer


references, and make virtual interface assignments.

⚫ Components are connected using TLM Ports.


Example

class myagent extends uvm_agent;


mydriver dr;
mysequencer sq;
…………… //component registration and constructor

function void connect_phase (uvm_phase phase);


super.connect_phase(phase);
dr.seq_item_port.connect(sq.seq_item_export);
endfunction
endclass
end_of_elaboration_phase()

⚫ This phase can be used to examine whether all connections and


references defined in connect phase are proper and complete.

⚫ This phase executes in Bottom-Up fashion.

function void end_of_elaboration_phase(uvm_phase phase);


super.end_of_elaboration_phase(phase);
uvm_top.print_topology();
endfunction
start_of_simulation_phase()

⚫ This phase can be used for displaying banners, test bench topology
or configuration messages.

⚫ This phase executes in Bottom-Up fashion.

function void start_of_simulation_phase(uvm_phase phase);


super. start_of_simulation_phase(phase);
`uvm_info(“info”, “start of simulation”, UVM_LOW)
endfunction
run_phase()

⚫ run_phase is a time consuming task.

⚫ All run phases are executed in parallel.

⚫ Run phase is used inside driver , monitor and test.

⚫ Run phase is further divided in 12 sub-phases.


Example

class driver extends uvm_driver;


…………… //component registration and constructor

task run_phase (uvm_phase phase);


super.run_phase(phase);
repeat(10) begin
@(posedge vif.clk) vif.data<=$random;
end
endtask
endclass
run phase – sub phases

Pre Reset
Reset
Post Reset

Pre Configure
Configure
Post Configure

Pre Main
Main
Post Reset

Pre Shutdown
Shutdown
Post Shutdown
Phase Synchronization

⚫ All components allow other components to complete a phase


before they proceed to next phase.
Component1
Reset Configure Main Shutdown

Component2

Reset Configure Main Shutdown

Component3
Reset Configure Main Shutdown
Post run Phases

⚫ extract_phase() is used to retrieves and processes information from


scoreboards and functional coverage monitors. This phase executed
in Bottom-Up fashion.

⚫ check_phase() checks if the DUT behaved correctly and identifies


errors that may have occurred during the execution. This phase
executed in Bottom-Up fashion.

⚫ report_phase() displays the result of the simulation. This phase


executed in Bottom-Up fashion

⚫ final_phase() completes any other outstanding actions. This phase


executed in Top-Down fashion.
END OF TEST
Objection

⚫ Components can raise and drop objections.

⚫ A component that raises objection remains in same phase till all the
objections are dropped.

⚫ Raising and dropping of objection is done in run phases.

⚫ Usage:
o phase.raise_objection(this); //to raise objection in this object
o phase.drop_objection(this); //to drop objection in this object
Example

class agent extends uvm_agent; class driver extends uvm_driver;


task run_phase(uvm_phase phase); task run_phase(uvm_phase phase);
phase.raise_objection(this); phase.raise_objection(this);
#100; //do some work #10;
phase.drop_objection(this); phase.drop_objection(this);
endtask endtask
endclass endclass

run extract check

0 100
REPORTING MECHANISM
Messaging and Reporting

⚫ uvm_report_object class provides set of methods that can be used


to report messages in order to facilitate debugging.

⚫ Severity of messages could be


o Info
o Warning
o Error
o Fatal

⚫ User can filter out messages depending upon there importance.


Reporting Methods

virtual function void uvm_report_info ( string id,


string message,
int verbosity=UVM_MEDIUM,
string filename=“ ”,
int line=0);

o id is user defined string id given to message.


o message is user defined message.
o verbosity defines importance of message for filtering purpose.
o filename and line are optional arguments are used to report
location from which report was issued.
Reporting Methods

virtual function void uvm_report_warning ( string id,


string message,
int verbosity=UVM_MEDIUM,
string filename=“ ”,
int line=0);

virtual function void uvm_report_error ( string id,


string message,
int verbosity=UVM_LOW,
string filename=“ ”,
int line=0);
Reporting Methods

virtual function void uvm_report_fatal ( string id,


string message,
int verbosity=UVM_NONE,
string filename=“ ”,
int line=0);

⚫ `__FILE__ and `__LINE__ are predefined macros to get file name and
line number.

⚫ Use them as an argument to automatically display filename and line


on which report was encountered.
UVM Macros

`uvm_info(id, message, verbosity)


`uvm_warning (id, message)
`uvm_error (id, message)
`uvm_fatal (id, message)

⚫ UVM_NONE is verbosity for warning, error and fatal.

⚫ UVM recommends usage of UVM Macros over UVM reporting


methods.
Example

`uvm_info ( “DRIVER”, “Driver Data”, UVM_MEDIUM);

Output:

severity time scope id message body

UVM_INFO @50 uvm_test_top.tb.driver [DRIVER] Driver Data


Verbosity Settings

⚫ The verbosity level is an integral value to indicate the relative


importance of the message.

⚫ If verbosity value is smaller or equal to current verbosity level, then


report is issued.

⚫ For example if current verbosity level is set to 100 then messages


with verbosity 101 or higher won’t be printed.

⚫ An enumerated type verbosity provides some standard verbosity


levels UVM_NONE=0, UVM_LOW=100, UVM_MEDIUM=200,
UVM_HIGH=300, UVM_FULL=400, UVM_DEBUG=500.
Example

`uvm_info ( “1”, “Verbosity MEDIUM”, UVM_MEDIUM);


`uvm_info ( “2”, “Verbosity LOW”, UVM_LOW);
`uvm_info ( “3”, “Verbosity NONE”, UVM_NONE);

myobject a;
initial begin
a=new(“a”);
a.set_report_verbosity_level (UVM_LOW); //set verbosity level
end

Output:
UVM_INFO @0 : [2] Verbosity LOW
UVM_INFO @0 : [3] Verbosity NONE
TLM Ports
TLM

⚫ In UVM transaction is a class that extends from uvm_sequence_item.

⚫ A transaction typically contains sufficient data fields to enable


driver or transactor to create the actual signal-level activity.

⚫ A transaction may contain additional data fields to control how


randomization occurs.

⚫ TLM stands for Transaction Level Modeling.

⚫ TLM promotes reuse and interoperability for mixed-language


verification environments
TLM

⚫ TLM API provides set of methods that are used to communicate


transaction between components.

⚫ There are three basic types of TLM Objects:


o Port: A port object specifies set of methods that can be called
like get(), put(), peek(), etc. (Symbol : )
o Export: Export port are used to forward implementation of a
method. (Symbol : )
o Imp: Imp port provides implementation of these methods.
(Symbol : )

⚫ Ports and Exports/Imp are connected together via connect() method


where verification environment are constructed.
Blocking PUT port

Producer Consumer

⚫ Producer calls the put method and sends transaction (object)


to TLM port.

⚫ Consumers implements put method, receives transaction


using TLM imp.

⚫ Component that initiates transaction uses TLM port.


Example - Transaction

class packet extends uvm_sequence_item;


rand bit [3:0] src_addr, dst_addr;
rand bit [7:0] data;
constraint addr_constraint {src_addr != dst_addr;}
`uvm_object_utils_begin(packet)
`uvm_field_int(src_addr, UVM_DEFAULT)
`uvm_field_int(dst_addr, UVM_DEFAULT)
`uvm_field_int(data, UVM_DEFAULT)
`uvm_object_utils_end
//constructor not mentioned here
endclass
Example – Producer (Put)

class producer extends uvm_component;


uvm_blocking_put_port #(packet) put_port; //defining put port

packet p;

`uvm_component_utils(producer)

function new (string name, uvm_component parent);


super.new(name, parent);
put_port= new(“put_port”, this);
endfunction
Example – Producer (Put)

task run_phase (uvm_phase phase);


repeat(10)
begin
p=new();
p.randomize;
put_port.put(p);
end
endtask

endclass
Example – Consumer (Put)

class consumer extends uvm_component;


uvm_blocking_put_imp #(packet, consumer) put_export;
//defining imp port

`uvm_component_utils(consumer)

function new (string name, uvm_component parent);


super.new(name, parent);
put_export= new(“put_export”, this);
endfunction
Example – Consumer (Put)

task put (packet p);


`uvm_info(“packet”, “packet received”, UVM_LOW)
p.print();
endtask

endclass
Blocking GET port

Producer Consumer

⚫ Consumer calls the get method and receives transaction


using TLM port.

⚫ Producer implements get method and sends generated


transaction using TLM imp.

⚫ Component that initiates transaction uses TLM port.


Example – Producer (Get)

class producer extends uvm_component;


uvm_blocking_get_imp #(packet, producer) get_export;
//defining get imp

`uvm_component_utils(producer)

function new (string name, uvm_component parent);


super.new(name, parent);
get_export=new(“get_export”, this);
endfunction
Example – Producer (Get)

task get (output packet p);


packet temp;
temp=new();
temp.randomize;
p=temp;
endtask

endclass
Example – Consumer (Get)

class consumer extends uvm_component;


uvm_blocking_get_port #(packet) get_port; //defining get port

`uvm_component_utils(consumer)

function new (string name, uvm_component parent);


super.new(name, parent);
get_port=new(“get_port”, this);
endfunction
Example – Consumer (Get)

task run_phase (uvm_phase phase);


repeat(10)
begin
packet p;
get_port.get(p);
p.print;
end
endtask

endclass
Connecting TLM Ports

⚫ When we are connecting components that lie in same level of


hierarchy, then ports are always connected to exports.

⚫ All connection call between components is done in parent’s connect


phase.

Get Producer Get Consumer


get_imp get_port

Put Producer Put Consumer


put_port put_imp
Example

class agent extends uvm_agent;


get_producer get_prod; //Get Components
get_consumer get_cons;

put_producer put_prod; //Put Components


put_consumer put_cons;

function void connect_phase (uvm_phase phase);


get_cons.get_port.connect(get_prod.get_imp);
put_prod.put_port.connect(put_cons.put_imp);
endfunction
endclass
Blocking vs. Non-Blocking

⚫ uvm_blocking_get_port/uvm_blocking_put_port provides set of


blocking methods that blocks the process if target is not ready:
o put()
o get()
o peek()

⚫ uvm_non_blocking_get_port/uvm_non_blocking_put_port provides
set of methods that returns immediately even if target is not ready:
o try_put()
o try_get()
o try_peek()
TLM FIFO

⚫ In certain situations we want to connect a get consumer to a put


producer.

⚫ In such cases we use TLM FIFO. These are verification component


independent of implementation.

⚫ They contain all TLM interface methods like put, get, peek etc.

Producer TLM FIFO Consumer

⚫ Producer puts transaction in uvm_tlm_fifo where as consumer gets


transaction from the fifo.
Example

class fifo_example extends uvm_component;


get_consumer get_cons; //Consumer of get type
put_producer put_prod; //Producer of put type

uvm_tlm_fifo #(packet) fifo_inst; //TLM FIFO declaration

function new (string name, uvm_component parent);


super.new(name, parent);
put_prod=new(“producer”, this); //using create is recommended
get_cons=new(“consumer”, this);
fifo_inst=new(“fifo_inst”, this, 16); //set fifo depth to 16
endfunction
Example

function void connect_phase(uvm_phase phase);


put_prod.put_port.connect(fifo_inst.put_export);
get_cons.get_port.connect(fifo_inst.get_export);
endfunction

endclass
Analysis port and export

⚫ While using put and get method, it is mandatory to connect them to


exactly one export/imp before simulation starts.

⚫ UVM will report errors if ports are left unconnected.

⚫ In certain cases (like in monitors) we require a port that can either


be left unconnected or connected to one or more components.

⚫ In UVM, Analysis ports are serves this purpose. Symbol ( ).

⚫ Analysis port has a single non-blocking write function that can be


called with single transaction argument.
Analysis port and export

⚫ When write method of analysis port is called, analysis port calls


write method of every connected analysis exports.

⚫ uvm_subscriber class contains inbuilt analysis export and pure virtual


function called as write, Hence it become compulsory for derived
class to provide implementation for write.

Subscriber Subscriber

Consumer
Analysis port

class monitor extends uvm_component;


uvm_analysis_port #(packet) analysis_port;
function new (string name, uvm_component parent);
super.new(name, parent);
analysis_port=new(“analysis_port”, this);
endfunction
virtual task run ();
packet p=new;
…….//collect packet from lower level
analysis_port.write(p); //write collected transaction
endtask
endclass
Analysis export

class checker extends uvm_component;


uvm_anaysis_imp #(packet, checker) analysis_export;

function new (string name, uvm_component parent);


super.new(name, parent);
analysis_export=new(“analysis_export”, this);
endfunction

function void write (packet p);


//perform some check on packet p
endfunction
endclass
Analysis FIFO

⚫ Sometimes transactions that are passed through analysis port


cannot be processed immediately.

⚫ In such case the transaction needs to stored before they are


consumed.

⚫ Example scoreboard needs to compare actual packet coming from


DUT with expected packet coming from a reference model.

⚫ uvm_tlm_analysis_fifo is used to address this requirement. It has an


analysis_export that can be directly connected to analysis ports.

⚫ Analysis fifo has unbound size so that write always succeed.


Example Usage

Score Board

Analysis FIFO

Monitor Reference Model


UVM CONFIGURATION
Factory Overriding

⚫ UVM factory has the ability to substitute a child class with another
class of a derived type when it is constructed.

⚫ This helps in changing the behavior of test bench by substituting


one class for another without editing or re-compiling the code.

⚫ There are two types of overriding :


o set_type_override_by_type used for overriding type i.e.
global override.
o set_inst_override_by_type used for overriding an instance i.e.
instance override.
Usage

set_type_override_by_type ( original_type :: get_type(),


substitute_type :: get_type(),
replace = 1);
set_inst_override_by_type ( “path”,
original_type :: get_type(),
substitute_type :: get_type(),
replace = 1);
ooriginal_type is name of the component that has to be replaced.
o substitute_type is name of the component by which original has to
be replaced.
opath refers to the hierarchal position of the component.
oreplace specifies whether to replace definition in factory or not.
Example

Test

Env

Agent1 (UART) Agent2 (UART)

Driver Monitor Sequencer Driver Monitor Sequencer


Global Override

class env extents uvm_env;

function void build_phase (uvm_phase phase);


super.build_phase (phase);
set_type_override_by_type ( UART :: get_type(),
SPI :: get_type());
//Both UART and SPI classes are registered with UVM Factory
…………
endfunction
endclass
Result

Test

Env

Agent1 (SPI) Agent2 (SPI)

Driver Monitor Sequencer Driver Monitor Sequencer


uvm_config_db

⚫ set_config methods discussed earlier are depreciated method for


setting and getting configuration fields.

⚫ UVM provides Configuration Database class to set integers, strings,


virtual interfaces, objects etc resources with hierarchal context.

⚫ All functions in uvm_config_db #(type T) are static in nature and


can be accessed with help of scope resolution operator(::).
uvm_config_db : set method

uvm_config_db #(type T) :: set ( cntxt,


“inst_name”,
“field_name”,
value);

o type is used to specify type of field.


o cntxt is a prefix added to instance name, if null then instance name
provides complete scope of setting.
o inst_name is the place from which setting will be affected.
o field_name is the name of parameter to be updated.
o value is the updated value for the given field_name.
uvm_config_db : get method

assert ( uvm_config_db #(type T) :: get ( cntxt, “inst_name”,


“field_name”, value) );

o get method returns the status for availability of field.


o cntxt is used to provides starting of search point.
o inst_name is name of instance where the field is available, can be
null if cntxt is the instance name.

⚫ Example
uvm_config_db #(bit) :: set(this, “*.ag[1].*”, “is_active”, 1);
void’ ( uvm_config_db #(bit) :: get(this, “ ”,“is_active”, is_active));
Example - Env

class env extents uvm_env;


agent ag [2];
……….
function void build_phase (uvm_phase phase);
super.build_phase(phase);
uvm_config_db #(bit) :: set(null, “*.ag[0].*”, “is_active”, 1);
uvm_config_db #(bit) :: set(null, “*.ag[1].*”, “is_active”, 0);
ag[0]=agent :: type_id :: create(“ag[0]”, this);
ag[1]=agent :: type_id :: create(“ag[1]”, this);
endfunction
endclass
Example - Agent

class agent extents uvm_agent;


bit is_active;

monitor mon;
driver dvr;
sequencer sqr;

`uvm_component_utils(agent)

……………//On Next Slide


endclass
Example - Agent

function void build_phase (uvm_phase phase);


super.build_phase (phase);
void’ ( uvm_config_db #(bit) :: get (this, “ ”,“is_active”, is_active));
if(is_active==1)
begin
dvr= driver :: type_id :: create(“dr”, this);
sqr= sequencer :: type_id :: create(“sqr”, this);
end
mon= monitor :: type_id :: create(“mon”, this);
endfunction
Example – Virtual Interface (Top)

module top;
mem_inf i0 (clk); //Memory interface
mem_dut u0 (i0); // DUT instance

initial begin
uvm_config_db #(virtual mem_inf) :: set (null, “*", “mem_vif”, i0);
//registering virtual interface with all components(*) using mem_vif
//as the field name
run_test(); //calling uvm_top.run_test();
end
endmodule
Example – Virtual Interface (Driver)

class mem_driver extends uvm_driver;


virtual mem_if vif;

function void build_phase(uvm_phase phase);


super.build_phase(phase);
if(! uvm_config_db #(virtual mem_inf) :: get(this, “ ”, “mem_vif”, vif))
`uvm_fatal(“Vif Error”, “cannot locate mem_vif in config database”);
endfunction

task run_phase(uvm_phase phase); …………


endtask
endclass
uvm_resource_db

⚫ uvm_resource_db is a depreciated class that offer functionality


similar to that of uvm_config_db.

uvm_resource_db#(type T) :: set ( “scope”, “field_name”, value);


uvm_resource_db#(type T) :: get_by_name( “scope”,
“field_name”, value));
o scope is the lookup parameter
o field_name is the parameter to be updated
o value is the value or object to update the field_name

⚫ If same thing is written at multiple places in the hierarchy then last


write wins. UVM recommends usage of uvm_config_db.
Creating Components (Adder)
Test Bench Hierarchy

Top
Test

Env

Agent

Sequence Sequencer Driver Monitor


(Checking)
Virtual Interface
Interface
DUT
Test Bench - Interface

Top
Test

Env

Agent

Sequence Sequencer Driver Monitor


(Checking)
Virtual Interface
Interface
DUT
Adder- Interface

interface adder_inf (input bit clk);


logic [3:0] a, b; //inputs a and b
logic c; //input c
logic [4:0] sum; //output sum

modport DUT (output sum, input a, b, c, clk);


//Defining direction of signals

endinterface
Test Bench - DUT

Top
Test

Env

Agent

Sequence Sequencer Driver Monitor


(Checking)
Virtual Interface
Interface
DUT
Adder- DUT

module adder (adder_inf.DUT inf);

always @(posedge inf.clk)


inf.sum<= inf.a + inf.b + inf.c;
//Definition of adder

endmodule
Test Bench – TOP

Top
Test

Env

Agent

Sequence Sequencer Driver Monitor


(Checking)
Virtual Interface
Interface
DUT
Adder - Top

module top;
import uvm_pkg :: *; //import UVM package
`include “uvm_macros.svh” //include UVM macros
`include “myfiles.sv” //include user defined file

bit clk;
adder_inf i0 (); //Adder interface
adder u0 (i0); // Adder instance

………………….//On Next Slide

endmodule
Adder - Top

initial
begin
uvm_config_db #(virtual adder_inf) :: set (null, “*”, “add_vif”, i0);
//registering virtual interface to configuration database
run_test();
//calling uvm_top.run_test();
//Test name can be specified as an argument
end

always #5 clk<=~clk;
Adder - transaction

class transaction extends uvm_sequence_item;


rand bit [3:0] a, b;
rand bit c;
rand bit [4:0] sum;

`uvm_object_utils_begin(transaction)
`uvm_field_int(a, UVM_DEFAULT)
`uvm_field_int(b, UVM_DEFAULT)
`uvm_field_int(c, UVM_DEFAULT)
`uvm_field_int(sum, UVM_DEFAULT)
`uvm_object_utils_end
……………….//On Next Slide
endclass
Adder - transaction

//Defining Constructor is not compulsory

function new(string name=“packet”);


super.new(name);
endfunction
Test Bench – Sequence

Top
Test

Env

Agent

Sequence Sequencer Driver Monitor


(Checking)
Virtual Interface
Interface
DUT
Adder – sequence1

class sequence1 extends uvm_sequence#(transaction);


transaction pkt;
`uvm_object_utils(sequence1)

function new (string name=“sequence1”);


super.new(name);
endfunction
…………. //On Next Slide

endclass
Adder – sequence1

task body();
repeat(1000)
begin
pkt=transaction :: type_id :: create(“pkt”);
start_item(pkt);
void‘(pkt.randomize);
finish_item(pkt);
end
endtask
Adder – sequence2

class sequence2 extends uvm_sequence#(transaction);


transaction pkt;
`uvm_object_utils(sequence2)

function new (string name=“sequence2”);


super.new(name);
endfunction
……………. //On Next Slide

endclass
Adder – sequence2

task body();
repeat(1000)
begin
pkt=transaction :: type_id :: create(“pkt”);
start_item(pkt);
pkt.randomize with {a<16; b<16;};
//inline constraints Randomization
finish_item(pkt);
end
endtask
Test Bench – Sequencer

Top
Test

Env

Agent

Sequence Sequencer Driver Monitor


(Checking)
Virtual Interface
Interface
DUT
sequencer

⚫ Sequencer routes stimulus data from sequence and passes it to a


driver.

⚫ Extend user define sequencer from uvm_sequencer base class. This


class is parameterized by request and response item types.

Syntax: typedef uvm_sequencer #(REQ, RSP) sequencer;

⚫ RSP(Response) is same type as that of REQ(Request) if it is not


specified separately.

typedef uvm_sequencer#(transaction) sequencer;


//user defined sequencer
Sequencer - Driver Connection

Sequencer Driver

uvm_sequence_item_pull_export uvm_sequence_item_pull_port
seq_item_export seq_item_port

⚫ Driver gets the data through seq_item_port and optionally


provides response
⚫ Sequencer provides the data through seq_item_export.
⚫ Connection between seq_item_port and seq_item_export is done
in agent.
Transaction Flow

Driver Sequencer Sequences


get_next_item() Chooses a start_item(item)
Transaction pre_do()
item.randomize

mid_do()
Performs Pin Deliver to driver finish_item(item)
Level Activity

item_done()

write(rsp) Route response post_do()


back get_response()
(Optional)
Test Bench – Driver

Top
Test

Env

Agent

Sequence Sequencer Driver Monitor


(Checking)
Virtual Interface
Interface
DUT
driver

⚫ A driver will drive DUT signals with help of virtual interface.

⚫ uvm_sequence_pull_port class provides two methods to fetch data


from a sequencer.
o get_next_item() : Blocking Method
o try_next_item() : Non Blocking Method

⚫ Driver needs to return the processed response back to sequencer,


uvm_sequence_pull_port provides following methods returning
response
o item_done() : Non Blocking Method
o put_response() : Blocking Method, sequence must do get_response()
o rsp_port.write(rsp) : built-in Analysis port in driver (Optional)
Adder – driver

class driver extends uvm_driver#(transaction);


virtual adder_inf vif;
transaction pkt;
`uvm_component_utils(driver)
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase (uvm_phase phase);
if(! uvm_config_db #(virtual adder_inf)::get(this,“ ”, “add_vif”, vif))
`uvm_error(“Driver”, “Unable to get virtual interface”);
……………. // On Next Slide
Adder – driver

super.build_phase(phase);
endfunction

task run_phase(uvm_phase phase);


forever begin
seq_item_port.get_next_item(pkt);
drive_item(pkt);
seq_item_port.item_done();
end
endtask
……………… //On Next Slide
Adder – driver

task drive_item (transaction pkt);


@(posedge vif.clk)
vif.a<=pkt.a;
vif.b<=pkt.b;
vif.c<=pkt.c;
endtask

endclass
Test Bench – Monitor

Top
Test

Env

Agent

Sequence Sequencer Driver Monitor


(Checking)
Virtual Interface
Interface
DUT
Adder – monitor

class monitor extends uvm_monitor;


virtual adder_inf vif;
bit [4:0] sum;
`uvm_component_utils_begin(monitor)
`uvm_field_int(sum, UVM_DEFAULT)
`uvm_component_utils_end
covergroup cg;
a : coverpoint vif.a;
b : coverpoint vif.b;
c : coverpoint vif.c;
cross a, b, c;
endgroup …………………..//On Next Slide
Adder – monitor

function new (string name, uvm_component parent);


super.new(name, parent);
cg=new;
endfunction
function void build_phase (uvm_phase phase);
if(! uvm_config_db #(virtual adder_inf)::get(this,“ ”, “add_vif”,vif))
`uvm_error(“Monitor”, “Unable to get virtual interface”)
super.build_phase(phase);
endfunction
…………….//On Next Slide
Adder – monitor

task run_phase (uvm_phase phase);


forever predict_and_compare();
endtask

task predict_and_compare();
@(posedge vif.clk);
cg.sample;
sum=vif.a + vif.b + vif.c;
@(posedge vif.clk);
if(sum!=vif.sum)
`uvm_error(“Monitor”, “Result Mismatch”)
endtask
endclass
Test Bench – Agent

Top
Test

Env

Agent

Sequence Sequencer Driver Monitor


(Checking)
Virtual Interface
Interface
DUT
Adder – agent

class agent extends uvm_agent;


bit is_active=1;
`uvm_component_utils(agent)

monitor mon;
driver dvr;
sequencer sqr;
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction
……………….//On Next Slide
Adder – agent

function void build_phase (uvm_phase phase);


super.build_phase (phase);
mon=monitor :: type_id :: create(“mon”, this); …..//call get method
if(is_active) begin
dvr=driver :: type_id :: create(“dvr”, this);
sqr=sequencer :: type_id :: create(“sqr”, this);
end
endfunction
function void connect_phase (uvm_phase phase);
if(is_active)
dvr.seq_item_port.connect (sqr.seq_item_export);
endfunction
endclass
Test Bench – Env

Top
Test

Env

Agent

Sequence Sequencer Driver Monitor


(Checking)
Virtual Interface
Interface
DUT
Adder – env

class env extends uvm_env;


`uvm_component_utils(env)
agent ag;
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase (uvm_phase phase);
super.build_phase(phase);
uvm_config_db #(bit) :: set (this, “ag”, “is_active”, 1);
ag=agent :: type_id :: create(“ag”, this);
endfunction
endclass
Test Bench – Test

Top
Test

Env

Agent

Sequence Sequencer Driver Monitor


(Checking)
Virtual Interface
Interface
DUT
Adder – test

class test extends uvm_test;


`uvm_component_utils(test)
env e;
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
e=env :: type_id :: create(“e”, this);
endfunction
…………….// On Next Slide
Adder – test

task run_phase (uvm_phase phase);


sequence1 seq1;
phase.raise_objection(this); //Raise objection
seq1=sequence1:: type_id :: create(“seq1”);
seq1.randomize;
seq1.start(e.ag.sqr); //start sequence on sequencer
phase.drop_objection(this); //Drop Objection
endtask

endclass
“myfiles.sv” and run test

//Order is based on dependency


`include “interface.sv”
`include “adder.sv”
`include “transaction.sv”
`include “sequence.sv”
`include “sequencer.sv”
`include “driver.sv”
`include “monitor.sv”
`include “agent.sv”
`include “env.sv”
`include “test.sv”
Pass plus argument in command line to run test name called test
+UVM_TESTNAME=test

You might also like