Sei sulla pagina 1di 26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

HOME

ABOUT US

SYSTEMVERILOG

Konnect. Innovate. Deliver

VLSI RESOURCES

FORUM

FAQ

CONTACT US
APR

SEARCH

23
WEDNESDAY

Methodology
Introduction to Methodologies
What is a Methodology?
M ethodology is a systematic way of doing things with a rich set of standard rules and guidelines. M ethodology provides the necessary infrastructure to build a robust,
reliable and complete Verification environment.
Why do we go for Verification Methodology?
M ethodology shrinks verification efforts with its predefined libraries. It will make your life easier down the road by preventing you from making mistakes or poor
decisions whose outcome may not be obvious at the time you made them. It also helps make sure that whatever you do will mesh nicely with what others do (reusability)
M ethodology is basically set of base class library which we can use to build our testbenches.
Let's take a 'simple' example. Suppose you asked to develop 3 VIP/testbench for different blocks. First thing is you will develop all three VIP's using similar
structure/architecture (every company follows this). Now think of common classes/functions you will require.
Just for an example consider transaction class. Common functions you will require here is display, compare, copy transactions, isn't it? Now what you will do is, you will
keep these common functions in some common area and you will access it in all 3 VIPs. So this common area is nothing but your 'methodology'.
So the verification giants have already defined such common classes and functions which we will mostly require to build testbenches and have formed one library.
That's it; they call this base class library a methodology. Now why 'base' class library? Well you can extend these classes to function it as per your requirement.
Building the testbench environment using M ethodologies have following advantages
Common test bench structure and run flow.
Reusability.
Time required to build any testbench is very less.
Avoids poor coding practices
Debugging simplicity
Layered Testbench Architecture

Figure 1 : Advantages of Methodology

Figure 2 : Methodology Based verification

http://www.systemverilog.in/method.php#fragment-3

1/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

These M ethodologies include Transaction-based verification (TBV), coverage-driven verification (CDV), Constrained Random Testing (CRT), and Assertion Based
Verification (ABV).
Verification Methodology Types
List of verification M ethodologies are given below
AVM Advanced Verification M ethodology (System C & Systemverilog) by M entor Graphics
RVM Reference Verification M ethodology (open Vera) by Synopsys
OVM Open verification M ethodology (systemverilog) by M entor Graphics
VMM Verification M ethodology M anual (systemverilog) by Synopsys

VMM Using SystemVerilog


To get most of Hardware Verification languages like system Verilog a M ethodology is must.
VM M is Verification M ethodology M anual using System Verilog defined by Synopsys and ARM
The VM M for SystemVerilog enables its users to build a scalable, predictable and reusable environment enabling users to take full advantage of assertions, reusability,
testbench automation, coverage, formal analysis, and other advanced technologies to help solve their RTL and system-level verification problems. Using VM M one can
quickly build a layered test bench and each component of VM M can reused. It also gives a consistent look and feel throghout the project .
The VM M for SystemVerilog enables all SoC and IP projects to establish an effective, efficient and predictable verification process that is based upon the experience of
leading industry experts from ARM , Synopsys, and their customers.
The broad scope of the VM M for SystemVerilog allows it to cover many verification techniques and show how they can be most effectively used together. The right
combination of advanced techniques can improve verification thoroughness, increase verification productivity, accelerate the development process and, over the
course of a project, consume fewer resources than brute-force approaches. The VM M for SystemVerilog can both enhance existing approaches and form the basis for
a comprehensive verification environment that takes full advantage of constrained random generation, functional coverage and assertions.
Let us start with VM M base classes
The following 8 base classes are available in VM M
vmm_notify : Base class for VM M notification
vmm_log : Base class for VM M messaging
vmm_data : Base class for VM M data and transactions
vmm_channel : Base class for VM M channels and completion models
vmm_xactor : Base class for VM M Transactors
vmm_env : Base class for VM M verification Environment
vmm_atomic_gen : Base class for VM M Atomic Generator
vmm_scenario_gen : Base class for VM M Scenario Generator
The VM M components used inside the Test bench
Generator: Generates the transactions either individually or in steams
Transactor: Takes High level transactions such as single Ethernet Packet transaction in to multiple Ethernet Packet transaction.
Driver : Controls the signals to the DUT it6 executes a single command such as bus read or write or driving Ethernet packet into the DUT
M onitor: Bundles the signals from the DUT into transactions.
Checker: Compares the output of the DUT, as seen by the M onitor, to the Scoreboard, using a predictor or reference model.
Assertions: Constantly check the DUT for correctness.
Scoreboard : Stores the transactions from transactors for later comparison
Layered VMM Testbench

VMM Messaging overview


A testbench produces messages of many types and severities
The vmm_log class allows to control

http://www.systemverilog.in/method.php#fragment-3

2/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

which messages are displayed,


what their format is, and
Even promote and demote them (useful for error testing).
All messages are sent to standard output, i.e. displayed on the screen and sent to the simulation log file, just like $display.
Message Type
In VM M , every message has a type and a severity. One may want to print a message to
Debug a piece of code
Tell the user that simulation reached a notable state, or
Encountered a problem.
The message type tells which of these is happening
Failure: Error has been detected
Note: Simulation progress
Debug: Optional simulation diagnostics
Timing: Timing check or error
Severity describes message importance
Severity levels and the type in parenthesis
Fatal: Functional correctness definitely compromised (Failure)
Example: Testbench failure
Error: Functional correctness may be compromised (Failure)
Example: Actual model results dont match expected results
Warning: Functional correctness not compromised (Failure or Timing).
Normal: Regular, expected message.
Trace: High-level simulation execution trace message (Debug)
Example: "Executing transaction"
Debug: Detailed simulation execution trace message (Debug)
Verbose: Very detailed simulation execution trace message (Debug)
Example: "Sending byte #5 (0x5A)"
vmm_log class
Each part of the testbench (test ,generator ,checkers ,etc ) uses its own instance of the vmm_log class to generate messages
Each instance is a separate massage source with a descriptive name and an instance name.
Use regular expressions to select and control sources.
Descriptive name name of the class instantiating vmm_log.
Instance name The name of the object or class if there is only single instance
Declaration and instantiations
The vmm_log usually instantiated inside a testbench object such as generator, checker or in a data object.
Vmm_log log = new (Name, instance)
The name string is the name of the class that contains the log, such as USB Host, or M AC Frame.
The instance string is the name of this instance of the object such as Generator 1, or Left side. If there is only a single instance, just use the string class.
Log Object Macros
The easiest way to use a vmm_log object is with the macros
`vmm_fatal(vmm_log log, string msg)
`vmm_error(vmm_log log, string msg)
`vmm_warning(vmm_log log, string msg)
`vmm_note(vmm_log log, string msg)
`vmm_trace(vmm_log log, string msg)
`vmm_debug(vmm_log log, string msg)
`vmm_verbose(vmm_log log, string msg)
Examples using Macros
Two examples of using the above message macros.
The first displays a simple string.
The second needs to print variable arguments, so it uses $psprintf, which returns a formatted string.
`vmm_verbose(log, "Checking rcvd byte");
if (got != expect) begin

http://www.systemverilog.in/method.php#fragment-3

3/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

`vmm_error (log, $psprintf("Bad data: 0x%h vs. 0x%h",got, expect));


End
Note that these macros expand to several lines, so surround them with begin-end when used in an if-statement.
Message Handling
The messaging class handles each message according to its severity level.
The default is that
fatal messages cause the simulation to exit,
error messages increment a global error count, and cause the simulation to exit after 10 errors,
While all others just print to standard out.
Use the method vmm_log::modify () to change how messages are handled.
Controlling Verbosity
By default, only messages with a severity of NORM AL (vmm_fatal, vmm_error, vmm_warning, vmm_note) or higher are displayed.
This can be controlled in two ways
Using +vmm_log_default
The command line switch +vmm_log_default=DEBUG will enable printing of all messages with
The severity level DEBUG and higher.
Using set_verbosity()
The method vmm_log::set_verbosity() allows to set the level of printing on the fly.
The following code sets the level to DEBUG for any vmm_log object with Drv in its name:
log.set_verbosity(log::DEBUG_SEV, "/Drv/", "/./", );
This call overrides the +vmm_log_default switch, and only applies to current vmm_log objects, not any created afterwards.
Create complex, multi-line messages using the vmm_log methods start_msg(), text (), and end_msg().
Change the formatting of vmm_log by extending the vmm_log_format class and register an instance with the vmm_log::set_format method.
VERIFICATION ENVIRONMENT
vmm_env:
Overview:
Testbench goes through many phases of execution, from initialization, simulation, and cleanup.
The class vmm_env helps to manage these steps and ensures that all execute in the proper order.
The new() method should only initialize values, and should never have any side effects such as spawning threads or consuming time.
If a testbench object starts running as soon as new () is called, one will not be able to delay its start, or synchronize it with other testbench operations.
The vmm_env class divides a simulation into the following nine steps, with corresponding methods:
gen_cfg() Randomize test configuration descriptor
build() Allocate and connect test environment components.
reset_dut() Reset the DUT
cfg_dut() Download test configuration into the DUT
start() Start components
wait_for_end() End of test detection
stop() Stop data generators and wait for DUT to drain
cleanup() Check recorded statistics and sweep for lost data
report() Print final report
Execution Sequence in vmm_env class
Base class run () Dut specific extension

http://www.systemverilog.in/method.php#fragment-3

4/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

Simplest Example
The top method run () keeps track of which steps have executed When run () is called, it runs the remaining ones.
For example, the following program runs all nine steps automatically
program test;
initial begin
verif_env env;
env = new(...);
env.run();
end
endprogram
The class verif_env extends vmm_env. When run() is called and it will call all the steps which have not yet been run.
Basic Example
The next example runs the first step, makes a modification to the configuration, and then completes the test.
program test;
initial begin
verif_env env;
env = new(...);
env.gen_cfg(); // Create rand config
env.rand_cfg.n_frames = 1; // Only run for 1 frame
env.run(); // Run the other steps
end
endprogram
Automatic Sequencing
The run() task is not the only method that executes the steps. As shown in the following example, if build() is called without calling gen_cfg(), the build() method will
automatically execute the previous step
program test;
initial begin
verif_env env;
env = new();
env.build(); // Config and build
begin
my_eth_fr my_fr;
my_fr = new(); // Use my own frame
env.src[0].rand_fr = my_fr; // Use to build more
end
env.run();
end
endprogram

http://www.systemverilog.in/method.php#fragment-3

5/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

Using Vmm_env
The virtual methods gen_cfg() and build() etc must call their super method as the first step.
These calls to the base methods contain the sequencing code that ensures all previous steps have been called.
If calls are left out, the vmm_env class will generate a fatal error at run time.
`include vmm.sv
class verif_env extends vmm_env;
my_cfg cfg;
my_gen gen[4];
my_drv drv[4];
my_mon mon[4];
virtual function void gen_cfg();
super.gen_cfg();
// rest of gen_cfg method
Endfunction
virtual function void build();
super.build();
// rest of build method
Endfunction
Endclass
DATA AND TRANSACTIONS
Traditional Approach Vs OOP Approach
In traditional testbench the transactions are implemented using procedures one per transaction.
This caused the following problems:
Code is not self-contained
Code is not protected properly
Cannot extend data types
Cannot add constraints to an existing data type
Instead, model transactions as objects.
Their data values exist in a transaction class that can be randomized, copied, packed, and unpacked.
The code that actually executes the transactions resides in the Driver.
Transaction Coding Guidelines
Properties in a transaction class should be public so they can be modified or constrained by other classes, such as the testbench.
Do not hide data values using set () & get () methods.
In hardware verification, one need access to all parts of the testbench for maximum control.
Properties should be random by default so that they can be randomized by other classes.
Can always go back and use rand_mode () to turn this off.
Transactions Vs Transactors
The transaction class contains both physical values that are sent to the DUT (address, data, etc.) and meta-data that has extra information about the transaction, such
as a kind field.
Even though this might be encoded in the physical values, put it into a separate field that can be easily accessed and can be randomized.
class alu_xactn extends vmm_data;
rand reg [7:0] data_in1 ;
rand reg [7:0] data_in2 ;
rand reg [2:0] select ;
rand bit reset_N ;
endclass
The Transactor contains the code to send the transaction to the next testbench level.
ID fields
Every transaction has three integer ID fields uniquely identifying it.
The stream_id tells which stream created this object useful when there are multiple generators.
The sequence_id is used when a stream generator creates groups of related transactions, and identifies the group.
The object_id identifies individual transactions in a sequence.
class vmm_data;
integer stream_id;
integer scenario_id;
integer object_id;

http://www.systemverilog.in/method.php#fragment-3

6/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

...
endclass
In the following example, a constraint block uses the stream_id.
Constraints - Guidelines
Every transaction should have one or more constraint blocks for the must-obey constraints that are never turned off or overridden.
For example, they would make sure an integer field is never negative or that a length field is never 0.
Name these constraints class_name_valid,
Have separate constraints for should-obey.
One can turn these off later for injecting errors.
Name these constraints class_name_rule.
Methods used in VMM transaction class
The vmm_data class defines a set of virtual methods for manipulating its properties.
M ake own methods when extending vmm_data.
display() & psdisplay()
These methods display the contents of the class, either to the screen or to string.
Virtual task display (string prefix);
Virtual function string psdisplay (string prefix) ;
allocate()
This method allocates a vmm_data object and initializes required fields.
This is a virtual method, unlike new() so the correct method is called regardless of the handle Type.
Virtual function vmm_data allocate()
copy()
This method makes a copy of an existing transaction. It has an optional to field so one can copy to a previously allocated object.
Note that this method returns a vmm_data type, so use $cast () with it.
virtual function vmm_data my_data::copy(vmm_data to = null);
my_data cpy;
// Copying to a new instance?
if (to == null)
cpy = new();
else
if (! $cast(cpy, to, CHECK)) begin
`vmm_fatal(this.log, "Attempting to copy to a non my_data instance");
return;
end
// Copy IDs and any other properties
cpy.stream_id = this.stream_id;
cpy.scenario_id = this.scenario_id;
cpy.object_id = this.object_id;
// Assign the copy to the return handle
copy = cpy;
endfunction
compare()
This method compares two objects and reports the difference.
Virtual function bit compare (to, diff, kind);
The current object is compared with to using type kind.
The method returns 1 if the two objects are the same, 0 if not.
The diff string gives a description of the difference.
The following three methods are used for converting between the physical fields of an object and an array of bytes
byte_size()
virtual function integer byte_size (kind);
The method byte_size tells how many bytes are needed to pack an object of this kind.

http://www.systemverilog.in/method.php#fragment-3

7/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

byte_pack();
virtual function integer byte_pack (bytes,offset,kind);
The method byte_pack packs the object of type kind into a dynamic array of bytes.
byte_unpack();
Virtual function integer byte_unpack (bytes,offset,kind);
The method byte_unpack unpacks the data from the dynamic array of bytes.
The offset tells the methods where to start in the byte array.
Notification - Overview
VM M provides an event notification class that allows notifying when an event notification is indicated, and includes data.
These notifiers are based on integer identifiers that hold a symbolic value.
The following code creates three notification identifiers associated with the alu_driver class:
class alu_driver extends vmm_xactor;
static integer TR_STARTED;
static integer TR_ABORTED;
static integer TR_SUCCESS;
endclass
Configuring a Notifier
Configure a notifier before using it.
A notifier can be ON_OFF, ONE_SHOT, or BLAST.
The following example calls the configure () method in the notify object (preinstantiated in vmm_xactor), which returns an integer value.
class alu_driver extends vmm_xactor;
function new(...);
this.TR_STARTED = this.notify.configure(*, vmm_notify::ON_OFF);
endtask
endclass
Channels and completion models:
Channels
Testbench environment needs to exchange transactions between its components.
For example, transactions flow from the Generator -> Transactor ->Driver, or from the M onitor -> Checker -> Scoreboard.
Transactions are modeled as objects that are then created and modified by the different testbench components.
The connection between these components is the VM M channel.
One side is the producer (such as the Generator) putting transactions into the channel.
The consumer side (Transactor) gets the transactions out of the channel and executes them.
Channels Vs Mailboxes
Unlike mailboxes, channels are strongly typed which helps prevent coding errors.
Channels allow flow control, so the put () method will block if the channel is full.
A channel can have both high-water and low water marks to fine tune the interactions between the producer and consumer.
get() method removes the transaction from the end of the channel
peek () gives a handle to it without removal.
Both block if the channel is empty.
The output of a channel can be replicated using the tee() method.
Definition and Creation of Channel
class alu_xactn extends vmm_data;
...
Endclass
// macro automatically creates new data type by
// appending "_channel" to data_type_name
`vmm_channel(alu_xactn); // alu_xactn_channel declaration
program test;
initial begin
alu_xactn_channel ch;
ch = new(ALU channel, class);
end
endprogram

http://www.systemverilog.in/method.php#fragment-3

8/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

Communication using Channel


// Producer
forever begin
alu_xactn tr = new();
ch.put(tr);
end
and:
// Consumer
forever begin
alu_xactn tr = ch.get();
...
end
Allocate object every time
Just like a SystemVerilog mailbox, the channel contains handles to objects, not the object themselves.
One can modify an object after it has been put in the channel, leading to a common mistake.
// Producer
Alu_xactn_channel ch = new( ALU channel, class);
Alu_xactn tr;
tr = new();
while (...) begin
void = tr.randomize();
ch.put(tr);
end
This code only allocates a single cell. It then repeatedly randomizes this cell and puts it in the channel.
The result is that the channel will contain many references to the same object.
The solution is to allocate a new cell every time through the loop.
while (...) begin
tr = new();
void = tr.randomize();
ch.put(tr);
end
Using channels to connect blocks
Just like a SystemVerilog mailbox, the channel contains handles to objects, not the object themselves.
One can modify an object after it has been put in the channel, leading to a common mistake.
// Producer alu_xactn_channel ch = new(ALU channel, class);
alu_xactn tr;
tr = new();
while (...) begin
void = tr.randomize();
ch.put(tr);
end
Transaction Completion
Synchronize two testbench blocks using a channel.
Configure the channel with full=1 (the default) so it works like a procedural interface.
The producer thread blocks when it calls put().
When the consumer calls get() to remove the transaction from the channel, the producer unblocks so it can create a new transaction.
In the following example, the consumer first calls peek() to read the transaction, but does not call get() until it is done, thus waking the producer.
// Consumer forever begin
tr = ch.peek(); // Read the cell
case (tr.kind) {
... // Process the cell
}
void = ch.get(); // Done, wake up producer
end
Atomic Generator
VMM approach to testbench
Traditional test benches create stimulus with generators that grow more and more complex as the project progresses, accommodating

http://www.systemverilog.in/method.php#fragment-3

9/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

every variant of stimulus,


error generation,
Synchronization, etc.
This mother of all generators can be unstable because of the constant changes, as well as difficult to enhance and maintain.
In VM M , Tests should tune random generators, not completely rewrite them.
These results in
less code (each test is smaller),
more randomness (all unspecified behavior is random) and
M ore checking (extra randomness broadens the stimulus).
Typical Generator
class alu_gen extends vmm_xactor;
...task main();
forever begin
alu_xactn tr = new();
void = tr.randomize();
this.ch.put(tr);
end
endtask
endclass
With this generator, there is no easy way to randomize cells with different constraints.
Solutions
One could use the randomize with {} construct, but this would require a separate generator for each test, just what we were trying to avoid.
One could modify the transaction class, alu_xactn, adding constraints for each test, but this moves the problem to a different file.
Each of these requires every test writer to edit a common file, with the results applied to every generator / ALU transaction.
Some test benches have knobs to control the different distributions and cases, but once again, the generator or transaction becomes the bottleneck, growing in
complexity.
In addition, the testcase is the testbench plus knob files, adding another file to the flow.
Factory Patterns
Factories Correct Solution
Create a factory that stamps out transactions, then have individual tests feed it different blueprints.
All the test-specific code is located in the test file, not the generators.
In fact, one can have multiple factories running in a test, each generating a unique set of stimulus
class factory;
alu_xactn blueprint = new();
task run();
while (run) begim
alu_xactn tr;
void = blueprint.randomize();
$cast(tr, blueprint.copy());
process(tr);
end
endtask
endclass
Changing the blueprint
class my_transaction extends alu_xactn;
constraint select_valid {select == 3'b100;}
endclass
program test;
verif_env env;
initial begin
env = new();
env.build();
begin
my_transaction my_tr = new();
env.select.blueprint = my_tr;
end
env.run();
end
endprogram
Benefits

http://www.systemverilog.in/method.php#fragment-3

10/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

Tests can modify constraints by


M aking variables non-random
Turning constraint blocks off
Add new constraint block
Re-define constraint blocks
Add random variables
Supersede random results with directed data
Transactors
VMM Transactors
A VM M transactor is just a while loop that reads in transactions from a previous testbench layer, does some processing, and sends out transactions to the next
layer.
The key is properly starting and stopping the transactors.
The VM M has several transactor types:
Active Xactor M aster
Drives pins, blocks on channel get()
Reactive Xactor Slave
M onitors and drives pins, blocks on signal edges
Passive Xactor M onitor
M onitors pins, blocks on signal edges
Also Generator or other Xactors as needed
Creates transactions, blocks using notification or channel put()
A Basic Transactor
Add code to method main() to process transactions.
The other methods all start with a call to the base method to start and stop this method. For example, vmm_xactor::start_xactor() starts the virtual method main()
Dont need to do this.
class alu_driver extends vmm_xactor;
//start_xactor starts the execution threads
virtual task start_xactor;
super.start_xactor();
...
endtask
//stops execution threads after currently executing
//transaction had completed. Takes effect at next call
//to vmm_xactor::wait_if_stopped()
virtual task stop_xactor();
super.stop_xactor();
...
endtask
// resets the xactors state and execution threads
virtual task reset_xactor(...);
super.reset_xactor(...);
...
endtask
virtual task main();
...
endtask
endclass
Stopping an Xactor
The main() method periodically checks to see if the transactor has been stopped by calling wait_if_stopped() as shown below
virtual task main();
forever begin
this.wait_if_stopped();
alu_xactn tr = to_driver.get();
this.wait_if_stopped();
...
end
endtask
The wait_if_stopped() method will block if stop_xactor() has been called.
Different blocks in testbench will define when to stop and what it means.
Should check if the transactor needs to stop after every time-consuming action, such as the call to get () above.
Physical and Virtual Interfaces

http://www.systemverilog.in/method.php#fragment-3

11/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

The SystemVerilog interface groups all relevant physical signals (ports) together,
A virtual interface is just a pointer to a physical interface.
One can pass a virtual interface into drivers and monitors.
Now the testbench can replicate a driver, with each instance using a separate virtual interface so as to drive multiple physical ports.
If need to synchronize on a clock edge in an interface, use the clocking block in the interface.
Note that this form does not contain the active edge of the clock signal.
If the designer changes the edge, just change the interface definition, not every usage of the signal.

Click here to download the VMM example

OVM VERIFICATION ENVIRONMENT


This Example gives you detailed explanation about OVM verification environment including a Design Under Test (DUT), a Verification Environment and a Test. The Design
is written in Verilog or VHDL and Verification Environment is developed using SystemVerilog and OVM methodology.
In traditional Verilog code, modules are the basic building blocks to structure designs and test benches. The recent trend is to use classes to build flexible and
reusable Verification Environment.
The OVM Verification environment consist of OVM components like
OVM Transactor
OVM Sequencer
OVM sequence
OVM Driver
OVM M onitor
OVM Scoreboard
OVM TRANSACTOR
The transactor contains the code to send the transaction to the next test bench level. Here we are creating the basic transaction class alu_item which is extended
from OVM base class ovm_sequence_item.
A transaction is just a collection of related data items that get passed around the verification environment as a single unit.
In OVM all transactions including sequence item all are derived from the class ovm_transaction. This Example uses the sequencer hence the transaction class must be
derived from ovm_sequence_item class, which is child class of ovm_transaction. The constructor new is passed a string used to build a unique instance name of
transaction.
The code snippet for transaction class is as show below.
class alu_item extends ovm_sequence_item;
rand reg [ 7:0] data_in1 ;
rand reg [ 7:0] data_in2 ;
rand reg [ 2:0] select;
rand bit reset_N;
constraint rest_c1{reset_N == 1'b1;}
`ovm_object_utils_begin (alu_item)
`ovm_field_int(data_in1 , OVM _ALL_ON)
`ovm_field_int(data_in2 , OVM _ALL_ON)
`ovm_field_int(select , OVM _ALL_ON)
`ovm_field_int(reset_N , OVM _ALL_ON)
`ovm_object_utils_end
// new constructor
function new (string name = "alu transaction instant") ;
super.new(name);
endfunction
endclass
As transactions are created we need to copy, compare, print, pack, and unpack those transactions is done automatically by inbuilt ovm macros as shown below.
`ovm_object_utils_begin (alu_item)
`ovm_field_int(data_in1 , OVM _ALL_ON)
`ovm_field_int(data_in2 , OVM _ALL_ON)
`ovm_field_int(select , OVM _ALL_ON)
`ovm_field_int(reset_N , OVM _ALL_ON)
`ovm_object_utils_end
The flag OVM _ALL_ON indicates that the given field should be copied printed, included in any comparison for equality between two transactions, and so on.
OVM_SEQUENCER
A sequencer is an advanced stimulus generator that controls the items that are provided to the driver for execution. By default, a sequencer behaves similarly to a
simple stimulus generator and returns a random data item upon request from the driver. This default behavior allows you to add constraints to the data item class in
order to control the distribution of randomized values.

http://www.systemverilog.in/method.php#fragment-3

12/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

The alu_sequencer is derived from base class ovm_sequencer parameterizes it to use the alu_item type.
`ovm_sequencer_utils and `ovm_update_sequence_lib_and_item are used to indicate the generated data item type and field desired automation.
Call `ovm_update_sequence_lib_and_item macro from the constructor of your sequencer class. This macro registers all the sequence types that are associated
with the current sequencer and indicates the sequencer's generated transaction type as a parameter
class alu_sequencer extends ovm_sequencer #(alu_item) ;
//constructor
function new(string name , ovm_component parent) ;
super.new(name , parent) ;
`ovm_update_sequence_lib_and_item(alu_item)
endfunction
// Provide implementations of virtual methods such as get_type_name and
// create
`ovm_sequencer_utils(alu_sequencer)
endclass
OVM_SEQUENCE
The class alu_seq_do in the following example defines a simple sequence. It is derived from ovm_sequence and uses the `ovm_sequence_utils macro to associate this
sequence with alu_sequencer, and to declare the various utilities `ovm_object_utils would provide.
Once you define a sequence, it is registered inside its sequencer and may be generated by the sequencers default generation loop. The `ovm_sequence_utils macro
creates the necessary infrastructure to associate this sequence with the relevant sequencer type, and declares the various automation utilities. This macro is similar to
the `ovm_object_utils macro (and its variations) except that it takes a second argument, which is the sequencer type name, this sequence is associated with.
class alu_seq_do extends ovm_sequence #(alu_item), ;
function new(string name = "alu_seq_do") ;
super.new(name) ;
endfunction
`ovm_sequence_utils(alu_seq_do,alu_sequencer)
virtual task body() ;
`ovm_info(get_name(), $psprintf("In body() of %s",get_name()), 1000)
`ovm_do(req)
endtask
endclass : alu_seq_do
Sequence and Sequence Item Macros
This section describes the sequence and sequence item macros, `ovm_do and `ovm_do_with.
The `ovm_do macro takes as an argument either a variable of type ovm_sequence or of type ovm_sequence_item. An object is created using the factory settings and
assigned to the specified variable. Based on the processing when the driver requests an item from the sequencer, the item is randomized and provided to the driver.
The body of the sequence invokes an item of type alu_item, using the `ovm_do macro.
OVM_DRIVER
A driver is an active entity that emulates logic that drives the DUT. A typical driver repeatedly receives a data item and drives it to the DUT by sampling and driving the
DUT signals.
To create a driver
Derive a driver from the ovm_driver base class.
If desired, add OVM infrastructure macros for class properties to implement utilities for printing, copying, comparing, and so on.
Obtain the next data item from the sequencer and execute it as outlined above.
Declare a virtual interface in the driver to connect the driver to the DUT.
The class alu_driver in the example below defines a driver class. The example derives alu_driver from ovm_driver (parameterized to use the alu_item transaction type)
and uses the methods in the seq_item_port object to communicate with the sequencer. As always, include a constructor and the `ovm_component_utils macro to
register the driver type with the common factory.
class alu_driver extends ovm_driver #(alu_item) ;
// Provide implementations of virtual methods such as get_type_name and
// create
`ovm_component_utils(alu_driver)
// constructor
function new(string name , ovm_component parent ) ;
super.new(name,parent) ;
endfunction
task run ();
while(1) begin
#10
seq_item_port.get_next_item(req);
`ovm_info("Driver", "printing Recieved item:" , OVM _M EDIUM )
req.print();
seq_item_port.item_done() ;
end
endtask : run

http://www.systemverilog.in/method.php#fragment-3

13/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

endclass : alu_driver
OVM_TEST
This is top level of ovm verification environment which include all instance of transactor, sequencer, driver.
The following Elaboration and simulation steps are followed inside ovm environment
new() : In this Phase constructor is called.
build() : In this Phase Create components using new or the factory.
connect() : In this Phase M ake port, export and implementation connections.
end_of_elaboration() : In This Phase make sure that after all connections have been hardened
start_of_simulation() : This phase start Just before simulation starts
run() : This Phase starts the simulation
extract() , check() , report() : All these are post processing used to extract ,check , give the detail report .
In our Example As shown inside initial block
set_config_string("sequencer" ,"default_sequence", "alu_seq_do") ; will indicate that sequencer has to run alu_seq_do sequence as default sequence.
The build () function is used to Create components using new or the factory.
In connect phase we need to connect driver sequence item port to sequencer item export as show below.
The test is actually started by calling the run_test method.
The simulation can be stopped by calling global_stop_request()
module test ;
`include "ovm.svh"
`include "alu_xactn.sv"
`include "alu_sequencer.sv"
`include "alu_driver.sv"
`include "alu_seq_lib.sv"
alu_sequencer sequencer ;
alu_driver driver ;
initial begin
set_config_string("sequencer" ,"default_sequence", "alu_seq_do") ;
sequencer = new("sequencer" , null) ; sequencer.build() ;
driver = new("driver", null) ; driver.build();
driver.seq_item_port.connect(sequencer.seq_item_export);
ovm_default_printer = ovm_default_tree_printer ;
sequencer.print();
driver.print();
fork
run_test() ;
#2000 global_stop_request();
join
end
endmodule

Click here to download the OVM example


Click here to download more on OVM methodology

UVM article
Introduction
The UVM ( Universal Verification M ethodology) is started in December 2009, a technical subcommittee of Accellera- a standard organization in the electronic design
automation(EDA) industryvoted to establish the UVM and decided to build this new standard using the Open Verification M ethodology (OVM -2.1.1) as its foundation.
Accellera released version UVM 1.0 EA on M ay 17, 2010. UVM Class Library provides the building blocks needed to quickly develop well-constructed and reusable
verification components and test environments in systemverilog. All three of the simulation vendors (Synopsys, Cadence and M entor)support UVM today.
UVM library contents are same as that OVM library as mentioned below
1.Component classes for building testbench components like generator/driver/monitor etc.
2. Reporting classes for logging,
3. Factory for object substitution.
4. Synchronization classes for managing concurrent process.
5. Policy classes for printing, copying, recording, packing, and unpacking of uvm_object based classes.
6. TLM Classes for transaction level interface.
7. Sequencer and Sequence classes for generating realistic stimulus.
8. And M acros which can be used for shorthand notation of complex implement
Like in OVM how all above mentioned classes are derived from OVM _object base class in UVM also above mentioned classes are derived from UVM _object base class.

http://www.systemverilog.in/method.php#fragment-3

14/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

A more detailed overview of each category and the classes comprising them:
Components
Components form the foundation of the UVM . They encapsulate behavior of drivers, scoreboards, and other objects in a testbench. The UVM library provides a set of
predefined component types, all derived directly or indirectly from ovm_component.
Following are some of the UVM component classes.
1. Agent
2. M onitor
3. Scoreboard
4. Driver
5. Sequencer
Reporting
The uvm_report_object provides an interface to the UVM reporting facility. The reporting classes provide a facility for issuing reports (messages) with consistent
formatting and configurable side effects, such as logging to a file or exiting simulation. Users can also filter out reports based on their verbosity , unique ID, or severity.
If the verbosity level of a report is greater than the configured maximum verbosity level of its report object, it is ignored.
Argument Description
1. unique ID or severity = its an unique id to form a group of messages.
2. verbosity = it mainly indicates the relative importance of particular message.
3. filename/line = we need to include macros like '__FILE__ and __LINE__' if we require filename and line number from where the massage is issued.
Factory
As the name implies, the UVM factory is used to manufacture (create) UVM objects and components. The factory pattern is an well known object-oriented design
pattern. Users can configure the factory to produce an object of a given type on a global or instance basis. The factory method design pattern defining a separate
method for creating the objects. whose subclasses can then override to specify the derived type of object that will be created. Use of the factory allows dynamically
configurable component hierarchies and object substitutions without having to modify their code and without breaking encapsulation.
There are three basic steps to be followed for using uvm factory.
1. Registration = class type has to be registered while defining a class.
2. Construction = here create() should be used to construct uvm based objects.
3. Overriding = user can override the registered classes or objects accroding to the requirement.
Synchronization
The UVM provides event and barrier synchronization classes for process synchronization.
Policies
Each of UVM s policy classes perform a specific task for ovm_object based objects: printing, comparing, recording, packing, and unpacking. They are implemented
separately from uvm_object so that users can plug in different ways to print, compare, etc. without modifying the object class being operated on. The user can simply
apply a different printer or compare policy to change how an object is printed or compared.
TLM
The UVM TLM library defines several abstract, transaction-level interfaces and the ports and exports that facilitate their use. Each TLM interface consists of one or
more methods used to transport data, typically whole transactions (objects) at a time. Component designs that use TLM ports and exports to communicate are
inherently more reusable, inter operable, and modular.
Core Base Classes of UVM
The UVM library defines a set of base classes and utilities that facilitate the design of modular, scalable, reusable verification environments. The basic building blocks
for all environments are components and the transactions they use to communicate. The UVM provides base classes for these, as shown below.

uvm_object

http://www.systemverilog.in/method.php#fragment-3

15/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

All components and transactions derive from uvm_object,which defines an interface of core class-based operations: create, copy, compare, print,sprint, record, etc. It
also defines interfaces for instance identification (name, type name, unique id, etc.) and random seeding.
uvm_component
The uvm_component class is the root base class for all UVM components. Components are quasi-static objects that exist throughout simulation. This allows them to
establish structural hierarchy much like modules and program blocks . Every component is uniquely addressable via a hierarchical path name, e.g.
env1.pci1.master3.driver.
The uvm_component also defines a phased test flow that components follow during the course of simulation. Each phase-- build , connect , run , etc.-- is defined by a
callback that is executed in precise order. Finally, the uvm_component also defines configuration, reporting, transaction recording, and factory interfaces.
Following example depicts the usage of uvm_component:
class consumer extends uvm_component;
uvm_blocking_put_imp #(simple_trans, consumer) put_export;
// 2 parameters
...
task put(simple_trans t);
case(t.kind)
READ: // Do read.
WRITE: // Do write.
endcase
endtask
endclass
uvm_transaction:
The uvm_transaction is the root base class for UVM transactions, which, unlike uvm_components , are transient in nature. It extends uvm_object to include a timing
and recording interface. Simple transactions can derive directly from uvm_transaction , while sequence-enabled transactions derive from uvm_sequence_item .
class simple_trans extends uvm_transaction;
rand data_t data;
rand addr_t addr;
rand enum {WRITE,READ} kind;
constraint c1 { addr < 16h2000; }
...
endclass
uvm_root
The uvm_root class is special uvm_component that serves as the top level component for all UVM components, provides phasing control for all UVM components, and
other global services.
uvm_void
The uvm_void class is the base class for all UVM classes. It is an abstract class with no data members or functions. It allows for generic containers of objects to be
created, similar to a void pointer in the C programming language. User classes derived directly from uvm_void inherit none of the UVM functionality, but such classes
may be placed in uvm_void -typed containers along with other UVM objects.
As all base classes of UVM are from OVM there we do not find much difference between OVM and UVM . Only some new features are added to UVM such as callbacks,
report catcher and heartbeat. Features like byte packing,unpacking,transaction id,transaction recording and time of transaction created all these VM M features are
now available in UVM . This UVM methodology efficiently uses both OVM and VM M features.
The main differences between OVM and UVM are as mentioned below:
UVM is based on OVM
The deprecated features from OVM were removed in UVM .
The URM and AVM compatibility layers were removed from UVM .
Added a uvm_heartbeat class which allows environments to set up heartbeat criteria to monitor the liveness of the components in the hierarchy.
Callbacks were updated with the following additional functionality:
- A callback iterator class
- Type wide callback support (instead of just instance specific)
- Callback type registration for type checking (added type checking to the add functions to warn if added to a type that doesn't support a specific callback).
- Added add/delete callback by name.
- M ore callback tracing was added.
Objections were updated with the following additional functionality:
- Added a string description for raise/drop

http://www.systemverilog.in/method.php#fragment-3

16/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

- Added ability to add external callbacks to objections.


uvm_report_catcher callback mechanism for reports. Allows messages to be processed and potentially changed. Catcher callbacks can be added globally or to specific
report objects using the uvm_callbacks add methods.
uvm_callbacks added support for type wide callbacks by using a null object identifier.
Added better runtime type checking for callbacks to ensure that callbacks are only registered with objects that can use them.
* added type-callback registration macro, `uvm_register_cb.
* added ability to specify inheritance hierarchy of objects using callbacks via the `uvm_set_super_type macro.
Added the ability to configure the global timeout using the configuration mechanism. ovm_top.set_config("","timeout",<value>) will set the timeout value for the task
based phases.
Added tracing to the objection mechanism. The tracing can be enabled procedurally with uvm_objection::trace_mode() or can be set via the command line with +
UVM _OBJECTION_TRACE.
Added raised, dropped, and all_dropped callbacks to the uvm_objection class. This allows external callbacks to be attached to objections
Detailed explanation of differences :
uvm_heartbeat
Heartbeats provide a way for environments to easily ensure that their descendants are alive. A uvm_heartbeat is associated with a specific objection object. A
component that is being tracked by the heartbeat object must raise (or drop) the synchronizing objection during the heartbeat window.
The uvm_heartbeat object has a list of participating objects. The heartbeat can be configured so that all components (UVM _ALL_ACTIVE), exactly
one(UVM _ONE_ACTIVE), or any component (UVM _ANY_ACTIVE) must trigger the objection in order to satisfy the heartbeat condition.
Heartbeats provide a way for environments to easily ensure that their descendants are alive.
Methods
new: Creates a new heartbeat instance associated with cntxt.
hb_mode: Sets or retrieves the heartbeat mode.
set_heartbeat: Sets up the heartbeat event and assigns a list of objects to watch.
add: Add a single component to the set of components to be monitored.
remove: Remove a single component to the set of components being monitored.
start: Starts the heartbeat monitor.
stop: Stops the heartbeat monitor.
Explanation of uvm_heartbeat methods :
new:
This will creates a new heartbeat instance associated with context . The context is the hierarchical location that the heartbeat objections will flow through and be
monitored at. The objection associated with the heartbeat is optional, if it is left null then the uvm_test_done objection is used.
Syntax
function new(string name , uvm_component cntxt, uvm_objection = null)
hb_mode:
Sets or retrieves the heartbeat mode. The current value for the heartbeat mode is returned. If an argument is specified to change the mode then the mode is changed
to the new value.
Syntax
function uvm_heartbeat_modes hb_mode (uvm_heartbeat_modes mode = UVM _NO_HB_M O)
Set_heartbeat
Sets up the heartbeat event and assigns a list of objects to watch. The monitoring is started as soon as this method is called. Once the monitoring has been started
with a specific event, providing a new monitor event results in an error. To change trigger events, you must first stop the monitor and then start with a event trigger.
If the trigger event e is null and there was no previously set trigger event, then the monitoring is not started. M onitoring can be started by start.
Syntax:
function void set_heartbeat ( uvm_event e , ref uvm_component comps [$] )
add

http://www.systemverilog.in/method.php#fragment-3

17/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

Add a single component to the set of components to be monitored. This does not cause monitoring to be started. If monitoring is currently active then this component
will be immediately added to the list of components and will be expected to participate in the currently active event window.
syntax
function void add ( uvm_component comp )
remove
Remove a single component to the set of components being monitored. M onitoring is not stopped, even if the last component has been removed (an explicit stop is
required).
syntax
function void remove ( uvm_component comp )
start:
Starts the heartbeat monitor. If e is null then whatever event was previously set is used. If no event was previously set then a warning is issued. It is an error if the
monitor is currently running and e is specifying a different trigger event from the current event.
syntax:
function void start ( uvm_event e = null )
stop:
Stops the heartbeat monitor. Current state information is reset so that if start is called again the process will wait for the first event trigger to start the monitoring.
syntax:
function void stop ()
uvm_callback
The uvm_callback class is the base class for user-defined callback classes. Typically, the component developer defines an application-specific callback class that
extends from this class. In it, he defines one or more virtual methods, called a callback interface, that represent the hooks available for user override.
M ethods intended for optional override should not be declared pure.Usually, all the callback methods are defined with empty implementations so users have the option
of overriding any or all of them. As mentioned earlier ovm library provide extra features in callback they are explained below:
example: mainly taken out from user guide
virtual class bus_bfm_cb extends uvm_callback;
virtual function bit trans_received(bus_bfm driver, bus_tr tr); return 0;
endfunction
virtual task trans_executed(bus_bfm driver, bus_tr tr);
endtask
function new(string name="bus_bfm_cb_inst");
super.new(name);
endfunction
endclass
uvm_callback_iter
The uvm_callback_iter class is an iterator class for iterating over callback queues of a specific callback type. The typical usage of the class is
uvm_callback_iter#(mycomp,mycb) iter = new(this);
for(mycb cb = iter.first(); cb != null; cb = iter.next())
cb.dosomething();
The callback iteration macros, uvm_do_callbacks and uvm_do_callbacks_exit_on provide a simple method for iterating callbacks and executing the callback methods.
The uvm_callback_iter class is an iterator class for iterating over callback queues of a specific callback type.
Class Declaration
class uvm_callback_iter#(type T = uvm_object,type CB = uvm_callback)
Methods:
new:
function new(T obj)
Creates a new callback iterator object. It is required that the object context be provided.

http://www.systemverilog.in/method.php#fragment-3

18/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

first
function CB first()
Returns the first valid (enabled) callback of the callback type (or a derivative) that is in the queue of the context object. If the queue is empty then null is returned.
next
function CB next()
Returns the next valid (enabled) callback of the callback type (or a derivative) that is in the queue of the context object. If there are no more valid callbacks in the
queue, then null is returned.
get_cb:
function CB get_cb()
Returns the last callback accessed via a first() or next() call.
Iterator interface:
This set of functions provide an iterator interface for callback queues. A facade class, uvm_callback_iter is also available, and is the generally preferred way to iterate
over callback queues.
get_first:
static function CB get_first (ref int itr, input T obj)
returns the first enabled callback of type CB which resides in the queue for obj. If obj is null then the type wide queue for T is searched. itr is the iterator; it will be
updated with a value that can be supplied to get_next to get the next callback object. If the queue is empty then null is returned.
The iterator class uvm_callback_iter may be used as an alternative, simplified, iterator interface.
get_next
static function CB get_next (ref int itr, input T obj) returns the next enabled callback of type CB which resides in the queue for obj, using itr as the starting point. If
obj is null then the type wide queue for T is searched. itr is the iterator; it will be updated with a value that can be supplied to get_next to get the next callback
object. If no more callbacks exist in the queue, then null is returned. get_next will continue to return null in this case until get_first has been used to reset the
iterator.
The iterator class uvm_callback_iter may be used as an alternative, simplified, iterator interface.
uvm_callbacks(T,CB):
To enable compile-time type-safety, the class is parameterized on both the user-defined callback interface implementation as well as the object type associated with
the callback. The object type-callback type pair are associated together using the uvm_register_cb macro to define a valid pairing; valid pairings are checked when a
user attempts to add a callback to an object.
To provide the most flexibility for end-user customization and reuse, it is recommended that the component developer also define a corresponding set of virtual
method hooks in the component itself. This affords users the ability to customize via inheritance/factory overrides as well as callback object registration. The
implementation of each virtual method would provide the default traversal algorithm for the particular callback being called. Being virtual, users can define subtypes
that override the default algorithm, perform tasks before and/or after calling super. to execute any registered callbacks, or to not call the base implementation,
effectively disabling that particular hook.
T
This type parameter specifies the base object type with which the CB callback objects will be registered. This object must be a derivative of uvm_object.
CB
This type parameter specifies the base callback type that will be managed by this callback class. The callback type is typically a interface class, which defines one or
more virtual method prototypes that users can override in subtypes. This type must be a derivative of uvm_callback.
Add/delete interface
add
static function void add_by_name(string name, uvm_callback cb,uvm_apprepend ordering = UVM _APPEND)
Registers the given callback object, cb, with the given obj handle. The obj handle can be null, which allows registration of callbacks without an object context. If
ordering is UVM _APPEND (default), the callback will be executed after previously added callbacks, else the callback will be executed ahead of previously added
callbacks. The cb is the callback handle; it must be non-null, and if the callback has already been added to the object instance then a warning is issued. Note that the
CB parameter is optional. For example, the following are equivalent:
uvm_callbacks#(my_comp)::add(comp_a, cb);
uvm_callbacks#(my_comp, my_callback)::add(comp_a,cb);
Use of this add is described in the following example:

http://www.systemverilog.in/method.php#fragment-3

19/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

initial begin
bd_cb::add(driver,cb);
cbs.display_cbs();
for (int i=1; i<=5; i++)
begin
tr.addr = i;
tr.data = 6-i;
driver.in.put(tr);
end
end
endmodule
add_by_name
static function void add_by_name(string name, uvm_callback cb, uvm_component root,uvm_apprepend ordering= UVM _APPEND)
Registers the given callback object, cb, with one or more uvm_components. The components must already exist and must be type T or a derivative. As with add the CB
parameter is optional. root specifies the location in the component hierarchy to start the search for name. See uvm_root::find_all for more details on searching by
name.
delete:
static function void delete(T obj,uvm_callback cb)
Deletes the given callback object, cb, from the queue associated with the given obj handle. The obj handle can be null, which allows de-registration of callbacks
without an object context. The cb is the callback handle; it must be non-null, and if the callback has already been removed to the object instance then a warning is
issued. Note that the CB parameter is optional. For example, the following are equivalent
uvm_callbacks#(my_comp)::delete(comp_a, cb);
uvm_callbacks#(my_comp, my_callback)::delete(comp_a,cb);
Use of these option are described in following examples: mainly taken out from user guide
virtual task run();
cbs = new;
#1000;
bd_cb::add_by_name(cb, top.bfm);
#100;
bd_cb::delete(cb);
endfunction
endclass
uvm_report_catcher
The uvm_report_catcher is used to catch messages issued by the uvm report server. Catchers are uvm_callbacks(uvm_report_object,uvm_report_catcher) object, so all
facilities in the uvm_callback and uvm_callback#(T,CB) classes are available for registering catchers and controlling catcher state. The uvm_callbacks#
(uvm_report_object,uvm_report_catcher) class is aliased to uvm_report_cb to make it easier to use. M ultiple report catchers can be registered with a report object.
The catchers can be registered as default catchers which catch all reports on all uvm_report_object reporters, or catchers can be attached to specific report
objects (i.e. components).
User extensions of uvm_report_catcher must implement the catcher method in which the action to be taken on catching the report is specified. The catch method
can return CAUGHT, in which case further processing of the report is immediately stopped, or return THROW in which case the (possibly modified) report is passed on
to other registered catchers. The catchers are processed in the order in which they are registered.
On catching a report, the catch method can modify the severity, id, action, verbosity or the report string itself before the report is finally issued by the report server.
The report can be immediately issued from within the catcher class by calling the issue method.
The catcher maintains a count of all reports with FATAL,ERROR or WARNING severity and a count of all reports with FATAL, ERROR or WARNING severity whose severity
was lowered. These statistics are reported in the summary of the uvm_report_server.
This example shows the basic concept of creating a report catching callback and attaching it to all messages that get emitted
mainly taken out from user guide
class my_error_demoter extends uvm_report_catcher;
function new(string name="my_error_demoter");
super.new(name);
endfunction
//This example demotes "M Y_ID" errors to an info message
function action_e catch();
if(get_severity() == UVM _ERROR && get_id() == "M Y_ID")
set_severity(UVM _INFO);
return THROW;
endfunction
endclass

my_error_demoter demoter = new;

http://www.systemverilog.in/method.php#fragment-3

20/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

initial begin
// Catchers are callbacks on report objects (components are report
// objects, so catchers can be attached to components).
// To affect all reporters, use null for the object
uvm_report_cb::add(null, demoter);
// To affect some specific object use the specific reporter
uvm_report_cb::add(mytest.myenv.myagent.mydriver, demoter);
// To affect some set of components using the component name
uvm_report_cb::add_by_name("*.*driver", demoter);
end
type-callback registration macro:
`uvm_register_cb:
Registers the given CB callback type with the given T object type. If a type-callback pair is not registered then a warning is issued if an attempt is made to use the pair
(add,delete, etc.).
The registration will typically occur in the component that executes the given type of callback. For instance:
virtual class mycb;
virtual function void doit();
endclass
class my_comp extends uvm_component;
`uvm_register_cb(my_comp,mycb)
...
task run;
...
`uvm_do_callbacks(my_comp, mycb, doit())
endtask
endclass
`uvm_set_super_type macro
Defines the super type of T to be ST. This allows for derived class objects to inherit type wide callbacks that are registered with the base class. The registration will
typically occur in the component that executes the given type of callback. For instance:
virtual class mycb;
virtual function void doit();
endclass
class my_comp extends uvm_component;
`uvm_register_cb(my_comp,mycb)
...
task run;
...
`uvm_do_callbacks(my_comp, mycb, doit())
endtask
endclass
class my_derived_comp extends my_comp;
`uvm_set_super_type(my_derived_comp,my_comp)
...
task run;
...
`uvm_do_callbacks(my_comp, mycb, doit())
endtask
endclass
Tracing objection
Tracing of objection activity can be turned on to follow the activity of the objection mechanism. It may be turned on for a specific objection instance with
uvm_objection::trace_mode, or it can be set for all objections from the command line using the option +UVM _OBJECTION_TRACE.
trace_mode
function bit trace_mode (int mode = -1 )
Set or get the trace mode for the objection object. If no argument is specified (or an argument other than 0 or 1) the current trace mode is unaffected. A
trace_mode of 0 turns tracing off. A trace mode of 1 turns tracing on. The return value is the mode prior to being reset.
Callback Hooks
raised
The raised callback is called when a descendant of the component instance raises the specified objection . The source_obj is the object which originally raised the
object. count is an optional count that was used to indicate a number of objections which were raised.
virtual function void raised (uvm_objection objection,uvm_object source_obj,string description,int count )
dropped

http://www.systemverilog.in/method.php#fragment-3

21/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

The dropped callback is called when a descendant of the component instance raises the specified objection . The source_obj is the object which originally dropped
the object. count is an optional count that was used to indicate a number of objections which were dropped.
virtual function void dropped (uvm_objection objection,uvm_object source_obj,string description,int count )
A typical use model of objections is for a sequence from an active agent to raise an uvm_test_done objection when it is started as a root sequence (a sequence which
has no parent sequence), and to drop the objection when it is finished as a root sequence. This would look like the following:
mainly taken out from user guide
class interesting_sequence extends uvm_sequence#(data_item);
task pre_body();
// raise objection if started as a root sequence
uvm_test_done.raise_objection(this);
endtask
task body();
/do interesting activity
...
endtask
task post_body();
// drop objection if started as a root sequence
uvm_test_done.drop_objection(this);
endtask
endclass
all_dropped:
The all_dropped callback is called when a descendant of the component instance raises the specified objection . The source_obj is the object which originally
all_dropped the object. count is an optional count that was used to indicate a number of objections which were dropped. This callback is time-consuming and the
all_dropped conditional will not be propagated up to the objects parent until the callback returns.
virtual task all_dropped (uvm_objection objection,uvm_object source_obj,string description,int count )
UVM EXAM PLE
UVM , a new verification methodology has more features in developing a verification environment than previous methodologies like OVM and VM M . A verification
environment, which is reusable is composed of bus-functional modules called verification components. Each verification component follows consistent architecture and
encapsulates a complete set of elements for stimulating, checking, and collecting coverage information for a specific design.
Following example projects a detailed information on building of a UVM based environment for specified design. The design is written in verilog and the verification
environment for that design is created using the UVM methodology.
UVM Components
A UVM environment basically has the following components.
1. UVM Transactor
2. UVM Sequencer
3. UVM Sequence
4. UVM Driver
5. UVM M onitor
All these components instantiated in environment, named as UVM environment are connected through interface.
1. UVM Transactor
This is a component which sends stimulus to rest of the testbench. Here, all properties which are very much necessary in developing further environment will be
specified.
All UVM related transaction methods are derived form uvm_transaction. This class(uvm_transaction) extends from the base class uvm_object to include a timing and
recording interface. Here sequence enabled transactions are derived mainly from uvm_sequence_item while simple transactions are derived from uvm_transaction.
The example below illustrates the use of uvm_sequence_item for transaction of a simple vending machine.
class ven_seq_do extends uvm_sequence #(xctor) ;
rand intrst;
rand int data;
function new(string name="ven_seq_do") ;
super.new(name) ;
endfunction
`uvm_sequence_utils_begin(ven_seq_do,sequencer)
`uvm_field_int(rst,UVM _ALL_ON)
`uvm_field_int(data,UVM _ALL_ON)
`uvm_sequence_utils_end
virtual task body() ;
`uvm_info(get_type_name(),"Starting simple sequence", UVM _LOG);
for(int i=0; i<=5; i++)

http://www.systemverilog.in/method.php#fragment-3

22/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

begin
$display("%0t :///////////////////// simple seq started ///////////////////////",$time);
`uvm_do(req)
$display("%0t :///////////////////// simple seq item done ///////////////////////",$time);
end
endtask
endclass : ven_seq_do
We have inbuilt macros in UVM to perform some transaction level operations like copy, compare, print, pack, unpack. In this example, the field macros used within
uvm_*_utils_begin and uvm_*_utils_end are shown.
2. UVM Sequencer
The sequencer generates stimulus data and passes it to a bus functional module for execution. The UVM class library provides the uvm_sequencer, a base class, which
is parameterized by the request and response item types.
Creating a sequencer:
1. Derive a sequencer from uvm_sequencer base class by specifying the request and response type parameters.
2. Use `uvm_updates_sequence_lib_and_item to indicate generated data type.
Example below shows a sequencer
Following points are important for sequencer:
1. Should not use uvm_component_utils for this sequencer since all the methods related to sequencer are embedded in uvm_sequencer_utils. So use of
uvm_sequencer_utils is efficient.
2. `uvm_updates_sequence_lib_and_item should be used within a constructor of sequencer. This macro register all the sequence types that are associated with
current sequencer.
Each `uvm_field_* macro has two arguments like ARG and FLAG
ARG is the instance name of the variable. The variables rst and data are an example.
FLAG as shown is UVM _ALL_ON signifies that ARG will undergo all kinds of methods. Use of UVM _DEFAULT is also allowed.
UVM sequence
This class defines a simple sequence. The sequence-specific macros perform the same function as the set of `uvm_object_*_utils macros, except they set the default
sequencer type and the sequence will run on.
This class is derived from uvm_sequence base class. This class must use the `uvm_sequence_utils. This `uvm_sequence_utils provides necessary environment for
sequence to get associated with relevant sequencer type and declares various automation utilities.
Example for uvm_sequence
M ethods of uvm_sequence:
`uvm_do: This method takes uvm_sequence_item as an argument and does the randomization.
body() : This function specifies the randomization of the uvm_sequence_item transactions.
UVM Driver
The driver's role is to request a data from sequencer and drive the same to interface. The UVM class library provides uvm_driver base class from which all driver classes
will be inherited.
Creating a driver:
1. Derive a driver from the uvm_driver base class
2. Implement utilities in driver if required
3. Declare a virtual interface in the driver to connect the driver to the DUT.
Methods
run() : This task does the actual work of driver. In the following example , seq_item_port, a command through which the driver sends a request to sequencer to obtain
a transaction. On the contrary, get_next_item(req) gets an actual transaction from a sequence.
Example for driver
class driver extends uvm_driver #(xctor) ;
protected virtual intf i_f;
xctor req;
`uvm_component_utils(driver)
function void assign_vi (virtual interface intf if1);
this.i_f = if1;
endfunction
virtual task run ();
$display("INSIDE RUN : DRIVER CLK = %x\n",i_f.clk);
fork

http://www.systemverilog.in/method.php#fragment-3

23/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.


drive_signal();
join

endtask : run
task drive_signal();
forever begin
@(posedge i_f.clk)
seq_item_port.get_next_item(req);
print();
req.print();
i_f.rst = req.rst;
i_f.coin = req.data;
if(i_f.coke == 1)
begin
disp();
end
seq_item_port.item_done();
end
endtask : drive_signal
task disp();
$display("-------------------------------------------------------------------------------------------");
$display("\n");
$display("the time at which the coke is available is = %0gs",$time);
$display("_______________________________________________________________________________COKE IS
AVAILABLE=%d_____________________________________________________________________________",i_f.coke);
$display("\n");
$display("-------------------------------------------------------------------------------------------");
endtask
endclass : driver
UVM Monitor
The monitor is responsible for extracting signal information from the bus and translating it into events and status information. The monitor functionality should be
limited to basic monitoring which is always required.
The following example shows a simple monitor which has the functions that collects the bus information through the virtual interface.
class monitor extends uvm_monitor;
virtual interface intf m_if;
function new(string name,uvm_component parent);
super.new(name,parent);
endfunction
`uvm_component_utils(monitor)
function void assign_vi(virtual interface intf m_if);
this.m_if = m_if;
endfunction
virtual task run();
forever
begin
@(posedge m_if.clk)
print();
begin
$display("@ time %0gs the rst is = %b",$time,m_if.rst);
$display("@ time %0gs the data is = %b",$time,m_if.coin);
$display("============================================\n");
$display(" Time \t output \t value \n");
$display("@ %0gs\t coke \t %b \n",$time,m_if.coke);
$display("============================================\n");
end
end
endtask
endclass : monitor
The collection is done in a task run() phase. It runs in an endless loop and collects the data as soon as the signals indicate that the data is available on the bus.
UVM Environment:
After creating the transaction level verification component, this section describes how to assemble these components into environment. Environment class is the
container of reusable components. It configures and connects all components.
Example for the environment:
Below example shows the phase build() where all components are constructed.
It connects the all the components through interface in a function assign_if.
class env extends uvm_env;
protected virtual interface intf i_f;
monitor mon;

http://www.systemverilog.in/method.php#fragment-3

24/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

sequencer seq;
driver dri;
`uvm_component_utils_begin(env)
`uvm_component_utils_end
function new(string name , uvm_component parent);
super.new(name,parent);
endfunction : new
function void build();
$display("INSIDE BUILD CREATE AN OBJECT");
mon = monitor :: type_id :: create("mon",this);
$display("INSIDE BUILD CREATE AN OBJECT");
dri = driver :: type_id :: create("dri",this);
$display("INSIDE BUILD CREATE AN OBJECT");
seq = sequencer :: type_id :: create("seq",this);
endfunction : build
function void assign_vi(virtual interface intf vif);
this.i_f = vif;
mon.assign_vi(vif);
seq.assign_vi(vif);
dri.assign_vi(vif);
endfunction
endclass : env
UVM Testcase
The uvm_test class defines the test scenario for the testbench specified in the test. The test class enables configuration of the testbench and environment class as
well as utilities for command-line test selection. Tests in UVM are classes that are derived from an uvm_test class. Using classes allows inheritance and reuse of tests.
Instantiating the reusable environment directly inside the tests has several drawbacks:
1. The test writer must know how to configure the environment.
2. Changes to the topology require updating multiple test files, which can turn into a big task.
3. The tests are not reusable because they rely on a specific environment structure.
Example for a testcase is shown below:
class ven_test extends uvm_env;
env env1;
`uvm_component_utils(ven_test)
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction
virtual function void build();
env1 = env :: type_id :: create("env1",this);
endfunction : build
function void connect();
env1.dri.seq_item_port.connect(env1.seq.seq_item_export);
env1.assign_vi(ven_top.i_if);
endfunction : connect
task run();
#10000
global_stop_request();
endtask
endclass
Methods
It has phases like
build() :Creation of environment .
connect() :Connection of driver and sequencer .
run() :To exercise stimulus and a global request is issued to stop the further transaction.
Top module
It is the top module of an entire verification environment. It is where the actual DUT and interface are instantiated.
`include "vending.v"
module ven_top;
//////////////////////////////////////top/////////////////////////////////////////////////
`include "ven_def.sv"
`include "ven_if.sv"
intf i_if();
driver dri;
vending ven(
rst(i_if.rst),

http://www.systemverilog.in/method.php#fragment-3

25/26

4/23/2014

.: SystemVerilog | Resources | Methodology :.

clk(i_if.clk),
coin(i_if.coin),
coke(i_if.coke)
);
initial begin
uvm_report_info("TB", "/////////////////////Starting out testbench/////////////////// \n", , "uday.txt", 2);
run_test();
end
initial begin
i_if.clk=1;
end always #5 i_if.clk = ~i_if.clk;
endmodule : ven_top

Click here to download the UVM example

FEEDBACK

Number of Visits:

http://www.systemverilog.in/method.php#fragment-3

2013 Systemverilog.in, All Rights Reserved, Email us: sv@kacpertech.com


Site best viewed in 1024 * 768px or more

Powered by

26/26

Potrebbero piacerti anche