1_testbench guide for ovm

42
W H I T E P A P E R www.m e n t o r.c o m MENTOR GRAPHICS UVM/ OVM DOCUMENTATION VERIFICATION METHODOLOGY ONLINE COOKBOOK MENTOR GRAPHICS VERIFICATION METHODOLOGY TEAM CONTACT VMDOC@MENTOR.COM HTTP://WWW.MENTOR.COM/PRODUCTS/FV/TECHPUBS

Upload: abhipankaj

Post on 30-Oct-2014

502 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 1_Testbench Guide for OVM

WH

IT

EP

AP

ER

w w w . m e n t o r . c o m

MENTOR GRAPHICS UVM/OVM DOCUMENTATIONVERIFICATION METHODOLOGY ONLINE COOKBOOK

MENTOR GRAPHICS VERIFICATION METHODOLOGY TEAMCONTACT [email protected] TP://WWW.MENTOR.COM/PRODUCTS/FV/ TECHPUBS

Page 2: 1_Testbench Guide for OVM

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.comPDF generated at: Fri, 08 Jul 2011 17:30:57 PST

Testbench Guide for OVMlearn the basics and details of OVMtestbench architecture

Page 3: 1_Testbench Guide for OVM

Table of ContentsArticles

Ovm/Testbench/Overview 1Ovm/Testbench/Build 6Ovm/Testbench/Blocklevel 13Ovm/Testbench/IntegrationLevel 21Ovm/Agent 28OVM Phases 33OVM Factory 36

Datestamp:- This document is a snapshot of dynamic content from the Online Methodology Cookbook

- Created from http://uvm.mentor.com on Fri, 08 Jul 2011 10:30:58 PDT

Page 4: 1_Testbench Guide for OVM

Ovm/Testbench/Overview 1

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

Ovm/Testbench/Overview

You are reading the OVM version of this article. You can find the new UVM version at [[]]

How an OVM testbench differs from a traditional module based testbenchIn Verilog or VHDL, a testbench consists of a hierarchy of modules containing testbench code that are connected to thedesign under test (DUT). The modules contain stimulus and response checking code which is loaded into simulatormemory along with the DUT at the beginning of the simulation and is present for the duration of the simulation.Therefore, the classic Verilog testbench wrapped around a DUT consists of what are known as static objects.SystemVerilog builds on top of Verilog by adding abstract language constructs targetted at helping the verificationprocess. One of the key additions to the language was the class. SystemVerilog classes allow Object OrientatedProgramming (OOP) techniques to be applied to testbenches. The OVM itself is a library of base classes which facilitatethe creation of structured testbenches using code which is open source and can be run on any SystemVerilog IEEE 1800simulator.Like classes in any other OOP language such as C++ and Java, SystemVerilog class definitions are templates for anobject that is constructed in memory. Once created, that object persists in memory until it is de-referenced and garbagecollected by an automatic background process. The class template defines the members of the class which can either bedata variables or methods. In SystemVerilog, the methods can either be functions which are non-time consuming, ortasks which can consume time. Since a class object has to be constructed before it exists in memory the creation of aclass hierarchy in a SystemVerilog testbench has to be initiated from a module since a module is a static object that ispresent at the beginning of the simulation. For the same reason, a class cannot contain a module. Classes are referred toas dynamic objects because they can come and go during the life time of a simulation.

//// Example to show how a class is constructed from within a static object (a module)//

//// Example class that contains a message and some convenience methods//class example;

string message;

function void set_message(string ip_string); message = ip_string;endfunction: set_message

function void print(); $display("%s", message);endfunction: print

endclass: example

//// Module that uses the class - class is constructed, used and dereferenced// in the initial block, after the simulation starts//module tb;

example C; // Null handle after elaboration

initial begin C = new(); // Handle points to C object in memory C.set_message("This ojbect has been created");

Page 5: 1_Testbench Guide for OVM

Ovm/Testbench/Overview 2

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

#10; C.print(); C = null; // C has been deferenced, object can be garbage collectedend

endmodule: tb

The OVM PackageThe OVM package contains a class library that comprises three main types of classes, ovm_components which are usedto construct a class based hierarchical testbench structure, ovm_objects which are used as data structures forconfiguration of the testbench and ovm_transactions which are used in stimulus generation and analysis.An OVM testbench will always have a top level module which contains the DUT and the testbench connections to it. Theprocess of connecting a DUT to an OVM class based testbench is described in the article on DUT- testbenchconnections.The top level module will also contain an initial block which will contain a call to the OVM run_test() method.This method starts the execution of the OVM phases, which controls the order in which the testbench is built, stimulusis generated and then reports on the results of the simulation.

OVM testbench HierarchyOVM testbenches are built from classes derived from the ovm_component base class. The testbench hierarchy isdetermined by a series of 'has-a' class relationships, in other words which components contain which other components.The top level class in an OVM testbench is usually known as the test class and this class is responsible for configuringthe testbench, initiating the construction process by building the next level down in the hierarchy and by initiating thestimulus by starting the main sequence. For a given verification environment, the testbench hierararchy below the testclass is reasonably consistent, and each test case is implemented by extending a test base class.The OVM testbench architecture is modular to facilitate the reuse of groups of verification components either in differentprojects (horizontal reuse) or at a higher level of integration in the same project (vertical reuse). There are two maincollective component types used to enable reuse - the env (short for environment) and the agent.

Page 6: 1_Testbench Guide for OVM

Ovm/Testbench/Overview 3

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

The Agent

Active agent.gif

Most DUTs have a number of different signalinterfaces, each of which have their ownprotocol. The OVM agent collects together agroup of ovm_components focused around aspecific pin-level interface. The purpose of theagent is to provide a verification componentwhich allows users to generate and monitorpin level transactions. A SystemVerilogpackage  is used to gather all the classesassociated with an agent together in onenamespace. The contents of an agent packagewill usually include:

• A Sequence_item -The agent will haveone or more sequence items which are usedto either define what pin level activity willbe generated by the agent or to report onwhat pin level activity has been observed by the agent.

• A Driver - The driver is responsible for converting the data inside a series of sequence_items into pin leveltransactions.

• A Sequencer - The role of the sequencer is to route sequence_items from a sequence where they are generatedto/from a driver.

• A Monitor - The monitor observes pin level activity and converts its observations into sequence_items which are sentto components such as scoreboards which use them to analyse what is happening in the testbench.

• Configuration object - A container object, used to pass information to the agent which affects what it does and howit is built and connected.

Each agent should have a configuration object, this will contain a reference to the virtual interface which the driver andthe monitor use to access pin level signals. The configuration object will also contain other data members which willcontrol which of the agents sub-components are built, and it may also contain information that affects the behaviour ofthe agents components (e.g. error injection, or support for a protocol variant)The agent configuration object contains an active bit which can be used to select whether the agent is passive - i.e. thedriver and sequencer are not required, or active. It may also contain other fields which control whether othersub-component classes such as functional coverage monitors or scoreboards get built or not.Other classes that might be included in an agent package:• Functional coverage monitor - to collect protocol specific functional coverage information• Scoreboard - usually of limited use• A responder - A driver that responds to bus events rather than creating them (i.e. a slave version of the driver rather

than a master version).• (API) Sequences - Utility sequences likely to be of general use, often implementing an API layer for the driver.

Page 7: 1_Testbench Guide for OVM

Ovm/Testbench/Overview 4

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

The env

The environment, or env, is a container component for grouping together sub-components orientated around a block, oraround a collection of blocks at higher levels of integration.

Block Level env

In a block level OVM testbench, the environment, or env, is used to collect together the agents needed for the DUTsinterfaces together. Like the agent, the different classes associated with the env are organised into a SystemVerilogpackage, which will import the agent packages. In addition to the agents the env will also contain some or all of thefollowing types of components:• Configuration object - The env will have

a configuration object that enables the testwriter to control which of the environmentssub-components are built. The envconfiguration object should also contain ahandle for the configuration object for eachof the agents that it contains. These arethen assigned to the envs agents usingset_config_object.

• Scoreboards - A scoreboard is an analysiscomponent that checks that the DUT isbehaving correctly. OVM scoreboards useanalysis transactions from the monitorsimplemented inside agents. A scoreboard will usually compare transactions from at least two agents, which is why itis usually present in the env.

• Predictors - A predictor is a component that computes the response expected from the stimulus, it is generally used inconjunction with other components such as the scoreboard.

• Functional Coverage Monitors - A functional coverage monitor analysis component contains one or morecovergroups which are used to gather functional coverage information relating to what has happened in a <spanstyle="background-color: navy; color: white;" />testbench during a test case. A functional coverage monitor is usuallyspecific to a DUT.

• Virtual Sequencers - A virtual sequencer is used in the stimulus generation process to allow a single sequence tocontrol activity via several agents.

The diagram shows a block level testbench which consists of a series of tests which build an env which contains severalanalysis components and two agents.

Page 8: 1_Testbench Guide for OVM

Ovm/Testbench/Overview 5

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

Integration Level env

When blocks are integrated to create a sub-system, vertical reuse can be achieved by reusing the envs used in each of the

Integration level ovm hierarchy.gif

block level testbenches merged together into ahigher level env. The block level envs provideall of the structures required to test eachblock, but as a result of the integrationprocess, not all the block level interfaces areexposed at the boundary and so some of thefunctionality of the block level envs will beredundant. The integration level env thenneeds to be configured to make agentsconnected to internal interfaces passive, orpossibly even not to include an agent at all.This configuration is done in the test, and theconfiguration object for each sub-env isnested inside the configuration object for theenv at the next level of hiearchy.As an illustration, the diagram shows a firstlevel of integration where two block levelenvironments have been merged together totest the peripheral file. The 'greyed out'components in the envs are components thatare no longer used in the integration level envrionment. The configuration object for the integration level contains therest of the configuration objects nested inside it.Further levels of integration can be accomodated by layering multiple integration level envs inside eachother.

The OVM testbench Build And Connection ProcessBefore an OVM testbench can start to apply stimulus its component hierarchy has to be built and the connectionsbetween the verification components has to be made. The process for configuring and building agents, block level andintegration level OVM testbenches is described in the article on building OVM testbenches.

Page 9: 1_Testbench Guide for OVM

Ovm/Testbench/Build 6

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

Ovm/Testbench/Build

You are reading the OVM version of this article. You can find the new UVM version at [[]]

The first phase of an OVM testbench is thebuild phase. During this phase theovm_component classes that make up thetestbench hierarchy are constructed intoobjects. The construction process workstop-down with each level of the hierarchybeing constructed before the next level isconfigured and constructed. This approach toconstruction is referred to as deferredconstruction.

The OVM testbench is is activated when therun_test() method is called in an initial blockin the top level test module. This method is anOVM static method, and it takes a stringargument or a string passed in from the+OVM_TESTNAME plusarg that defines the test to be run and constructs it via the factory. The +OVM_TESTNAMEtakes precedence over a string argument passed into run_test().  Then the OVM infrastructure starts the build phase bycalling the test classes build methodDuring the execution of the tests build phase, the testbench component configuration objects are prepared andassignments to the testbench module interfaces are made to the virtual interface handles in the configuration objects. Thenext step is for the configuration objects to be put into the tests configuration table. Finally the next level of hierarchy isbuilt.At the next level of hierarchy the configuration object prepared by the test is "got" and further configuration may takeplace, before the configuration object is used to guide the configuration and conditional construction of the next level ofhierarchy. This conditional construction affects the topology or hierarchical structure of the testbench.The build phase works top-down and so the process is repeated for the each successive level of the testbench hiearchyuntil the bottom of the hierarchical tree is reached.After the build phase has completed, the connect phase is used to ensure that all intra-component connections are made.The connect phase works from the bottom to the top of the testbench hierarchy. Following the connect phase, the rest ofthe OVM phases run to completion before control is passed back to the testbench module.

Page 10: 1_Testbench Guide for OVM

Ovm/Testbench/Build 7

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

The Test Is The Starting Point For The Build ProcessThe build process for an OVM testbench starts from the test class and works top-down. The test class build method is thefirst to be called during the build phase and what the test method sets up determines what gets built in an OVMtestbench. The function of the tests build method is to:• Set up any factory overrides so that configuration objects or component objects are created as derived types• Create and configure the configuration objects required by the various sub-components• Assign any virtual interface handles put into configuration space by the testbench module• Build up a nested env configuration object which is then set into configuration space• Build the next level down in the testbench hierarchy, usually the top-level envFor a given design verification environment most of the work done in the build method will be the same for all the tests,so it is recommended that a test base class is created which can be easily extended for each of the test cases.To help explain how the test build process works, a block level verification environment will be referred to. Thisexample is an environment for an SPI master interface DUT and it contains two agents, one for its APB bus interface andone for its SPI interface. A detailed account of the build and connect processes for this example can be found in theBlock Level Testbench Example article.

Factory Overrides

The OVM factory allows an OVM classto be substituted with another derivedclass at the point of construction.This facility can be useful forchanging or updatingcomponent behaviour or for extending aconfiguration object. The factoryoverride must be specified before thetarget object is constructed, so it isconvenient to do it at the start ofthe build process.

Sub-Component ConfigurationObjects

Each collective component such as an agent or an env should have a configuration object which defines their structureand behaviour. These configuration objects should be created in the test build method and configured according to therequirements of the test case. If the configuration of the sub-component is either complex or is likely to change then it isworth adding a function call to take care of the configuration, since this can be overloaded in test cases extending fromthe base test class.

`ifndef SPI_TEST_BASE`define SPI_TEST_BASE

//// Class Description:////class spi_test_base extends ovm_test;

Page 11: 1_Testbench Guide for OVM

Ovm/Testbench/Build 8

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

// OVM Factory Registration Macro//`ovm_component_utils(spi_test_base)

//------------------------------------------// Data Members//------------------------------------------

//------------------------------------------// Component Members//------------------------------------------// The environment classspi_env m_env; // Configuration objectsspi_env_config m_env_cfg;apb_agent_config m_apb_cfg;spi_agent_config m_spi_cfg;

//------------------------------------------// Methods//------------------------------------------

// Standard OVM Methods:extern function new(string name = "spi_test_base", ovm_component parent = null);extern function void build();extern funciton void configure_env(spi_env_config cfg);extern funciton void configure_apb_agent(apb_agent_config cfg);

endclass: spi_test_base

function spi_test_base::new(string name = "spi_test_base", ovm_component parent = null); super.new(name, parent);endfunction

// Build the env, create the env configuration// including any sub configurations and assigning virtural interfacesfunction void spi_test_base::build(); // Create env configuration object m_env_cfg = spi_env_config::type_id::create("m_env_cfg"); // Call function to configure the env configure_env(m_env_cfg); // Create apb agent configuration object m_apb_cfg = apb_agent_config::type_id::create("m_apb_cfg"); // Call function to configure the apb_agent configure_apb_agent(m_apb_cfg);// More to followendfunction: build

//// Convenience function to configure the env// // This can be overloaded by extensions to this base classfunction void spi_test_base::configure_env(spi_env_config cfg); cfg.has_functional_coverage = 1; cfg.has_reg_scoreboard = 0; cfg.has_spi_scoreboard = 1;endfunction: configure_apb_agent

//// Convenience function to configure the apb agent// // This can be overloaded by extensions to this base classfunction void spi_test_base::configure_apb_agent(apb_agent_config cfg); cfg.active = OVM_ACTIVE; cfg.has_functional_coverage = 0; cfg.has_scoreboard = 0;endfunction: configure_apb_agent

`endif // SPI_TEST_BASE

Page 12: 1_Testbench Guide for OVM

Ovm/Testbench/Build 9

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

Assigning Virtual Interfaces From The Configuration SpaceBefore the OVM run_test() method is called, the links to the signals on the top level I/O boundary of the DUT shouldhave been made by connecting them to SystemVerilog interfaces and then a handle to each interface should have beenassigned to a virtual interface handle which was wrapped inside a virtual interface container object. See the article onvirtual interfaces for more information on this topic.In the test build method, these virtual interface references need to be assigned to the virtual interface handles inside therelevant component configuration objects. Then, individual components access the virtual interface handle inside theirconfiguration object in order to drive or monitor DUT signals. In order to keep components modular and reusable driversand monitors should not get their virtual interface pointers directly from configuration space, only from theirconfiguration object. The test class is the correct place to ensure that the virtual interfaces are assigned to the rightverification components via their configuration objects.The following code shows how the the SPI testbench example uses the ovm_container to make virtual interfaceassignments to the virtual interface handle in the apb_agents configuration object:

// The build method from before, adding the apb agent virtual interface assignment// Build the env, create the env configuration// including any sub configurations and assigning virtural interfacesfunction void spi_test_base::build(); // Create env configuration object m_env_cfg = spi_env_config::type_id::create("m_env_cfg"); // Call function to configure the env configure_env(m_env_cfg); // Create apb agent configuration object m_apb_cfg = apb_agent_config::type_id::create("m_apb_cfg"); // Call function to configure the apb_agent configure_apb_agent(m_apb_cfg); // Adding the apb virtual interface: m_apb_cfg.APB = ovm_container #(virtual apb_if)::get_value_from_config(this, "APB_vif");// More to followendfunction: build

Nesting Sub-Component Configuration ObjectsConfiguration objects are passed to sub-components via the OVM component configuration space from the test. Theycan be passed individually, using the path argument in the set_config_object() method to control which components canaccess the objects, however a common requirement is that intermediate components also need to do some localconfiguration.Therefore, an effective way to approach the passing of configuration objects through a testbench hierarchy is to nest theconfiguration objects inside each other in a way that reflects the hierarchy itself. At each intermediate level in thetestbench, the configuration object for that level is unpacked and then its sub-configuration objects are re-configured (ifnecessary) and then passed to the relevant components using set_config_object().Following the SPI block level envrionment example, each of the agents will have a separate configuration object. Theenvs configuration object will have a handle for each of the agents configuration object. In the test, all of theconfiguration objects will be constructed and configured from the test case viewpoint, then the agent configuration objecthandles inside the env configuration object will be assigned to the actual agent configuration objects. Then the envconfiguration object would be set into the configuration space, to be retrieved when the env is built.

Page 13: 1_Testbench Guide for OVM

Ovm/Testbench/Build 10

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

For more complex environments,additional levels of nesting will berequired.

//// Configuration object for the spi_env://`ifndef SPI_ENV_CONFIG`define SPI_ENV_CONFIG

//// Class Description:////class spi_env_config extends ovm_object;

// OVM Factory Registration Macro//`ovm_object_utils(spi_env_config)

//------------------------------------------// Data Members//------------------------------------------// Whether env analysis components are used:bit has_functional_coverage = 1;bit has_reg_scoreboard = 0;bit has_spi_scoreboard = 1;

// Configurations for the sub_componentsapb_config m_apb_agent_cfg;spi_agent_config m_spi_agent_cfg;

//------------------------------------------// Methods//------------------------------------------

// Standard OVM Methods:extern function new(string name = "spi_env_config");

endclass: spi_env_config

function spi_env_config::new(string name = "spi_env_config"); super.new(name);endfunction

`endif // SPI_ENV_CONFIG

//// Inside the spi_test_base class, the agent config handles are assigned://// The build method from before, adding the apb agent virtual interface assignment// Build the env, create the env configuration// including any sub configurations and assigning virtural interfacesfunction void spi_test_base::build(); // Create env configuration object m_env_cfg = spi_env_config::type_id::create("m_env_cfg");

Page 14: 1_Testbench Guide for OVM

Ovm/Testbench/Build 11

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

// Call function to configure the env configure_env(m_env_cfg); // Create apb agent configuration object m_apb_cfg = apb_agent_config::type_id::create("m_apb_cfg"); // Call function to configure the apb_agent configure_apb_agent(m_apb_cfg); // Adding the apb virtual interface: m_apb_cfg.APB = ovm_container #(virtual apb_if)::get_value_from_config(this, "APB_vif"); // Assign the apb_angent config handle inside the env_config: m_env_cfg.m_apb_agent_cfg = m_apb_cfg; // Repeated for the spi configuration object m_spi_cfg = spi_agent_config::type_id::create("m_spicfg"); configure_spi_agent(m_spi_cfg); m_spi_cfg.SPI = ovm_container #(virtual spi_if)::get_value_from_config(this, "SPIvif"); m_env_cfg.m_spi_agent_cfg = m_spi_cfg; // Now env config is complete set it into config space: set_config_object("*", "spi_env_config", m_env_cfg, 0); // Now we are ready to build the spi_env: m_env = spi_env::type_id::create("m_env", this);endfunction: build

Building The Next Level Of HierarchyThe final stage of the test build process is to build the next level of testbench hierarchy using the OVM factory. Thisusually means building the top level env, but there could be more than one env or there could be a conditional build witha choice being made between several envs.

Coding Convention - Name ArgumentFor Factory Create Method ShouldMatch Local Handle

The create method takes two arguments,one is a name string and the other ispointer to the parent ovm_componentclass object. The values of thesearguments are used to create an entry ina linked list which the OVM uses tolocate ovm_components in a pusedohierarchy, this list is used in themessaging and configurationmechanisms. By convention, the nameargument string should be the same asthe declaration handle of the componentand the parent argument should be "this"so that it refers to the ovm_component inwhich the component is being created.Using the same name as the handle makes it easier to cross reference paths and handles. In the previous code snippet, thespi_env is created in the test using its declaration handle m_env. This means that, after the end of the build process, theOVM path to the spi_env would be "spi_test.m_env".

Page 15: 1_Testbench Guide for OVM

Ovm/Testbench/Build 12

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

Hierarchical Build ProcessThe build phase in the OVM works top down. Once the test class has been constructed, its build method is called, andthen the build method of its child(ren) is called. In turn, the build methods of each of the child nodes through thetestbench tree are called until the whole hierarchy has been constructed. This deferred approach to construction meansthat each build method can affect what happens in the build process of components at lower levels in the testbenchhierarchy. For instance, if an agent is configured to be passive, the build process for the agent omits the creation of theagents sequencer and driver since these are only required if the agent is active.

The Hierarchical ConnectionProcess

Once the build phase has completed, theOVM testbench component hierarchy isin place and the individual componentshave been constructed and linked intothe component hierarchy linked list. Theconnect phase follows the build phase,and works from the bottom of thehierarchy tree to the top and its purposeis to make connections between TLMclasses, assign virtual interface pointersto their handles and to make any otherassignments to resources such as virtualsequencer sub-sequencers.Configuration objects are used duringthe connection process since they makecontain references to virtual interfaces orthey may contain information that guidesthe connection process. For instance,inside an agent, the virtual interfaceassignment to a driver and the TLM connection between a driver and its sequencer can only be made if the agent isactive.

ExamplesThe build process is best illustrated by looking at some examples to illustrate how different types of component hierarchyare built up:A block level testbench containing an agentAn integration level testbench

Page 16: 1_Testbench Guide for OVM

Ovm/Testbench/Blocklevel 13

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

Ovm/Testbench/Blocklevel

You are reading the OVM version of this article. You can find the new UVM version at [[]]

Block level ovm hierarchy.gif

As an example of a block level test bench, weare going to consider a test bench built toverify a SPI Master DUT. In this case, theOVM environment has two agents - an APBagent to handle bus transfers on its APB slaveport, and a SPI agent to handle SPI protocoltransfers on its SPI port. The structure of theoverall OVM verification environment is asillustrated in the block diagram. We shall gothrough each layer of the test bench anddescribe how it is put together from the topdown.

The Test Bench Module

The top level test bench module is used to encapsulate the SPI Master DUT and connect it to the apb_if and spi_ifSystemVerilog interfaces. There is also an initial block which generates a clock and a reset signal for the APB interface.In the initial block of the test bench, handles for the APB, SPI and INTR (interrupt) virtual interfaces are put into theOVM top configuration space using the set_value_in_global_config() method in the ovm_container. Then therun_test() method is called - this causes the specified test to be constructed and the processing of the OVM phases tostart.

module top_tb;

`include "timescale.v"

import ovm_pkg::*;import ovm_container_pkg::*;import spi_test_lib_pkg::*;

// PCLK and PRESETn//logic PCLK;logic PRESETn;

//// Instantiate the interfaces://apb_if APB(PCLK, PRESETn); // APB interfacespi_if SPI(); // SPI Interfaceintr_if INTR(); // Interrupt

// DUTspi_top DUT( // APB Interface: .PCLK(PCLK), .PRESETN(PRESETn), .PSEL(APB.PSEL[0]), .PADDR(APB.PADDR[4:0]), .PWDATA(APB.PWDATA), .PRDATA(APB.PRDATA), .PENABLE(APB.PENABLE),

Page 17: 1_Testbench Guide for OVM

Ovm/Testbench/Blocklevel 14

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

.PREADY(APB.PREADY), .PSLVERR(), .PWRITE(APB.PWRITE), // Interrupt output .IRQ(INTR.IRQ), // SPI signals .ss_pad_o(SPI.cs), .sclk_pad_o(SPI.clk), .mosi_pad_o(SPI.mosi), .miso_pad_i(SPI.miso));

// OVM initial block:// Virtual interface wrapping & run_test()initial begin ovm_container #(virtual apb_if)::set_value_in_global_config("APB_vif" , APB); ovm_container #(virtual spi_if)::set_value_in_global_config("SPI_vif" , SPI); ovm_container #(virtual intr_if)::set_value_in_global_config("INTR_vif", INTR); run_test(); $finish;end

//// Clock and reset initial block://initial begin PCLK = 0; PRESETn = 0; repeat(8) begin #10ns PCLK = ~PCLK; end PRESETn = 1; forever begin #10ns PCLK = ~PCLK; endend

endmodule: top_tb

The TestThe next phase in the OVM construction process is the build phase. For the SPI block level example this means buildingthe spi_env component, having first created and prepared all of the configuration objects that are going to be used by theenvironment. The configuration and build process is likely to be common to most test cases, so it is usually good practiceto create a test base class that can be extended to create specific tests.In SPI example, the configuration object for the spi_env contains handles for the SPI and APB configuration objects, thisallows the env configuration object to be used to pass all of the configuration objects to the env. The build method in thespi_env is then responsible for passing on these sub-configurations. This "Russian Doll" approach to nestingconfigurations is used since it is scalable for many levels of hierarchy.Before the configuration objects for the agents are assigned to their handles in the env configuration block, they areconstructed, have their virtual interfaces assigned, using the ovm_container get_value_from_config() method, and thenthey are configured. The APB agent may well be configured differently between test cases and so its configurationprocess has been split out into a separate virtual method in the base class, this allows inheriting test classes to overloadthis method and configure the APB agent differently.The following code is for the spi_test_base class:

`ifndef SPI_TEST_BASE`define SPI_TEST_BASE

//// Class Description:

Page 18: 1_Testbench Guide for OVM

Ovm/Testbench/Blocklevel 15

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

////class spi_test_base extends ovm_test;

// OVM Factory Registration Macro//`ovm_component_utils(spi_test_base)

//------------------------------------------// Data Members//------------------------------------------

//------------------------------------------// Component Members//------------------------------------------// The environment classspi_env m_env;// Configuration objectsspi_env_config m_env_cfg;apb_agent_config m_apb_cfg;spi_agent_config m_spi_cfg;// Register mapspi_register_map spi_rm;

//------------------------------------------// Methods//------------------------------------------extern virtual function void configure_apb_agent(apb_agent_config cfg);// Standard OVM Methods:extern function new(string name = "spi_test_base", ovm_component parent = null);extern function void build();

endclass: spi_test_base

function spi_test_base::new(string name = "spi_test_base", ovm_component parent = null); super.new(name, parent);endfunction

// Build the env, create the env configuration// including any sub configurations and assigning virtural interfacesfunction void spi_test_base::build(); m_env_cfg = spi_env_config::type_id::create("m_env_cfg"); // Register map - Keep reg_map a generic name for vertical reuse reasons spi_rm = new("reg_map", null); m_env_cfg.spi_rm = spi_rm; m_apb_cfg = apb_agent_config::type_id::create("m_apb_cfg"); configure_apb_agent(m_apb_cfg); m_apb_cfg.APB = ovm_container #(virtual apb_if)::get_value_from_config(this, "APB_vif"); m_env_cfg.m_apb_agent_cfg = m_apb_cfg; // The SPI is not configured as such m_spi_cfg = spi_agent_config::type_id::create("m_spi_cfg"); m_spi_cfg.SPI = ovm_container #(virtual spi_if)::get_value_from_config(this, "SPI_vif"); m_spi_cfg.has_functional_coverage = 0; m_env_cfg.m_spi_agent_cfg = m_spi_cfg; // Insert the interrupt virtual interface into the env_config: m_env_cfg.INTR = ovm_container #(virtual intr_if)::get_value_from_config(this, "INTR_vif"); set_config_object("*", "spi_env_config", m_env_cfg, 0); m_env = spi_env::type_id::create("m_env", this); // Override for register adapter: register_adapter_base::type_id::set_inst_override(apb_register_adapter::get_type(), "spi_bus.adapter");endfunction: build

//// Convenience function to configure the apb agent//// This can be overloaded by extensions to this base classfunction void spi_test_base::configure_apb_agent(apb_agent_config cfg); cfg.active = OVM_ACTIVE; cfg.has_functional_coverage = 0; cfg.has_scoreboard = 0; // SPI is on select line 0 for address range 0-18h cfg.no_select_lines = 1; cfg.start_address[0] = 32'h0;

Page 19: 1_Testbench Guide for OVM

Ovm/Testbench/Blocklevel 16

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

cfg.range[0] = 32'h18;endfunction: configure_apb_agent

`endif // SPI_TEST_BASE

To create a specific test case the spi_test_base class is extended, and this allows the test writer to take advantage of theconfiguration and build process defined in the parent class and means that he only needs to add a run method. In thefollowing (simplistic and to be updated) example, the run method instantiates a virtual sequence and starts it on thevirtual sequencer in the env. All of the configuration process is carried out by the super.build() method call in the buildmethod.

`ifndef SPI_TEST`define SPI_TEST

//// Class Description:////class spi_test extends spi_test_base;

// OVM Factory Registration Macro//`ovm_component_utils(spi_test)

//------------------------------------------// Methods//------------------------------------------

// Standard OVM Methods:extern function new(string name = "spi_test", ovm_component parent = null);extern function void build();extern task run();

endclass: spi_test

function spi_test::new(string name = "spi_test", ovm_component parent = null); super.new(name, parent);endfunction

// Build the env, create the env configuration// including any sub configurations and assigning virtural interfacesfunction void spi_test::build(); super.build();endfunction: build

task spi_test::run; check_reset_seq reset_test_seq = check_reset_seq::type_id::create("rest_test_seq"); send_spi_char_seq spi_char_seq = send_spi_char_seq::type_id::create("spi_char_seq");

reset_test_seq.start(m_env.m_v_sqr.apb); spi_char_seq.start(m_env.m_v_sqr.apb); #100ns; global_stop_request();endtask: run

`endif // SPI_TEST

Page 20: 1_Testbench Guide for OVM

Ovm/Testbench/Blocklevel 17

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

The envThe next level in the SPI OVM environment is the spi_env. This class contains a number of sub-components, namely theSPI and APB agents, a scoreboard, a functional coverage monitor and a virtual sequencer. Which ofthese sub-components gets built is determined by variables in the spi_env configuration object.In this case, the spi_env configuration object also contains a virtual interface and a method for detecting an interrupt.This will be used by sequences running on the virtual sequencer. The contents of the spi_env_config class are asfollows:

`ifndef SPI_ENV_CONFIG`define SPI_ENV_CONFIG

//// Class Description:////class spi_env_config extends ovm_object;

localparam string s_my_config_id = "spi_env_config";localparam string s_no_config_id = "no config";localparam string s_my_config_type_error_id = "config type error";

// OVM Factory Registration Macro//`ovm_object_utils(spi_env_config)

// Interrupt Virtual Interface - used in the wait for interrupt task//virtual intr_if INTR;

//------------------------------------------// Data Members//------------------------------------------// Whether env analysis components are used:bit has_functional_coverage = 0;bit has_spi_functional_coverage = 1;bit has_reg_scoreboard = 0;bit has_spi_scoreboard = 1;// Whether the various agents are used:bit has_apb_agent = 1;bit has_spi_agent = 1;// Whether the virtual sequencer is used:bit has_virtual_sequencer = 1;// Configurations for the sub_componentsapb_agent_config m_apb_agent_cfg;spi_agent_config m_spi_agent_cfg;// SPI Register modelovm_register_map spi_rm;

//------------------------------------------// Methods//------------------------------------------extern static function spi_env_config get_config( ovm_component c);extern task wait_for_interrupt;extern function bit is_interrupt_cleared;// Standard OVM Methods:extern function new(string name = "spi_env_config");

endclass: spi_env_config

function spi_env_config::new(string name = "spi_env_config"); super.new(name);endfunction

//// Function: get_config//// This method gets the my_config associated with component c. We check for// the two kinds of error which may occur with this kind of

Page 21: 1_Testbench Guide for OVM

Ovm/Testbench/Blocklevel 18

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

// operation.//function spi_env_config spi_env_config::get_config( ovm_component c ); ovm_object o; spi_env_config t;

if( !c.get_config_object( s_my_config_id , o , 0 ) ) begin c.ovm_report_error( s_no_config_id , $psprintf("no config associated with %s" , s_my_config_id ) , OVM_NONE , `ovm_file , `ovm_line ); return null; end

if( !$cast( t , o ) ) begin c.ovm_report_error( s_my_config_type_error_id , $psprintf("config %s associated with config %s is not of type my_config" , o.sprint() , s_my_config_id ) , OVM_NONE , `ovm_file , `ovm_line ); end

return t;endfunction

// This task is a convenience method for sequences waiting for the interrupt// signaltask spi_env_config::wait_for_interrupt; @(posedge INTR.IRQ);endtask: wait_for_interrupt

// Check that interrupt has cleared:function bit spi_env_config::is_interrupt_cleared; if(INTR.IRQ == 0) return 1; else return 0;endfunction: is_interrupt_cleared

`endif // SPI_ENV_CONFIG

In this example, there are build configuration field bits for each sub-component. This gives the env the ultimateflexibility for reuse.During the spi_envs build phase, a pointer to the spi_env_config is retrieved from the tests configuration table usingget_config(). Then the build process tests the various has_<sub_component> fields in the configuration object todetermine whether to build a sub-component. In the case of the APB and SPI agents, there is an additional step which isto unpack the configuration objects for each of the agents from the envs configuration object and then to set theagent configuration objects in the envs configuration table after any local modification.In the connect phase, the spi_env configuration object is again used to determine which TLM connections to makeand which pointers to assign to the sequencer handles in the virtual sequencer.

`ifndef SPI_ENV`define SPI_ENV

//// Class Description:////class spi_env extends ovm_env;

// OVM Factory Registration Macro//`ovm_component_utils(spi_env)//------------------------------------------// Data Members//------------------------------------------apb_agent m_apb_agent;

Page 22: 1_Testbench Guide for OVM

Ovm/Testbench/Blocklevel 19

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

spi_agent m_spi_agent;spi_env_config m_cfg;spi_register_coverage m_reg_cov_monitor;spi_reg_functional_coverage m_func_cov_monitor;spi_virtual_sequencer m_v_sqr;spi_scoreboard m_scoreboard;//------------------------------------------// Constraints//------------------------------------------

//------------------------------------------// Methods//------------------------------------------

// Standard OVM Methods:extern function new(string name = "spi_env", ovm_component parent = null);extern function void build();extern function void connect();

endclass:spi_env

function spi_env::new(string name = "spi_env", ovm_component parent = null); super.new(name, parent);endfunction

function void spi_env::build(); m_cfg = spi_env_config::get_config(this); if(m_cfg.has_apb_agent) begin set_config_object("m_apb_agent*", "apb_agent_config", m_cfg.m_apb_agent_cfg, 0); m_apb_agent = apb_agent::type_id::create("m_apb_agent", this); end if(m_cfg.has_spi_agent) begin set_config_object("m_spi_agent*", "spi_agent_config", m_cfg.m_spi_agent_cfg, 0); m_spi_agent = spi_agent::type_id::create("m_spi_agent", this); end if(m_cfg.has_virtual_sequencer) begin m_v_sqr = spi_virtual_sequencer::type_id::create("m_v_sqr", this); end if(m_cfg.has_functional_coverage) begin m_reg_cov_monitor = spi_register_coverage::type_id::create("m_reg_cov_monitor", this); end if(m_cfg.has_spi_functional_coverage) begin m_func_cov_monitor = spi_reg_functional_coverage::type_id::create("m_func_cov_monitor", this); end if(m_cfg.has_spi_scoreboard) begin m_scoreboard = spi_scoreboard::type_id::create("m_scoreboard", this); endendfunction:build

function void spi_env::connect(); if(m_cfg.has_virtual_sequencer) begin if(m_cfg.has_spi_agent) begin m_v_sqr.spi = m_spi_agent.m_sequencer; end if(m_cfg.has_apb_agent) begin m_v_sqr.apb = m_apb_agent.m_sequencer; end end if(m_cfg.has_functional_coverage) begin m_apb_agent.ap.connect(m_reg_cov_monitor.analysis_export); end if(m_cfg.has_spi_functional_coverage) begin m_apb_agent.ap.connect(m_func_cov_monitor.analysis_export); end if(m_cfg.has_spi_scoreboard) begin m_apb_agent.ap.connect(m_scoreboard.apb.analysis_export); m_spi_agent.ap.connect(m_scoreboard.spi.analysis_export); m_scoreboard.spi_rm = m_cfg.spi_rm; end

endfunction: connect

`endif // SPI_ENV

Page 23: 1_Testbench Guide for OVM

Ovm/Testbench/Blocklevel 20

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

The AgentsSince the OVM build process is top down, the SPI and APB agents are constructed next. The article on the agent buildprocess describes how the APB agent is configured and built, the SPI agent follows the same process.The components within the agents are at the bottom of the test bench hierarchy, so the build process terminates there.( for source code example download visit us online at http:/ / uvm. mentor. com ).

Page 24: 1_Testbench Guide for OVM

Ovm/Testbench/IntegrationLevel 21

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

Ovm/Testbench/IntegrationLevel

You are reading the OVM version of this article. You can find the new UVM version at [[]]

This test bench example is one that takes twoblock level verification environments andshows how they can be reused at a higherlevel of integration. The principles that areillustrated in the example are applicable torepeated rounds of vertical resue.The example takes the SPI block levelexample and integrates it with another blocklevel verification environment for a GPIODUT. The hardware for the two blocks hasbeen integrated into a Peripheral Sub-System(PSS) which uses an AHB to APB bus bridgeto interface with the APB interfaces on theSPI and GPIO blocks. The environments fromthe block level are encapsulated by thepss_env, which also includes an AHB agent todrive the exposed AHB bus interface. In thisconfiguration, the block level APB businterfaces are no longer exposed, and so theAPB agents are put into passive mode tomonitor the APB traffic. The stimulus needsto drive the AHB interface and registerlayering enables reuse of block level stimulus at the integration level.

We shall now go through the test bench and the build process from the top down, starting with the top level testbench module.

Top Level Test Bench ModuleAs with the block level test bench example, the top level test bench module is used to encapsulate the DUT, connectinterfaces to the DUT signal pins and then set the virtual interface containers up in configuration space before callingrun_test(). The main differences between this code and the block level test bench code are that there are more interfacesand that there is a need to bind to some internal signals to monitor the APB bus. The DUT is wrapped by a module whichconnects its I/O signals to the interfaces used in the OVM test bench. The internal signals are bound to the APB interfaceusing the binder module:

module top_tb;

import ovm_pkg::*;import ovm_container_pkg::*;import pss_test_lib_pkg::*;

// PCLK and PRESETn

Page 25: 1_Testbench Guide for OVM

Ovm/Testbench/IntegrationLevel 22

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

//logic HCLK;logic HRESETn;

//// Instantiate the interfaces://apb_if APB(HCLK, HRESETn); // APB interface - shared between passive agentsahb_if AHB(HCLK, HRESETn); // AHB interfacespi_if SPI(); // SPI Interfaceintr_if INTR(); // Interruptgpio_if GPO();gpio_if GPI();gpio_if GPOE();icpit_if ICPIT();serial_if UART_RX();serial_if UART_TX();modem_if MODEM();

// Binderbinder probe();

// DUT Wrapper:pss_wrapper wrapper(.ahb(AHB), .spi(SPI), .gpi(GPI), .gpo(GPO), .gpoe(GPOE), .icpit(ICPIT), .uart_rx(UART_RX), .uart_tx(UART_TX), .modem(MODEM));

// OVM initial block:// Virtual interface wrapping & run_test()initial begin ovm_container #(virtual apb_if)::set_value_in_global_config("APB_vif" , APB); ovm_container #(virtual ahb_if)::set_value_in_global_config("AHB_vif" , AHB); ovm_container #(virtual spi_if)::set_value_in_global_config("SPI_vif" , SPI); ovm_container #(virtual intr_if)::set_value_in_global_config("INTR_vif", INTR); ovm_container #(virtual gpio_if)::set_value_in_global_config("GPO_vif" , GPO); ovm_container #(virtual gpio_if)::set_value_in_global_config("GPOE_vif" , GPOE); ovm_container #(virtual gpio_if)::set_value_in_global_config("GPI_vif" , GPI); ovm_container #(virtual icpit_if)::set_value_in_global_config("ICPIT_vif" , ICPIT); ovm_container #(virtual serial_if)::set_value_in_global_config("UART_RX_vif" , UART_RX); ovm_container #(virtual serial_if)::set_value_in_global_config("UART_TX_vif" , UART_TX); ovm_container #(virtual modem_if)::set_value_in_global_config("MODEM_vif" , MODEM); run_test();end

//// Clock and reset initial block://initial begin HCLK = 0; HRESETn = 0; repeat(8) begin #10ns HCLK = ~HCLK; end HRESETn = 1; forever begin #10ns HCLK = ~HCLK; endend

// Clock assignments:assign GPO.clk = HCLK;assign GPOE.clk = HCLK;assign GPI.clk = HCLK;assign ICPIT.PCLK = HCLK;

endmodule: top_tb

Page 26: 1_Testbench Guide for OVM

Ovm/Testbench/IntegrationLevel 23

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

The TestLike the block level test, the integration level test should have the common build and configuration process captured in abase class that subsequent test cases can inherit from. As can be seen from the example, there is more configuration to doand so the need becomes more compelling.The configuration object for the pss_env contains handles for the configuration objects for the spi_env and the gpio_env.In turn, the sub-env configuration objects contain handles for their agent sub-component configuration objects. Thepss_env is responsible for unnesting the spi_env and gpio_env configuration objects and setting them in its configurationtable, making any local changes necessary. In turn the spi_env and the gpio_env put their agent configurations into theirconfiguration table.The pss test base class is as follows:

`ifndef PSS_TEST_BASE

`define PSS_TEST_BASE

//

// Class Description:

//

//

class pss_test_base extends ovm_test;

// OVM Factory Registration Macro

//

`ovm_component_utils(pss_test_base)

//------------------------------------------

// Data Members

//------------------------------------------

//------------------------------------------

// Component Members

//------------------------------------------

// The environment class

pss_env m_env;

// Configuration objects

pss_env_config m_env_cfg;

spi_env_config m_spi_env_cfg;

gpio_env_config m_gpio_env_cfg;

//uart_env_config m_uart_env_cfg;

apb_agent_config m_spi_apb_agent_cfg;

apb_agent_config m_gpio_apb_agent_cfg;

ahb_agent_config m_ahb_agent_cfg;

spi_agent_config m_spi_agent_cfg;

gpio_agent_config m_GPO_agent_cfg;

gpio_agent_config m_GPI_agent_cfg;

gpio_agent_config m_GPOE_agent_cfg;

// Register map

pss_register_map pss_rm;

//------------------------------------------

// Methods

//------------------------------------------

//extern function void configure_apb_agent(apb_agent_config cfg);

// Standard OVM Methods:

extern function new(string name = "spi_test_base", ovm_component parent = null);

extern function void build();

extern virtual function void configure_apb_agent(apb_agent_config cfg, int index, logic[31:0] start_address, logic[31:0] range);

extern task run();

endclass: pss_test_base

function pss_test_base::new(string name = "spi_test_base", ovm_component parent = null);

super.new(name, parent);

endfunction

Page 27: 1_Testbench Guide for OVM

Ovm/Testbench/IntegrationLevel 24

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

// Build the env, create the env configuration

// including any sub configurations and assigning virtural interfaces

function void pss_test_base::build();

m_env_cfg = pss_env_config::type_id::create("m_env_cfg");

// Register map - Keep reg_map a generic name for vertical reuse reasons

pss_rm = new("reg_map", null);

m_env_cfg.pss_rm = pss_rm;

// SPI Sub-env configuration:

m_spi_env_cfg = spi_env_config::type_id::create("m_spi_env_cfg");

m_spi_env_cfg.spi_rm = pss_rm;

// apb agent in the SPI env:

m_spi_env_cfg.has_apb_agent = 1;

m_spi_apb_agent_cfg = apb_agent_config::type_id::create("m_spi_apb_agent_cfg");

configure_apb_agent(m_spi_apb_agent_cfg, 0, 32'h0, 32'h18);

m_spi_apb_agent_cfg.APB = ovm_container #(virtual apb_if)::get_value_from_config(this, "APB_vif");

m_spi_env_cfg.m_apb_agent_cfg = m_spi_apb_agent_cfg;

// SPI agent:

m_spi_agent_cfg = spi_agent_config::type_id::create("m_spi_agent_cfg");

m_spi_agent_cfg.SPI = ovm_container #(virtual spi_if)::get_value_from_config(this, "SPI_vif");

m_spi_env_cfg.m_spi_agent_cfg = m_spi_agent_cfg;

m_env_cfg.m_spi_env_cfg = m_spi_env_cfg;

set_config_object("*", "spi_env_config", m_spi_env_cfg, 0);

// GPIO env configuration:

m_gpio_env_cfg = gpio_env_config::type_id::create("m_gpio_env_cfg");

m_gpio_env_cfg.gpio_rm = pss_rm;

m_gpio_env_cfg.has_apb_agent = 1; // APB agent used

m_gpio_apb_agent_cfg = apb_agent_config::type_id::create("m_gpio_apb_agent_cfg");

configure_apb_agent(m_gpio_apb_agent_cfg, 1, 32'h100, 32'h124);

m_gpio_apb_agent_cfg.APB = ovm_container #(virtual apb_if)::get_value_from_config(this, "APB_vif");

m_gpio_env_cfg.m_apb_agent_cfg = m_gpio_apb_agent_cfg;

m_gpio_env_cfg.has_functional_coverage = 1; // Register coverage no longer valid

// GPO agent

m_GPO_agent_cfg = gpio_agent_config::type_id::create("m_GPO_agent_cfg");

m_GPO_agent_cfg.GPIO = ovm_container #(virtual gpio_if)::get_value_from_config(this, "GPO_vif");

m_GPO_agent_cfg.active = OVM_PASSIVE; // Only monitors

m_gpio_env_cfg.m_GPO_agent_cfg = m_GPO_agent_cfg;

// GPOE agent

m_GPOE_agent_cfg = gpio_agent_config::type_id::create("m_GPOE_agent_cfg");

m_GPOE_agent_cfg.GPIO = ovm_container #(virtual gpio_if)::get_value_from_config(this, "GPOE_vif");

m_GPOE_agent_cfg.active = OVM_PASSIVE; // Only monitors

m_gpio_env_cfg.m_GPOE_agent_cfg = m_GPOE_agent_cfg;

// GPI agent - active (default)

m_GPI_agent_cfg = gpio_agent_config::type_id::create("m_GPI_agent_cfg");

m_GPI_agent_cfg.GPIO = ovm_container #(virtual gpio_if)::get_value_from_config(this, "GPI_vif");

m_gpio_env_cfg.m_GPI_agent_cfg = m_GPI_agent_cfg;

// GPIO Aux agent not present

m_gpio_env_cfg.has_AUX_agent = 0;

m_gpio_env_cfg.has_functional_coverage = 1;

m_gpio_env_cfg.has_virtual_sequencer = 0;

m_gpio_env_cfg.has_reg_scoreboard = 0;

m_gpio_env_cfg.has_out_scoreboard = 1;

m_gpio_env_cfg.has_in_scoreboard = 1;

m_env_cfg.m_gpio_env_cfg = m_gpio_env_cfg;

set_config_object("*", "gpio_env_config", m_gpio_env_cfg, 0);

// AHB Agent

m_ahb_agent_cfg = ahb_agent_config::type_id::create("m_ahb_agent_cfg");

m_ahb_agent_cfg.AHB = ovm_container #(virtual ahb_if)::get_value_from_config(this, "AHB_vif");

m_env_cfg.m_ahb_agent_cfg = m_ahb_agent_cfg;

// Add in interrupt line

m_env_cfg.ICPIT = ovm_container #(virtual icpit_if)::get_value_from_config(this, "ICPIT_vif");

set_config_object("*", "pss_env_config", m_env_cfg, 0);

m_env = pss_env::type_id::create("m_env", this);

// Override for register adapters:

register_adapter_base::type_id::set_inst_override(ahb_register_adapter::get_type(), "spi_bus.adapter");

register_adapter_base::type_id::set_inst_override(ahb_register_adapter::get_type(), "gpio_bus.adapter");

endfunction: build

//

// Convenience function to configure the apb agent

//

// This can be overloaded by extensions to this base class

function void pss_test_base::configure_apb_agent(apb_agent_config cfg, int index, logic[31:0] start_address, logic[31:0] range);

cfg.active = OVM_PASSIVE;

Page 28: 1_Testbench Guide for OVM

Ovm/Testbench/IntegrationLevel 25

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

cfg.has_functional_coverage = 0;

cfg.has_scoreboard = 0;

cfg.no_select_lines = 1;

cfg.apb_index = index;

cfg.start_address[0] = start_address;

cfg.range[0] = range;

endfunction: configure_apb_agent

task pss_test_base::run;

endtask: run

`endif // SPI_TEST_BASE

Again, a test case that extends this base class would populate its run method to define a virtual sequence that would berun on the virtual sequencer in the env.. If there was non-default configuration to be done, then this could be done bypopulating or overloading the build method or any of the configuration methods.

`ifndef PSS_TEST`define PSS_TEST

//// Class Description:////class pss_test extends pss_test_base;

// OVM Factory Registration Macro//`ovm_component_utils(pss_test)

//------------------------------------------// Methods//------------------------------------------

// Standard OVM Methods:extern function new(string name = "pss_test", ovm_component parent = null);extern function void build();extern task run();

endclass: pss_test

function pss_test::new(string name = "pss_test", ovm_component parent = null); super.new(name, parent);endfunction

// Build the env, create the env configuration// including any sub configurations and assigning virtural interfacesfunction void pss_test::build(); super.build();endfunction: build

task pss_test::run; bridge_basic_rw_vseq t_seq = bridge_basic_rw_vseq::type_id::create("t_seq"); $display("Starting PSS test");

repeat(10) begin t_seq.start(m_env.m_vsqr.ahb); end

global_stop_request();endtask: run

`endif // PSS_TEST

Page 29: 1_Testbench Guide for OVM

Ovm/Testbench/IntegrationLevel 26

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

The PSS envThe PSS env build process retrieves the configuration object and constructs the various sub-envs, after testing the varioushas_<sub-component> fields in order to determine whether the env is required by the test case. If the sub-env is to bepresent, the sub-envs configuration object is set in the PSS envs configuration table. The connect method assigns pointersfor the sub-sequencer handles in the pss_env virtual sequencer.

`ifndef PSS_ENV`define PSS_ENV

//// Class Description:////class pss_env extends ovm_env;

// OVM Factory Registration Macro//`ovm_component_utils(pss_env)

//------------------------------------------// Data Members//------------------------------------------pss_env_config m_cfg;//------------------------------------------// Sub Components//------------------------------------------spi_env m_spi_env;gpio_env m_gpio_env;ahb_agent m_ahb_agent;pss_virtual_sequencer m_vsqr;//------------------------------------------// Methods//------------------------------------------

// Standard OVM Methods:extern function new(string name = "pss_env", ovm_component parent = null);// Only required if you have sub-componentsextern function void build();// Only required if you have sub-components which are connectedextern function void connect();

endclass: pss_env

function pss_env::new(string name = "pss_env", ovm_component parent = null); super.new(name, parent);endfunction

// Only required if you have sub-componentsfunction void pss_env::build(); m_cfg = pss_env_config::get_config(this); if(m_cfg.has_spi_env) begin set_config_object("m_spi_env*", "spi_env_config", m_cfg.m_spi_env_cfg, 0); m_spi_env = spi_env::type_id::create("m_spi_env", this); end if(m_cfg.has_gpio_env) begin set_config_object("m_gpio_env*", "gpio_env_config", m_cfg.m_gpio_env_cfg, 0); m_gpio_env = gpio_env::type_id::create("m_gpio_env", this); end if(m_cfg.has_ahb_agent) begin set_config_object("m_ahb_agent*", "ahb_agent_config", m_cfg.m_ahb_agent_cfg, 0); m_ahb_agent = ahb_agent::type_id::create("m_ahb_agent", this); end if(m_cfg.has_virtual_sequencer) begin m_vsqr = pss_virtual_sequencer::type_id::create("m_vsqr", this); endendfunction: build

// Only required if you have sub-components which are connectedfunction void pss_env::connect();

Page 30: 1_Testbench Guide for OVM

Ovm/Testbench/IntegrationLevel 27

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

if(m_cfg.has_virtual_sequencer) begin if(m_cfg.has_spi_env) begin m_vsqr.spi = m_spi_env.m_spi_agent.m_sequencer; end if(m_cfg.has_gpio_env) begin m_vsqr.gpi = m_gpio_env.m_GPI_agent.m_sequencer; end if(m_cfg.has_ahb_agent) begin m_vsqr.ahb = m_ahb_agent.m_sequencer; end endendfunction: connect

`endif // PSS_ENV

The rest of the test bench hierarchyThe build process continues top-down with the sub-envs being conditionally constructed as illustrated in the block leveltest bench example and the agents contained within the sub-envs being built as described in the agent example.

Further levels of integrationVertical reuse for further levels of integration can be achieved by extending the process described for the PSS example.Each level of integration adds another layer, so for instance a level 2 integration environment would contain two or morelevel 1 envs and the level 2 env configuration object would contain nested handles for the level 1 env configurationobjects. Obviously, at the test level of the hierarchy the amount of code increases for each round of vertical reuse, butfurther down the hierarchy, the configuration and build process has already been implemented in the previous generationof vertical layering.( for source code example download visit us online at http:/ / uvm. mentor. com ).

Page 31: 1_Testbench Guide for OVM

Ovm/Agent 28

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

Ovm/Agent

You are reading the OVM version of this article. You can find the new UVM version at [[]]

Active agent ovm.gif

An OVM agent can be thought of as averification component kit for a specificlogical interface. The agent is developed aspackage that includes a SystemVeriloginterface for connecting to the signal pins of aDUT, and a SystemVerilog package thatincludes the classes that make up the overallagent component. The agent class itself is atop level container class for a driver, asequencer and a monitor, plus any otherverification components such as functionalcoverage monitors or scoreboards. The agentalso has an analysis port which is connected tothe analysis port on the monitor, making itpossible for a user to connect external analysiscomponents to the agent without having toknow how the agent has beenimplemented. The agent is the lowest level hierarchical block in a testbench and its exact structure is dependent on itsconfiguration which can be varied from one test to another via the agent configuration object.In order to illustrate the design and implementation of an agent we shall take an APB bus agent and show how it ispackaged, configured, built and connected. The APB agent uses an interface which is called apb_if and will be stored ina file called apb_if.sv. The various class template files for the agent are collected together in a SystemVerilog packagewhich is saved in a file called apb_agent_pkg.sv. Any component, such as an env, that uses files from this package willimport this package.

package apb_agent_pkg;

import ovm_pkg::*;`include "ovm_macros.svh"

`include "apb_seq_item.svh"`include "apb_agent_config.svh"`include "apb_driver.svh"`include "apb_coverage_monitor.svh"`include "apb_monitor.svh"`include "apb_sequencer.svh"`include "apb_agent.svh"

// Utility Sequences`include "apb_seq.svh"

endpackage: apb_agent_pkg

Page 32: 1_Testbench Guide for OVM

Ovm/Agent 29

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

The Agent Configuration ObjectThe agent has a configuration object which is used to define:• Which of the agent sub-components get constructed (Topology)• The handle for the virtual interface used by the driver and the monitor• The behaviour of the agentBy convention, OVM agents have a variable of type OVM_ACTIVE_PASSIVE_e which defines whether the agent isactive (OVM_ACTIVE) with the sequencer and the driver constructed, or passive (OVM_PASSIVE) with niether thedriver or the sequencer constructed. This parameter is called active and by default it is set to OVM_ACTIVE.Whether other sub-components are built or not is controlled by other variables which should have descriptive names. Forinstance if there is a functional coverage monitor, then the bit that controls whether the functional coverage monitor getsbuilt or not might be called has_functional_coverage.The configuration object will contain a handle for the virtual interface that is used by the driver and the monitor. Theconfiguration object is constructed and configured in the test and it is in test that the virtual interface handle is assignedto the virtual interface passed in from the testbench module.The configuration object may also contain other variables which affect the way in which the agent behaves or isconfigured. For instance, in the configuration object for the apb agent, there are variables which set up the memory mapand determine which apb PSEL lines is activated for which addresses.The configuration class should have all its variables set to common default values.The following code example shows the configuration object for the apb agent. This configuration class has a get_config()method implemented to provide a more convenient API for ovm_components to access this configuration.

`ifndef APB_AGENT_CONFIG`define APB_AGENT_CONFIG

//// Class Description:////class apb_agent_config extends ovm_object;

localparam string s_my_config_id = "apb_agent_config";localparam string s_no_config_id = "no config";localparam string s_my_config_type_error_id = "config type error";

// OVM Factory Registration Macro//`ovm_object_utils(apb_agent_config)

// Virtual Interfacevirtual apb_if APB;

//------------------------------------------// Data Members//------------------------------------------// Is the agent active or passiveovm_active_passive_enum active = OVM_ACTIVE;// Include the APB functional coverage monitorbit has_functional_coverage = 0;// Include the APB RAM based scoreboardbit has_scoreboard = 0;//// Address decode for the select lines:int no_select_lines = 1;logic[31:0] start_address[15:0];logic[31:0] range[15:0];

//------------------------------------------

Page 33: 1_Testbench Guide for OVM

Ovm/Agent 30

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

// Methods//------------------------------------------extern static function apb_agent_config get_config( ovm_component c );// Standard OVM Methods:extern function new(string name = "apb_agent_config");

endclass: apb_agent_config

function apb_agent_config::new(string name = "apb_agent_config"); super.new(name);endfunction

//// Function: get_config//// This method gets the my_config associated with component c. We check for// the two kinds of error which may occur with this kind of// operation.//function apb_agent_config apb_agent_config::get_config( ovm_component c ); ovm_object o; apb_agent_config t;

if( !c.get_config_object( s_my_config_id , o , 0 ) ) begin c.ovm_report_error( s_no_config_id , $sformatf("no config associated with %s" , s_my_config_id ) , OVM_NONE , `ovm_file , `ovm_line ); return null; end

if( !$cast( t , o ) ) begin c.ovm_report_error( s_my_config_type_error_id , $sformatf("config %s associated with config %s is not of type my_config" , o.sprint() , s_my_config_id ) , OVM_NONE , `ovm_file , `ovm_line ); end

return t;endfunction

`endif // APB_AGENT_CONFIG

Page 34: 1_Testbench Guide for OVM

Ovm/Agent 31

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

The Agent Build PhaseThe actions that take place during the agent build phase are determined by the contents of its configuration object. Thefirst action during the method is to get a reference to the configuration object. Then, at the pointswhere sub-components are to be constructed, the appropriate configuration field is tested to determine whether theyshould be constructed or not.

Passive agent ovm.gif

The exceptions to this rule is the monitorwhich is always built, since it is used whetherthe agent is active or passive.

The Agent Connect Phase

Once the agent sub-components have beenconstructed, then they need to be connected.The usual connections required are:• Monitor analysis port to the agent analysis

port 1

• The sequencer seq_item_pull_export to thedriver seq_item_pull_port (If the agent isactive).

• Any agent analysis sub-componentsanalysis exports to the monitor analysisport

• Assignment of the virtual interfaces in the driver and the monitor to the virtual interface in the configuration object 2

Notes:

1. The agent analysis port handle can be assigned a pointer from the monitor analysis port, this saves having to constructa separate analysis port object in the agent.

2. Assigning the driver and monitor virtual interfaces in the agent removes the need for these sub-components to havethe overhead of a configuration table lookup.

The following code for the apb agent illustrates how the configuration object determines what happens during the buildand connect phases:

`ifndef APB_AGENT`define APB_AGENT

//// Class Description:////class apb_agent extends ovm_component;

// OVM Factory Registration Macro//`ovm_component_utils(apb_agent)

//------------------------------------------// Data Members//------------------------------------------apb_agent_config m_cfg;//------------------------------------------// Component Members//------------------------------------------ovm_analysis_port #(apb_seq_item) ap;

Page 35: 1_Testbench Guide for OVM

Ovm/Agent 32

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

apb_monitor m_monitor;apb_sequencer m_sequencer;apb_driver m_driver;apb_coverage_monitor m_fcov_monitor;//------------------------------------------// Methods//------------------------------------------

// Standard OVM Methods:extern function new(string name = "apb_agent", ovm_component parent = null);extern function void build();extern function void connect();

endclass: apb_agent

function apb_agent::new(string name = "apb_agent", ovm_component parent = null); super.new(name, parent);endfunction

function void apb_agent::build(); m_cfg = apb_agent_config::get_config(this); // Monitor is always present m_monitor = apb_monitor::type_id::create("m_monitor", this); // Only build the driver and sequencer if active if(m_cfg.active == OVM_ACTIVE) begin m_driver = apb_driver::type_id::create("m_driver", this); m_sequencer = apb_sequencer::type_id::create("m_sequencer", this); end if(m_cfg.has_functional_coverage) begin m_fcov_monitor = apb_coverage_monitor::type_id::create("m_fcov_monitor", this); endendfunction: build

function void apb_agent::connect(); m_monitor.APB = m_cfg.APB; ap = m_monitor.ap; // Only connect the driver and the sequencer if active if(m_cfg.active == OVM_ACTIVE) begin m_driver.seq_item_port.connect(m_sequencer.seq_item_export); m_driver.APB = m_cfg.APB; end if(m_cfg.has_functional_coverage) begin m_monitor.ap.connect(m_fcov_monitor.analysis_export); end

endfunction: connect

`endif // APB_AGENT

The build process for the APB agent can be followed in the block level testbench example:( for source code example download visit us online at http:/ / uvm. mentor. com ).

Page 36: 1_Testbench Guide for OVM

OVM Phases 33

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

OVM Phases

You are reading the OVM version of this article. You can find the new UVM version at [[]]

Ovm phases.gif

In order to have a consistent execution flow, the OVM uses phaseswhich are ordered to allow the testbench component objects to stayin step as the testbench is built and configured and connected. Oncethe testbench hierarchy is available the simulation run phase isexecuted, after which the report phases occur. The defined phasesallow OVM verification components developed by different teams tobe mixed freely, since it is clear what happens in each phase.

The different OVM phases are illustrated in order in the flowdiagram. The ovm_component base class contains virtual methodsfor each of the phases which are populated by the testbench creatoraccording to the requirements of the component.

run_test() -> new

To start an OVM testbench the run_test() method has to be calledfrom the static part of the testbench. It is usually called from withinan initial block in the top level module of the testbench.Calling run_test() initiates the OVM phasing by constructing the rootcomponent of the OVM class structure. The method can be passed astring argument containing the default type name of anovm_component which will be constructed as the root node of theOVM testbench. However, run_test() checks a command line plusargcalled OVM_TESTNAME and uses that plusarg string as a lookupfor an ovm_component if there is one present, overriding the default type name. By convention, the root node will bederived from an ovm_test component, but it can be derived from any ovm_component.For instance - In order to signify the test component 'my_big_test' as the root class the Questa command line would looklike this:vsim tb_top +OVM_TESTNAME=my_big_test

Page 37: 1_Testbench Guide for OVM

OVM Phases 34

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

build

In an OVM testbench only the test or root node component is constructed directly using the new method. After that, therest of the testbench hierarchy is built top-down during the build phase. Construction is deferred so that the structure andconfiguration of each level of the component hierarchy can be controlled by the level above. During the build methodcomponents are indirectly constructed through a factory based creation process.

connect

Once the testbench component hierarchy has been put in place during the build method, the connect phase begins. Theconnect phase works from the bottom up and is used to make TLM connections between components or to makereferences to testbench resources.

end_of_elaboration

This phase can be used to make any final enhancements to the environment after it has been built and its inter-componentconnections made.

start_of_simulation

The start_of_simulation phase occurs just before the run phase. It may be a convenient point in the OVM phases to printbanner information or testbench configuration status information.

run - Terminated by global_stop_request

The run method is where the stimulus generation and checking activities of the testbench are defined. Unlike the otherOVM phases, the run method is a task which means that it consumes time. All components that are actively participatingin the testbench will have a populated run method and all of these run methods are run in parallel.The run phase is terminated by a call to the global_stop_request() method. This shuts down all the executing threads andterminates the run phase. The call to global_stop_request() can either be made explicitly by the user, or if theOVM objection mechanism is being used it will be called automatically when all objections have been lowered.

extract

The extract phase is intended to be used to extract test results and statistics together with functional coverage informationfrom different components in the testbench such as scoreboards and functional coverage monitors.

check

During the check phase, data collected during the previous extract phase is checked and the overall result of the testbenchis calculated.

report

The report phase is the final phase and is used to report the results of the test case, this is either via messages to thesimulator transcript or by writing to files.When the report phase has completed, the OVM testbench terminates and, by default, makes a $finish system call.

Page 38: 1_Testbench Guide for OVM

OVM Phases 35

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

OVM Phases - Summary

Phase Order Phase Type Description

run_test() -> new function Psuedo phase - used to construct the top level component, usually the test

build Top-Down function Component hierarchy deferred construction and configuration phase

connect Bottom-Up function Used to make TLM and other connections once components in place

end_of_elaboration Bottom-Up function Make final enhancements before simulation starts

start_of_simulation Bottom-Up function Print out start of simulation messages

run Bottom-Up task Time consuming phase where the work of the test case is done

extract Bottom-Up function Used for data extraction from analysis components

check Bottom-Up function Used to make checks to ensure that the simulation has completed with no errors

report Bottom-Up function Used to report the results of the simulation and any statistics collected

Deprecated PhasesThere are a number of phases which are a legacy from the AVM, URM and earlier versions of the OVM. These phasesare still supported in the current version of the OVM , but may disapear in future versions and will not be supported inthe UVM. Users should avoid using the deprecated phases, and they should consider porting any verification componentsusing them to align with the supported set of OVM phases.The deprecated phases and their recommended replacement phases are shown in the following table:

Deprecated Phase  Replacement Phase   

post_new build

export_connections connect

import_connections connect

pre_run start_of_simulation

configure end_of_elaboration

Adding Other PhasesThe OVM provides a means to allow users to insert other task or function based phases between the standard set ofphases. Whilst this may appear to be an useful thing to do, it is rarely used in practice since it introduces potentialincompatability problems between OVM components. For instance, adding a task phase means that any othercomponents will not be active during that phase so the monitor, scoreboard and the normal stimulus generationinfrastructure will be inactive during the user defined phase.  Therefore, adding phases is not recommended.

Page 39: 1_Testbench Guide for OVM

OVM Factory 36

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

OVM Factory

You are reading the OVM version of this article. You can find the new UVM version at [[]]

The OVM FactoryThe purpose of the OVM factory is to allow an object of one type to be substituted with an object of a derived typewithout having to change the structure of the testbench or edit the testbench code. The mechanism used is refered to as anoverride and the override can be by instance or type.  This functionality is useful for changing sequence functionality orfor changing one version of a component for another.  Any components which are to be swapped must bepolymorphically compatible.  This includes having all the same TLM interfaces handles exist and TLM objects becreated by the new replacement component. Additionally, in order to take advantage of the factory certain codingconventions need to be followed.

Factory Coding Convention 1: RegistrationA component or object must contain factory registration code which comprises of the following elements:• An ovm_component_registry wrapper, typedefed to type_id• A static function to get the type_id• A function to get the type nameFor example:

class my_component extends ovm_component;

// Wrapper class around the component class that is used within the factorytypedef ovm_component_registry #(my_component, "my_component") type_id;

// Used to get the type_id wrapperstatic function type_id get_type(); return type_id::get();endfunction

// Used to get the type_name as a stringfunction string get_type_name(); return "my_component";endfunction

...endclass: my_component

The registration code has a regular pattern and can be safely generated with one of a set of four factory registrationmacros:

// For a componentclass my_component extends ovm_component;

// Component factory registration macro`ovm_component_utils(my_component)

// For a parameterised componentclass my_param_component #(int ADD_WIDTH=20, int DATA_WIDTH=23) extends ovm_component;

typedef my_param_component #(ADD_WIDTH, DATA_WIDTH) this_t;

// Parameterised component factory registration macro

Page 40: 1_Testbench Guide for OVM

OVM Factory 37

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

`ovm_component_param_utils(this_t)

// For a class derived from an object (ovm_object, ovm_transaction, ovm_sequence_item, ovm_sequence etc)class my_item extends ovm_sequence_item;

`ovm_oject_utils(my_item)

// For a parameterised object classclass my_item #(int ADD_WIDTH=20, int DATA_WIDHT=20) extends ovm_sequence_item;

typedef my_item #(ADD_WIDTH, DATA_WIDTH) this_t

`ovm_object_param_utils(this_t)

Factory Coding Convention 2: Constructor DefaultsThe ovm_component and ovm_object constructors are virtual methods which means that users have to follow theirprototype template. In order to support deferred construction during the build phase, the factory constructor shouldcontain defaults for the constructor arguments. This allows a factory registered class to be built inside the factory usingthe defaults and then the class properties are re-assigned to the arguments passed via the create method of theovm_component_registry wrapper class. The defaults are different for components and objects:

// For a component:class my_component extends ovm_component;

function new(string name = "my_component", ovm_component parent = null); super.new(name, parent);endfunction

// For an objectclass my_item extends ovm_sequence_item;

function new(string name = "my_item"); super.new(name);endfunction

Factory Coding Convention 3: Component and Object creationTestbench components are created during the build phase using the create method of the ovm_component_registry. Thisfirst constructs the class, then assigns the pointer to the class to its declaration handle in the testbench after having thename and parent arguments correctly. For components, the build process is top-down, which allows higher levelcomponents and configurations to control what actually gets built.Object classes are created as required, again the create method is used.The following code snippet illustrates how this is done:

class env extends ovm_env;

my_component m_my_component;my_param_component #(.ADDR_WIDTH(32), .DATA_WIDTH(32)) m_my_p_component;

// Constructor & registration macro left out

// Component and Parameterised Component create examplesfunction void build(); m_my_component = my_component::type_id::create("m_my_component", this); m_my_p_component = my_param_component #(32, 32)::type_id::create("m_my_p_component", this);endfunction: build

task run; my_seq test_seq; my_param_seq #(.ADDR_WIDTH(32), .DATA_WIDTH(32)) p_test_seq;

Page 41: 1_Testbench Guide for OVM

OVM Factory 38

UVM/OVM Documentation - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com

// Object and parameterised ojbect create examples test_seq = my_seq::type_id::create("test_seq"); p_test_seq = my_param_seq #(32,32)::type_id::create("p_test_seq"); // ....endtask: run

Page 42: 1_Testbench Guide for OVM

Mentor Graphics UVM/OVM Documentation / Methodology Cookbook

© 2010 Mentor Graphics Corporation, all rights reserved. This document contains information that is proprietary to Mentor Graphics Corporation and may be duplicated in whole or in part by the original recipient for internal business purposes only, provided that this entire notice appears in all copies. In accepting this document, the recipient agrees to make every reasonable effort to prevent unauthorized use of this information. All trademarks mentioned are this document are trademarks of their respective owners.

MGC 06-10 TECH9050-w

F o r t h e l a t e s t p r o d u c t i n f o r m a t i o n , c a l l u s o r v i s i t : w w w . m e n t o r . c o m