This action might not be possible to undo. Are you sure you want to continue?
VERIFICATION METHODOLOGY ONLINE COOKBOOK
M ENTOR GRAPHICS VERIFICATION METHODOLOGY TEAM
CONTACT VMDOC@MENTOR.COM HTTP://WWW.MENTOR.COM/PRODUCTS/FV/TECHPUBS
w w w.m e n t o r.c o m
W H I T E P A P E R
learn about DUT Interface Connections, techniques for hookup and reuse
UVM/OVM Online Methodology Cookbook - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com PDF generated at: Tue, 15 Mar 2011 04:59:56 PST
Table of Contents
Connect/Dut Interface SVCreationOrder Connect/SV Techniques ParameterizedTests Config/Container Config/Overview Config/Params Package Connect/Virtual Interface VirtInterfaceConfigOVMContainer VirtInterfaceConfigPkg VirtInterfacePackage VirtInterfaceFunctionCallChain BusFunctionalModels DualTop ProtocolModules Connect/AbstractConcrete Connect/AbstractConcreteOVMContainer 1 5 7 9 12 14 18 21 28 30 33 35 37 39 41 43 45
Article Sources and Contributors Image Sources, Licenses and Contributors 50 51
- This document is a snapshot of dynamic content from the Online Methodology Cookbook - Created from http://uvm.mentor.com on Mon, 14 Mar 2011 21:59:57 PDT
The Device Under Test (DUT) is typically a Verilog module or a VHDL entity/architecture while the testbench is composed of SystemVerilog class objects. There are number of factors to consider in DUT € Testbench (TB) connection and communication; module instance to class object communication mechanisms, configuration of the DUT, reuse, emulation, black box/white box testing and so forth. There are quite a number of different approaches and solutions for managing the different pieces of this puzzle. The challenge is to manage it in a way that addresses all these different factors.
The DUT and testbench belong to two different SystemVerilog instance worlds. The DUT belongs to the static instance world while the testbench belongs to the dynamic instance world. Because of this the DUT's ports can not be connected directly to the testbench class objects so a different SystemVerilog means of communication, which is virtual interfaces, is used. The DUT's ports are connected to an instance of an interface. The Testbench communicates with the DUT through the interface instance. Using a virtual interface as a reference or handle to the interface instance, the testbench can access the tasks, functions, ports, and internal variables of the SystemVerilog interface. As the interface instance is connected to the DUT pins, the testbench can monitor and control the DUT pins indirectly through the interface elements. Sometimes a virtual interface approach cannot be used. In which case there is a second or alternative approach to DUT-TB communication which is referred to as the abstract/concrete class approach that may be used. However, as long as it can be used, virtual interfaces is the preferred and recommended approach. Regardless of which approach is used instance information must be passed from the DUT to the testbench. When using virtual interfaces the location of the interface instance is supplied to the testbench so its virtual interface properties may be set to point to the interface instance. The recommended approach for passing this information to the testbench is to use either the configuration database using ovm_container or to use a package. The test class in the testbench receives the information on the location of the interface instance. After receiving this information it supplies this information to the agent transactors that actually need the information. The test class does this by placing the information in a configuration object which is provided to the appropriate agent.
UVM/OVM Online Methodology Cookbook - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com
More detailed discussion and examples of passing virtual interface information to the testbench from the DUT and€ on setting€ virtual interfaces for DUT-TB communication is in the article on virtual interfaces.
Parameter sharing between the DUT and Testbench When the DUT and/or the associated interface(s) are parameterized the parameter values are almost always used in the testbench as well. These common parameters should be defined in a single location and then shared with both the DUT and the testbench. The recommended way to do this is to place in a package the parameters that are used both in the DUT and testbench. This package is referred to as the test parameters package. The test parameter package may also be used to pass the location of the interface instance from the DUT to the testbench as explained earlier.€ There is an example and more detailed explanation in the article on "setting virtual interface properties in the testbench with the configuration dataset using the test parameter package"
UVM/OVM Online Methodology Cookbook - Copyright (c) 2011 Mentor Graphics Corporation - http://uvm.mentor.com
The DUT wrapper is the stuff that goes in the emulator. A more detailed explanation and example is in the article Dual Top. DUT wires. If the testbench is only going to be used in simulation dual top is not necessary but may however still provide a useful level of encapsulation for modularity.com . Encapsulation also provides for modularity for swapping and for reuse. The other top module is a wrapper module which creates the testbench. When this occurs it is recommended to group items by encapsulating inside of€ wrapper modules. registers etc.http://uvm. Note: this article is not available to publish at this time so a link is not made.mentor. complicated and hard to manage. interfaces.Connect/Dut Interface Parameterized Tests Another approach to passing parameters into the testbench is to parameterize the top level class in the testbench which is typically the test. The testbench wrapper module stays running in the simulator. clock generation logic. protocol modules. One of the top modules is a DUT wrapper module that includes the DUT. UVM/OVM Online Methodology Cookbook .€ When emulation is a consideration Dual top is a necessity. Dual Top A level of encapsulation where two top modules are used is called dual top. 3 Encapsulation A typical DUT-TB setup has a top level SystemVerilog module that is a container for both the testbench and the DUT with its associated connection and support logic (such as clock generation). reuse etc. This style setup is referred to as a single top The top level module can become messy. Several different levels of encapsulation may be considered and are discussed below. There are a number of issues with parameterized tests that are discussed along with solutions.Copyright (c) 2011 Mentor Graphics Corporation . The passing of information from the DUT to the testbench is the same as described earlier.
associated assertions.http://uvm. Providing this access effects the structure of the DUT-TB communication and must be taken into account if white box testing is a requirement.Copyright (c) 2011 Mentor Graphics Corporation . They may however still provide a useful level of encapsulation for modularity. QVL instances (which are not allowed inside an interface). Protocol modules are wrapper modules that encapsulate a DUT interface. 4 Blackbox and Whitebox Testing Blackbox testing Blackbox testing of the DUT is a method of testing that tests the functionality of the DUT at the interface or pins of the DUT without specific knowledge of or access to the DUT's internal structure. Black box access to the DUT is provided typically by a virtual interface connection to an interface instance connected to the pins of the DUT. The writer of the test selects valid and invalid inputs and determines the correct response. reuse etc.com .mentor. If the testbench is only going to be used in simulation protocol modules are not necessary. Access to the DUT's internal structure is required. Whitebox testing Whitebox Testing of the DUT is a method of testing that tests the internal workings of the DUT. UVM/OVM Online Methodology Cookbook . and so forth.Connect/Dut Interface Protocol Modules When emulation is a consideration another level of encapsulation called protocol modules is necessary to isolate the changes that occur in the agent and interface in moving between simulation and emulation.
Copyright (c) 2011 Mentor Graphics Corporation . Phrases such as "prior to simulation" or "before simulation" are often used to refer to the compilation and elaboration steps that happen before run-time or "during simulation" to refer to the run-time step or phase. Elaboration is the process of binding together the components of the design.€ Elaboration includes among other things creating instantiations.SVCreationOrder 5 SVCreationOrder € SystemVerilog Instance Worlds When generating an OVM testbench and in particular the DUT € testbench communication it is helpful to understand the differences between the two different "instance worlds" of SystemVerilog and the order in which things are created.mentor. computing parameter values. This step or phase is often referred to as "simulation". Compilation is where the code is parsed and analyzed. elaboration and run-time.com . simulation time advances etc. In other words a "compile time error" may refer to an error at any time prior to run-time. Run-time is what is thought of as the simulation actually executing or running with processes executing. SystemVerilog Simulation Steps or Phases A SystemVerilog simulation consists of three steps or phases (not to be confused with OVM phases): compilation. UVM/OVM Online Methodology Cookbook . Often when referring to the compilation and elaboration phases they are not distinguished but are generally referred to as compilation.http://uvm. resolving hierarchical names and connecting nets.
however. We refer to this as the static instance world. Order of Creation The components of the two instance worlds are created in this order: During Elaboration: 1. There is an exception to this however. Class instances UVM/OVM Online Methodology Cookbook .Copyright (c) 2011 Mentor Graphics Corporation . Once simulation begins instances of these components are neither created nor destroyed but remain throughout the simulation. Components that belong to this world are module instances.mentor. checker instances. This is referred to as static initialization. Static methods and static properties of classes During run-time: 1.com .SVCreationOrder 6 Static Instance World Many SystemVerilog component instances are created during elaboration before the simulation begins. primitive instances and the top level of the design hierarchy. This exception is often used to create and initialize class properties (including class objects) before simulation. Components that belong to this world are classes. interface instance. They are. Component instances of the static world 2. created after the component instances of the static world. Class methods and properties that are declared as static are created prior to runtime.http://uvm. The OVM factory is an example of an object that is statically initialized. Dynamic Instance World Component instances that may be created and destroyed during simulation (the SystemVerilog run phase) belong to what is referred to as the dynamic instance world.
A virtual interface is a variable that represents an interface instance. Verilog hierarchical paths. Any named SystemVerilog object can be referenced by this hierarchical path name from any other SystemVerilog object. Pointers are the common means used.mentor. Therefore they may not be used in classes which are part of the Dynamic Instance World. The two most common examples of shared variables used in testbenches are variables declared in packages and static property declarations of classes. This implicit connection won't be synthesized or created when the model is implemented. both read and written) within other scopes such as classes or modules either by a fully resolved name ( package_name::variable_name ) or by import. These variables may be referenced (i. Verilog Hierarchical Path Every identifier in SystemVerilog has a unique hierarchical path name.Connect/SV Techniques 7 Connect/SV Techniques € Introduction and Recommendations SystemVerilog provides in general four different means of communication or connection between instances: ports. A shared variable is a variable declared in a scope that may be referenced by other scopes. and shared variables. Ports Ports are connections between members of the Static Instance World such as module and interface instances. These are not SystemVerilog ports but rather are wrapper classes around pointers. It is called a handle to differentiate it because it is what is considered a safe-pointer because of the restrictive rules of use compared to pointers in other languages such as C. It is recommended that shared variables only be used for initialization or status type communication where there is a UVM/OVM Online Methodology Cookbook . Handles A class handle is what points to a class object (instance).com . Hence OVM ports is a pointer based communication scheme dressed up like ports to look familiar to Verilog and VHDL engineers. It may be thought of as a handle to an interface instance. In shared variable behavior the variable may be read and or written in these other scopes. While this is powerful as it allows for communication from anywhere to anywhere it is in general not desirable to use this technique.€ For class based testbenches ports may not be used. Shared variables may be used in limited areas. Shared Variables Shared variables are sometimes referred to as global variables although generally speaking they are not truly global in scope. Static property declarations of classes may be referenced by a fully resolved name (class_name::static_property_name).e. Hierarchical paths are not recommended. In packages a variable may be declared such as an int or virtual interface. Often a static method of a class may be provided for accessing the static property.Copyright (c) 2011 Mentor Graphics Corporation .http://uvm. pointers. In modeling it is an absolute "no-no" because a connection is implicit in a hierarchical reference. thus breaking the design. OVM provides a notion of ports such as tlm_put_port etc. In verification it is to be avoided because portability and reuse are limited when it is used.
such as transactions. Because of the nature of shared variables race conditions are inherent and so care must be taken or races will occur.Copyright (c) 2011 Mentor Graphics Corporation .http://uvm. between objects. 8 UVM/OVM Online Methodology Cookbook .Connect/SV Techniques clear relationship between when information is written and read. Shared variables are not recommended for the transfer of data.mentor.com .
static function type_id get_type().com . To create a string-based registration. you would need to declare a "dummy"€specialization of the parameterized test class so that the string name specified above is tied to the particular parameter values. the macro call `ovm_component_param_utils(alu_basic_test #(DATA_WIDTH)) would expand to: typedef ovm_component_registry #(alu_basic_test #(DATA_WIDTH)) type_id.€ There are actually two factories.mentor. return type_id::get(). you need to provide a string for the second parameter argument that will be unique for each specialization of the test class.ParameterizedTests 9 ParameterizedTests € Introduction When configuring a test environment. it defaults to the null string and no string-based registration is performed. there are two situations where SystemVerilog parameters are the only option available .type parameters and parameters used to specify bit vector sizes. however . Registering Parameterized classes with the String-based Factory Parameterized classes use the `ovm_component_param_utils and `ovm_object_param_utils macros to register with the factory. endfunction virtual function ovm_object_wrapper get_object_type(). which is usually at the point where you invoke the simulator (See regression test performance below). Since a parameterized component does not register with the string-based factory by default. For example. To accomplish this. given a parameterized test class named alu_basic_test #(DATA_WIDTH). and the second is the string name that will be used to uniquely identify that type in the string-based registry. Occasionally. you might want to use the string-based factory to create a component or object. you will need to create a string-based registration for your top-level test classes so that they can be instantiated by run_test().€ The most common case where the string-based factory is used is during the call to run_test().http://uvm. you need to manually implement the actions that the param_utils macro performs. the latest time that these values can be set is at elaboration time.€ run_test() uses either its string argument or the string value from the OVM_TESTNAME plusarg to request a component from the string-based factory. Since the param_utils macro does not provide a value for the second parameter. Due to the nature of SystemVerilog parameters. endfunction The typedef in the code above creates a specialization of the ovm_component_registry type. "basic_test1") type_id. UVM/OVM Online Methodology Cookbook .the first is the type being registered (alu_basic_test #(DATA_WIDTH) in this case) with the type-based factory. In addition.one string-based and one type-based.€ You can rewrite the typedef to look like: typedef ovm_component_registry #(alu_basic_test #(DATA_WIDTH).Copyright (c) 2011 Mentor Graphics Corporation . but that type takes two parameter arguments .€ The param_utils macros only register with the type-based factory. return type_id::get().
So. adding a new parameter) usually requires careful editing of many different classes in many different files.g. is that these parameter values will not be used to help optimize the design for the best run-time performance. UVM/OVM Online Methodology Cookbook .€ This could have a significant impact on regression test performance where many test runs are made with different parameter values. Unfortunately. and will be specified later. Any change to a parameter list (e. Regression Test Performance with Parameters In order to increase simulation performance.mentor.http://uvm. including specifying top-level parameters. // Associate the string "basic_test1" with the value of DATA_WIDTH typedef alu_basic_test #(DATA_WIDTH) dummy. by using the command-line options +floatparameters (for Verilog) and +floatgenerics (for VHDL). initial begin run_test("basic_test1"). If necessary. The trade-off.g. when the time cost of optimization is a measurable percentage of the total simulation run time). To avoid this. then select the optimization to use at run time. you can tell vopt that certain parameters should be considered "floating". alu_rtl #(DATA_WIDTH) dut ( /* port connections */ ). QuestaSim performs some elaboration tasks. only when necessary (e. you can separately pre-optimize the design with several parameter values.Copyright (c) 2011 Mentor Graphics Corporation . this means that if you want to change the values of these parameters.ParameterizedTests module testbench #(DATA_WIDTH). These parameters tend to be declared together and are used in many places in the test environment. you can use the -g option in vsim to set the parameter value. however. endmodule 10 Note:€instead of a name like "basic_test1".€ This tool takes top-level parameters and "bakes" them into the design in order to take full advantage of the design structure for optimization. it is recommended that you use this technique sparingly. and is an error-prone process. you could use the macro described below to generate a string name like "basic_test_#(8)" with the actual parameter values as part of the string.€ Subsequent changes to the parameter value only require re-invocation of vsim with a new value and do not require a re-optimization of the design.com . Once the parameters have been specified as floating. in a separate optimization step via the vopt tool. Maintaining Consistency in Parameter Lists Many SystemVerilog parameters can naturally be grouped together in a conceptual "parameter list". An optional technique that can be employed is to create a set of macros that can reduce the chance of errors and enforce consistency. it requires a re-optimization of the entire design before invocation of the simulator.
ADDR_WIDTH(ADDR_WIDTH) ) String Value `define params_string $sformat("#(%1d.http://uvm. BUS_WIDTH.Copyright (c) 2011 Mentor Graphics Corporation . %1d)".BUS_WIDTH(BUS_WIDTH).mentor. By using the macros. ADDR_WIDTH) These macros keep with the reuse philosophy of minimizing areas of change. int ADDR_WIDTH = 8) Instantiation / Mapping `define params_map #(.ParameterizedTests 11 Declaration `define params_declare #(int BUS_WIDTH = 16.com . . there is one. well-defined place to make changes in parameter lists. UVM/OVM Online Methodology Cookbook .
UVM/OVM Online Methodology Cookbook . for convenience. the class has static methods to add the object to. string. this_t container = new(). T t ). and putting the object into the database: static function void set_value_in_global_config( string config_id .com . such as virtual interfaces. ovm_container has been created by Mentor that wraps a single piece of data. set_config_object("*" .i. Also. For any other type. mailboxes. endfunction This function • Creates the ovm_container object • Populates it with a piece of data • Stores the container object into the configuration database with global scope . a single parameterized.Config/Container 12 Config/Container € The ovm_container class OVM's configuration mechanism limits the type of data that can be stored to integral.http://uvm. config_id . // // Variable: t. endclass Putting the Object Into the OVM€Configuration Database You can use a static function to hide the details of creating a configuration object.mentor. any component can retrieve the object from the database.t = t. static function T get_value_from_config( ovm_component c . and retrieve the object from the configuration database. associative arrays. and object (derived from ovm_object). placing the value into the object. // See below for the source to these functions static function void set_value_in_global_config( string config_id .Copyright (c) 2011 Mentor Graphics Corporation . It also does not clone the object. container . /* Do not make a clone */ 0 ). queues. Rather than creating several different wrapper classes for each type of data to be stored. typedef ovm_container #( T ) this_t. container. general-purpose class.e. T t ). the data being wrapped // T t. the only way to get into the configuration database is to be a data member of a wrapper class that derives from ovm_object. Here is the class definition: class ovm_container #( type T = int ) extends ovm_object. The ovm_container class source code is available here [add link]. string config_id ).
$sformatf( "object associated with %s is not of the correct type" . config_id) ). o)) else c. return tmp. $sformatf( "component has no uvm_container associated with %s" . In this example the top module wraps a virtual interface and places the ovm_container object in the configuration database. Example use Here is a link to an example use of ovm_container to convey a virtual interface pointer to the testbench from the top module.get_config_object (config_id.mentor. But passing a value for the component allows the theoretical possibiliy that different values are present at different places in the OVM hierarchy for the same config_id. o)) else c. assert (c.ovm_report_error ( s_container_config_type_error_id .com .t. endfunction This static method gets the ovm_container associated with the config_id using the local config in component c.Config/Container 13 Getting an object out of the database static function T get_value_from_config( ovm_component c . Inside the testbench it fetches the ovm_container object from the database and extracts the virtual interface from it. ovm_container #(T) tmp. string config_id ).ovm_report_error ( s_no_container_config_id . If set_value_in_global_config has been used then the component c is in fact irrelevant since the value will be the same anywhere in the OVM component hierarchy. ovm_object o.Copyright (c) 2011 Mentor Graphics Corporation . assert ($cast (tmp.http://uvm. UVM/OVM Online Methodology Cookbook . config_id ) ).
however.Copyright (c) 2011 Mentor Graphics Corporation . In a testbench. coverage bin values. There is a common situation. `ovm_object_utils( wb_config ). // virtual wb_bus_if int int int int bit bit m_wb_id. there can be several configuration objects. a configuration object can have a static method that gets the object out of the database. // // // // // // Wishbone bus ID Wishbone bus master id for wishone agent id of MAC WB master Wishbone base address of MAC Ethernet address of MAC Ethernet address of testbench for sends/receives UVM/OVM Online Methodology Cookbook . In a typical testbench. there are any number of values that you might normally write as literals .bit size parameters.€ They are created as a subclass of ovm_object and group together all related configuration parameters for a given branch of the test structural hierarchy. The OVM configuration database takes care of the scope and storage of the object. where SystemVerilog parameters are the only option available .€ For convenience. which refers to the syntactic element. That situation is discussed in more detail in the Parameterized Tests document. // Configuration Parameters virtual wishbone_bus_syscon_if v_wb_bus_if. [47:0] m_mac_eth_addr. unsigned m_mac_wb_base_addr. or SystemVerilog parameters.€ There can also be an additional. randomization weights and other constraint expression values. as opposed to the term "SystemVerilog parameter". They are described in detail in the whitepaper OVM Configuration and Virtual Interfaces.mentor. [47:0] m_tb_eth_addr. // configuration container class class wb_config extends ovm_object. m_mac_id.€ These values can be represented by SystemVerilog variables. which must be set at compile time. string names. reusable mechanism for organizing configuration parameters. Types of configuration parameters Any point in your testbench where you would place a literal value .€ Examples include: • • • • for-loop limits array sizes values in randomization constraints values in SVA properties and sequences Configuration Objects Configuration objects are an efficient.com . but also occasionally strings . single configuration object that holds global configuration parameters.http://uvm.€ Here is an example configuration object. m_wb_master_id. which can be set (and changed) at runtime.is a candidate for a configuration parameter. each tied to a component.values such as for-loop limits. Parameterization permits scalability as well as flexibility to adapt a testbench to changing circumstances. This article uses the generic term "parameter" to mean any value that can be used to establish a specific configuration for a testbench. Because of the flexibility they offer.Config/Overview 14 Config/Overview € Introduction One of the key tenets of designing reusable testbenches is to use configuration parameters whenever possible.most commonly integral values. variables should be the preferred way to set configuration parameters.
m_mem_slave_wb_id = 0. .get_config_object( "wb_config" .http://uvm.mentor. then // casts it to the correct config object type. again checking for errors static function wb_config get_config( ovm_component c ). super. //set configuration info // NOTE The MAC is WISHBONE slave 0.Config/Overview int int int int m_mem_slave_size. end return t. wb_config_0. wb_config_0. o .. 0 ) ) begin c.. // 1 Mbyte wb_config_0.. $sformatf("the object associated with id %s is of type $s which is not the required type %s" .m_s_mem_wb_base_addr = 32'h00000000. // config object for WISHBONE BUS function void set_wishbone_config_params(). endfunction endclass Using a Configuration Object Any component that requires configuration should perform the following steps: • get its own configuration • create its own internal structure and behavior based on its configuration • configure its children The test component.ovm_report_error( "no config error ".v_wb_bus_if = ovm_container #(virtual wishbone_bus_syscon_if)::get_value_from_config(this. // the ID of slave mem // virtual interface UVM/OVM Online Methodology Cookbook . o ) ) begin c. unsigned m_s_mem_wb_base_addr.new( name ). type_name ) ).ovm_report_error( "config type error" .Copyright (c) 2011 Mentor Graphics Corporation . wb_config_0.get_type_name() .g.m_wb_master_id = 1. It then sets test-specific configuration parameters for components in the environment. as the top-level component gets its configuration values from either a "params package" or from the OVM configuration database (e.com . class test_mac_simple_duplex extends ovm_test. if( !c.m_mac_eth_addr = 48'h000BC0D0EF00.m_mac_id = 0. // the ID of the MAC master wb_config_0. wb_config wb_config_0. wb_config t. wb_master is WISHBONE master 1 wb_config_0 = new(). wb_config_0. // the ID of the wb master wb_config_0. wb_config_0. m_wb_verbosity. . return null. "wb_config" .m_mac_wb_base_addr = 32'h00100000. "this component has no config associated with id wb_config"). endfunction // Convenience function that first gets the object out of the OVM database // and reports an error if the object is not present in the database.m_tb_eth_addr = 48'h000203040506. wb_config_0. for a virtual interface handle).m_mem_slave_size = 32'h00100000. o. // WISHBONE 0 wb_config_0. mem_slave_0 is WISHBONE slave 1 // MAC is WISHBONE master 0. end if( !$cast( t . "WB_BUS_IF"). // // // // Size of slave memory in bytes base address of wb memory for MAC frame buffers Wishbone ID of slave memory verbosity level for wishbone messages 15 function new( string name = "" ). ovm_object o.m_wb_id = 0. return null.. m_mem_slave_wb_id.
class wb_m_bus_driver extends ovm_driver .set_report_verbosity_level(wb_verbosity). endtask // init the MAC's registers // get config object UVM/OVM Online Methodology Cookbook . endfunction ..build(). endclass 16 The components that use the configuration object data get access via the static helper function.... _global_reporter. m_config = wb_config::get_config(this). the drivers get the virtual interface handle. 0).€ Usually this should be done via its sequencer.. . . set_config_object("*"..com .connect(). set_wishbone_config_params().build(). wb_config m_config.. // put in config endfunction . endfunction function void connect(). . . // set local virtual if property endfunction function void end_of_elaboration()..m_wb_master_id.. // get config object m_id = m_config. // Wishbone bus master ID wb_config m_config. int wb_verbosity... function void build().. set_report_verbosity_level(m_config. .Copyright (c) 2011 Mentor Graphics Corporation . m_v_wb_bus_if = m_config.wb_config_0.. the MAC simple duplex sequence gets the configuration data from its sequencer and uses parameters to influence the data sent from the sequence: class mac_simple_duplex_seq extends wb_mem_map_access_base_seq. super..http://uvm. . bit [2:0] m_id. endfunction . super...m_wb_verbosity). endclass Configuring sequences A€sequence can use configuration data.m_wb_verbosity = 350. but it must get the data from a component. .v_wb_bus_if.. wb_txn). m_config = wb_config::get_config(m_sequencer). super... and verbosity from the object.mentor."wb_config".. #(wb_txn. init_mac(). function void build().€ Here. virtual wishbone_bus_syscon_if m_v_wb_bus_if.€ In this example. task body. ID..Config/Overview wb_config_0..
wb_config_0 = new().. ."wb_config". 0)... On the testbench side the test component gets the virtual interface handle from the OVM config database and applies it to appropriate configuration objects: class test_mac_simple_duplex extends ovm_test. endtask . endclass // virtual interface UVM/OVM Online Methodology Cookbook . most commonly using protocol modules and an ovm_container. //clear mode register in MAC wb_write_register("mode_reg". // put in config endfunction .v_wb_bus_if = ovm_container #(virtual wishbone_bus_syscon_if)::get_value_from_config(this. set_config_object("*". m_config. 0).. . ... endclass 17 Configuring DUT connections Setting up DUT-to-Testbench connections are one kind of configuration activity that is always necessary.http://uvm.Copyright (c) 2011 Mentor Graphics Corporation ...m_mac_eth_addr[31:00]).. function void set_wishbone_config_params().. // init the MAC ..wb_config_0.mentor..Config/Overview virtual task init_mac(). "WB_BUS_IF").com .€ It involves activity on the DUT side. //write MAC_ADDR1 register wb_write_register("mac_addr1_reg". m_config. //write MAC_ADDR0 register wb_write_register("mac_addr0_reg".m_mac_eth_addr[47:32]). // Get the virtual interface handle that was set in the top module or protocol module wb_config_0.
Config/Params Package 18 Config/Params Package € When a DUT and/or interface is parameterized the parameter values are almost always used in the testbench as well. The DUT parameters package should be used only for parameters that are shared between the DUT and the test. Example use of a Parameter Package In the WISHBONE bus based example below there are two WISHBONE bus devices.com .mentor. // WISHBONE general slave parameters parameter slave_addr_space_sz = 32'h00100000. A slave memory and an Ethernet Media Access Controller (MAC). there is a chance that a miscalculation may when making a change. Parameters are placed in a package (test_params_pkg) and then used in instantiating the WISHBONE devices in the top level module and inside the test class of the testbench. If you have test-specific parameters that are not used by the DUT. Instead define named parameter values in a package and use the named values in both the DUT side as well as the testbench side of the design. This helps avoid mistakes where a change is made to one side but not to the other. those values should be set directly in the test.http://uvm. if a test configuration parameter is some function of a DUT parameter.Copyright (c) 2011 Mentor Graphics Corporation . Or. import ovm_pkg::*. UVM/OVM Online Methodology Cookbook . These parameters should not be specified with direct literal values in your instantiations. Note that this package is not a place for all test parameters. The test parameter package is shown below: package test_params_pkg.
endmodule ).. // 2**slave_mem_size = size in words(32 bits) of wb slave memory parameter mem_slave_wb_id = 0..rst ( wb_bus_if.. // default is 1 Mbyte wb_config_0. function void set_wishbone_config_params().svh" endpackage //----------------------------------------------------------------class test_mac_simple_duplex extends ovm_test. )..m_mem_slave_size = 2**(mem_slave_size+2)..cyc ( wb_bus_if. .. .s_rty[mem_slave_wb_id] ).we ( wb_bus_if..s_stb[mem_slave_wb_id] ..rst ).s_cyc ). ). endpackage // WISHBONE bus master id of MAC // WISHBONE bus slave id of MAC The parameter values (mem_slave_size. . . Note that instead of using the numeric literal of 32'h00100000 for the address value.. parameter mac_slave_wb_id = 1. mem_slave_wb_id) usage in the top module to instantiate the WISHBONE bus slave memory module is shown below.0fffff // this is 1 Mbytes of memory wb_slave_mem #(mem_slave_size) wb_s_0 ( // inputs . Note the import of the test_params_pkg in the top_mac module: module top_mac.ack ( wb_bus_if. .s_wdata ). the code uses an expression involving a DUT parameter (mem_slave_size). // WISHBONE bus slave id of wb slave memory // MAC WISHBONE parameters parameter mac_m_wb_id = 0.s_addr ). slave 0: 000000 . //----------------------------------// WISHBONE 0. wb_config_0.din ( wb_bus_if.m_mem_slave_wb_id = mem_slave_wb_id.m_s_mem_wb_base_addr = mem_slave_wb_id * slave_addr_space_sz.rty ( wb_bus_if. wb_config wb_config_0.mentor.http://uvm.s_we ).s_ack[mem_slave_wb_id] . import test_params_pkg::*.s_rdata[mem_slave_wb_id] .com . . // config object for WISHBONE BUS .Config/Params Package 19 // WISHBONE slave memory parameters parameter mem_slave_size = 18. .stb ( wb_bus_if. package tests_pkg.sel ( wb_bus_if. `include "test_mac_simple_duplex. // WISHBONE interface instance // Supports up to 8 masters and up to 8 slaves wishbone_bus_syscon_if wb_bus_if().Copyright (c) 2011 Mentor Graphics Corporation . .. // outputs .clk ). //set configuration info wb_config_0 = new(). ) Parameter usage inside the test class of the testbench to set the configuration object values for the WISHBONE bus slave memory is shown below. import test_params_pkg::*.err ( wb_bus_if. .s_err[mem_slave_wb_id] .dout( wb_bus_if. . // base address of slave mem wb_config_0.. ). .. // WISHBONE bus slave id of slave mem UVM/OVM Online Methodology Cookbook .clk ( wb_bus_if.adr ( wb_bus_if.s_sel[3:0] ).
import ovm_pkg::*.s_addr ).0fffff // this is 1 Mbytes of memory wb_slave_mem #(WISHBONE_SLAVE_0::mem_slave_size) wb_s_0 ( // inputs .. 1) WISHBONE_SLAVE_1.Config/Params Package .ack ( wb_bus_if.http://uvm.. specified in the specializations WISHBONE_SLAVE_0 or WISHBONE_SLAVE_1 in the above code. // MAC WISHBONE parameters parameter mac_m_wb_id = 0. // outputs . // WISHBONE slave memory parameters class WISHBONE_SLAVE #(int mem_slave_size = 18. import test_params_pkg::*. ) UVM/OVM Online Methodology Cookbook . . typedef WISHBONE_SLAVE #(18. module top_mac. use the following syntax name_of_specialization::parameter_name as illustrated below. endclass // Specializations for each slave memory instance typedef WISHBONE_SLAVE #(18.s_wdata ). endpackage // WISHBONE bus master id of MAC // WISHBONE bus slave id of MAC To access or use the parameters.s_rdata[WISHBONE_SLAVE_0::mem_slave_wb_id] .clk ).stb ( wb_bus_if..rst ( wb_bus_if.s_ack [WISHBONE_SLAVE_0::mem_slave_wb_id] .dout( wb_bus_if. Then for each instance set the parameter values by creating a specialization of the parameterized class using a typedef. // WISHBONE interface instance // Supports up to 8 masters and up to 8 slaves wishbone_bus_syscon_if wb_bus_if(). endfunction ...we ( wb_bus_if. 0) WISHBONE_SLAVE_0.Copyright (c) 2011 Mentor Graphics Corporation .s_rty [WISHBONE_SLAVE_0::mem_slave_wb_id] ). endclass 20 Multiple Instances When you have multiple instances of parameter sets you can either create a naming convention for your parameters or you can use a prameterized class-based approach to organize your parameter sets on a per-instance basis. such as mem_slave_size or mem_slave_wb_id. . .mentor.err ( wb_bus_if. ). . . .s_err [WISHBONE_SLAVE_0::mem_slave_wb_id] . parameter mac_slave_wb_id = 2. endmodule ).adr ( wb_bus_if..s_we ). slave 0: 000000 . // WISHBONE general slave parameters parameter slave_addr_space_sz = 32'h00100000.cyc ( wb_bus_if.s_cyc ). Create a parameterized class which specifies the parameters and their default values.s_sel[3:0] ). ..rty ( wb_bus_if. ). package test_params_pkg.din ( wb_bus_if. ).s_stb [WISHBONE_SLAVE_0::mem_slave_wb_id] .clk ( wb_bus_if. int mem_slave_wb_id = 0).com . .sel ( wb_bus_if. //----------------------------------// WISHBONE 0..rst ).
rst. rst.http://uvm. din. UVM/OVM Online Methodology Cookbook . rty).Connect/Virtual Interface 21 Connect/Virtual Interface € Virtual Interaces A virtual interface is a dynamic variable that contains a reference to a static interface instance. we. As the interface instance is connected to the DUT pins. Virtual Interface Use Virtual interfaces are used because a class based test bench may not have ports and hence cannot directly connect to a Verilog or VHDL DUT. err.€ Note that the use of the term "virtual" here is not the in the same sense as is conventionally used in object oriented programming but rather it is what the IEEE 1800 committee chose to call these references. Using a virtual interface as a reference or handle to the interface instance. ports.) it is recommended to have a separate interface for each logical interface. dout. [31:0] dout.com . ack. din. adr. then the testbench can monitor and control the DUT pins indirectly through the interface elements. sel. Instead a SystemVerilog interface instance is connected to the ports of the DUT and the testbench communicates with the DUT through the interface instance. For all intents and purposes. The DUT may have one or more interfaces connected to its ports. stb. cyc. Consideration should also be given to encapsulate the interface instances inside a protocol module. stb. it can be thought of as a handle or reference to a SystemVerilog interface instance.mentor. functions. An example DUT (WISHBONE bus slave memory in diagram) has the following ports: module wb_slave_mem #(parameter mem_size = 13) (clk. the testbench can access the tasks. [31:0] adr. and internal variables of the SystemVerilog interface. If a DUT has multiple logical interfaces (different buses etc.Copyright (c) 2011 Mentor Graphics Corporation . cyc. input input output input clk.
€ The mem_slave_size is used to set the size of the slave memory device. reset and slave decode logic.. // 2**slave_mem_size = size in words(32 bits) of wb slave memory parameter mem_slave_wb_id = 0. import ovm_pkg::*. bit m_stb [num_masters]. bit m_we [num_masters]. Of interest here are the mem_slave_size and mem_slave_wb_id parameters.. bit m_rty. //only input not shared since it is the select bit s_we. // WISHBONE slave memory parameters parameter mem_slave_size = 18. // Wishbone bus system interconnect (syscon) // for multiple master.€ The WISHBONE bus has both masters and slaves with each having master and slave ids respectively.€ A link to the full source is further down in this article. err. multiple slave bus // max 8 masters and 8 slaves interface wishbone_bus_syscon_if #(int num_masters = 8.Copyright (c) 2011 Mentor Graphics Corporation . bit s_stb[num_slaves]. int data_width = 32.. bit s_rty[num_slaves].com . bit [7:0] s_sel. bit s_err[num_slaves]. // WISHBONE general slave parameters parameter slave_addr_space_sz = 32'h00100000. bit [7:0] m_sel[num_masters].€ Not shown here is the arbitration . logic [addr_width-1:0] m_addr [num_masters]. 22 In the WISHBONE bus environment there are a number of parameters that are shared between the DUT€and the testbench. bit s_cyc. int addr_width = 32) (). endpackage A WISHBONE bus interconnect interface to connect to this DUT is below. int num_slaves = 8. // WISHBONE bus slave id of wb slave memory .mentor.€ The mem_slave_wb_id is used to sets the WISHBONE slave id of the slave memory package test_params_pkg. // WISHBONE common signals bit clk. // WISHBONE master outputs logic [data_width-1:0] m_wdata[num_masters].http://uvm. rty. // WISHBONE master inputs bit m_err.Connect/Virtual Interface input input output .€ Only shown is the interconnect variables. bit m_ack [num_masters]. endmodule [3:0] sel. // WISHBONE slave inputs logic [data_width-1:0] s_wdata. bit m_lock[num_masters]. UVM/OVM Online Methodology Cookbook .€ They are defined in a test parameters package ( test_params_pkg) shown below. clock . logic [data_width-1:0] m_rdata. we. logic [addr_width-1:0] s_addr. // WISHBONE slave outputs logic [data_width-1:0] s_rdata[num_slaves]. bit [7:0] irq. This interconnect supports up to 8 masters and 8 slaves.. bit m_cyc [num_masters]. ack. bit rst.
stb ( wb_bus_if.clone()). //save off copy of original req transaction for(int i = 0.m_addr[m_id] = req_txn.. ) In the testbench access to the DUT is typically required in transactors such as drivers and monitors that reside in an agent.s_wdata ).cyc ( wb_bus_if. endinterface 23 To connect the interface to the DUT a hierarchical connection from the pins of the DUT to the variables in the interfaces is made as shown below.s_ack[mem_slave_wb_id] . Then in a WISHBONE bus driver the code might look like this. Note the use of the virtual interface property to access the interface variables€: class wb_m_bus_driver extends ovm_driver #(wb_txn.rty ( wb_bus_if.m_wdata[m_id] = req_txn.ack ( wb_bus_if. m_v_wb_bus_if. // Wishbone bus master ID wb_config m_config..sel ( wb_bus_if.we ( wb_bus_if. // Virtual Interface bit [2:0] m_id. import ovm_container_pkg::*.€ Note that the mem_slave_wb_id parameter from the test_params_pkg is used as a slave "slot id" to connect the slave memory to the correct signals in the interface.. i++) begin if(m_v_wb_bus_if. i<req_txn. . req_txn. endmodule ). ). $cast(orig_req_txn. .rst ). //exit if reset is asserted end m_v_wb_bus_if.0fffff // this is 1 Mbytes of memory wb_slave_mem #(18) wb_s_0 ( wb_slave_mem #(mem_slave_size) wb_s_0 ( // inputs . // outputs ..s_stb[mem_slave_wb_id] . //write UVM/OVM Online Methodology Cookbook .Copyright (c) 2011 Mentor Graphics Corporation . . .clk ( wb_bus_if. //----------------------------------// WISHBONE 0. m_v_wb_bus_if.count. import test_params_pkg::*. wb_txn). slave 0: 000000 .dout( wb_bus_if.din ( wb_bus_if.http://uvm.data[i]. . // WISHBONE interface instance // Supports up to 8 masters and up to 8 slaves wishbone_bus_syscon_if wb_bus_if()..Connect/Virtual Interface bit s_ack[num_slaves]. import tests_pkg::*. ).s_rty[mem_slave_wb_id] )... ).clk ). .m_we[m_id] = 1. Assume in the code example below that the virtual interface property m_v_wb_bus_if points to the instance of the wishbone_bus_syscon_if connected to the DUT (the next section discusses setting the virtual interface property).s_cyc ).rst) begin reset().. //WRITE 1 or more write cycles virtual task wb_write_cycle(ref wb_txn req_txn).rst ( wb_bus_if.s_err[mem_slave_wb_id] . . module top_mac. wb_txn orig_req_txn.mentor. . . // clear everything return.s_rdata[mem_slave_wb_id] .s_addr ). virtual wishbone_bus_syscon_if m_v_wb_bus_if.com .err ( wb_bus_if. .s_we ). import ovm_pkg::*.s_sel[3:0] ).adr ( wb_bus_if. ovm_analysis_port #(wb_txn) wb_drv_ap.adr.
Copyright (c) 2011 Mentor Graphics Corporation . Second the connection information must be distributed in the testbench to the appropriate agents with their transactors.orig_req_txn. endtask . Setting and distribution of configuration and connection information in the testbench ideally should be done in a single place € the test class.Connect/Virtual Interface m_v_wb_bus_if. req_txn. The test class should be the only testbench component that has hard coded information about the DUT. endclass 24 Setting Virtual Interface Properties in the Testbench There are two separate and distinct activities that occur in order to set a virtual interface property in the transactors (driver. This facilitates scalability and reusability for the rest of the testbench.m_stb[m_id] = 0.clk).m_stb[m_id] = 1. //broadcast orignal transaction m_v_wb_bus_if.m_cyc[m_id] = 1. 351 ) wb_drv_ap. m_v_wb_bus_if. // byte address so increment by 4 for word addr end `ovm_info($sformatf("WB_M_DRVR_%0d".gnt[m_id])) @ (posedge m_v_wb_bus_if. m_v_wb_bus_if.m_cyc[m_id] = 0. For the purposes of modularity and reuse this should be done in such a way that the DUT knows nothing about the testbench. First the DUT provides connection information to the testbench. When DUT configuration changes occur then changes to the testbench can be limited to the test.com . $sformatf("req_txn: %s". UVM/OVM Online Methodology Cookbook . The test class gets the information from the DUT and distributes it to the appropriate testbench components.m_id).m_ack[m_id] & m_v_wb_bus_if. and its interfaces..) of the testbench to point to the interface instance connected to the DUT.convert2string()). m_v_wb_bus_if.adr + 4. monitor etc..m_sel[m_id] = req_txn.write(orig_req_txn).mentor. The DUT should provide the necessary connection information to the testbench in a manner that does not require additional connections or modifications to the DUT or its associated logic.clk) while (!(m_v_wb_bus_if.byte_sel.adr = req_txn. @ (posedge m_v_wb_bus_if.http://uvm.
UVM/OVM Online Methodology Cookbook . If instead the agents each get information directly from the pool they need to know which information to fetch.mentor. If the information pool changes then appropriate changes are made in one location . One may think of the DUT connection and configuration information as a "pool" of information provided by the DUT to the testbench. The agents are not affected because they get their information in the same manner € from the test.http://uvm. If the information pool changes then changes would need to be made in the agents. In the recommended approach the test class gets information out of this pool and distributes it to the correct agents.com . If a change is made in the DUT configuration it is likely that change would be required in the agent.the test.€ The recommended approach is the first listed here which is using ovm_container.Connect/Virtual Interface 25 The questions may be asked: "Why not have the agents get the connection information directly from the DUT? Why have it distributed by the test? Doesn•t that seem more complicated and extra work?" The approach of the agents getting the information direct effectively hard codes information in the agents or transactors about the DUT and reduces scalability and reuse.Copyright (c) 2011 Mentor Graphics Corporation . There are two approaches to passing the location of the interface instance to the test class.
€ In the wishbone wrapper module code shown above a WB_ID parameter is used to uniquefy the wishbone bus interface instance and facilitate the placement in the configuration database using ovm_container. //environment for WISHBONE bus 1 wb_config wb_config_0. set_config_object("env_1*".. endclass // virtual interface // virtual interface If generate statements are used. // config object for WISHBONE BUS 1 . // DUT instance UVM/OVM Online Methodology Cookbook .€ Wishbone environement 0 is then connected to wishbone bus wrapper 0 an class test_mac_simple_duplex extends ovm_test.wb_config_1. function void set_wishbone_config_params(). Multiple Interface Instance Considerations When you have multiple instances of an interface type. endmodule In the test class the appropriate virtual interface is extracted and assigned to the appropriate wishbone configuration object..clk(clk)).m_v_wb_bus_bfm_if = ovm_container #(virtual wishbone_bus_bfm_if)::get_value_from_config(this. 0). 0)."wb_config".Connect/Virtual Interface 26 Bus Functional Models (BFM) Sometimes a the DUT connection is not directly to the ports of the DUT but rather is made through a BFM.. wb_config_1.wb_config_0..€ Often it is more convenient when there are multitple DUT instance and hence multiple interface instances to wrap the dut and its interfaces in a wrapper module. // put in config .Copyright (c) 2011 Mentor Graphics Corporation .€ The wrapper module may be parameterized to form unique id's internal to the wrapper for multiple instances.€ The code below shows the top level module with wrapper module instances: module top_mac. endfunction . each instance needs to have some sort of unique ID so that the transactors may know which interface to be connected to...mentor. wb_config_1 = new().m_wb_id = 1.. //set configuration info for WISHBONE 0 wb_config_0 = new().€ DUT-TB communication with a BFM€is discussed here.. the virtual interface assignment must also be done inside the generate block."wb_config". wb_config_0. // WISHBONE 1 wb_config_1. wb_bus_wrapper #(0) wb_bus_0(). i<NUM_INTERFACES. genvar i. Most often the BFM will have tasks for generating DUT transactions.com . set_config_object("env_0*". €This may be done by simply appending a numeric value to the end of the instance name if the interface instances are declared in an array or at the same level. // WISHBONE 0 // Get the virtual interface handle that was set in the top module or protocol module wb_config_0.. // put in config . "WB_BFM_IF_0"). //environment for WISHBONE bus 0 mac_env env_1. "WB_BFM_IF_1"). // config object for WISHBONE BUS 0 wb_config wb_config_1.m_wb_id = 0. . wb_bus_wrapper #(1) wb_bus_1(). i++) begin : gen // alu_if instance alu_if a_if(.. mac_env env_0. because variable indexing of generate block instances is not allowed.http://uvm. for (i = 0.m_v_wb_bus_bfm_if = ovm_container #(virtual wishbone_bus_bfm_if)::get_value_from_config(this.
a_if).val1(a_if.val2(a_if.mode).valid_o).http://uvm. .clk(a_if.mentor.val1).Connect/Virtual Interface alu_rtl alu ( .valid_i(a_if.i). . so use $sformatf ovm_container #(virtual alu_if)::set_value_in_global_config($sformatf("ALU_IF_%0d". .valid_i).val2). initial begin // Each virtual interface must have a unique name.Copyright (c) 2011 Mentor Graphics Corporation . . .result(a_if.result) ). end end 27 UVM/OVM Online Methodology Cookbook .mode(a_if.com .clk). .valid_o(a_if.
The component that actually accesses the DUT via the virtual interface sets its virtual interface property from the virtual interface in the supplied configuration object.. drivers. that points to a specific interface instance. Placing a Virtual Interface into the Configuration Database using ovm_container Since the configuration database can only store integral values. 2... Use ovm_container as a means to put a virtual interface. This approach supports scalability and reuse: • Since the transactor receives the interface instance information from the configuration object it is not affected by changes in the DUT configuration. There is a discussion here as to why one would take the approach of the test class fetching and distributing the information to the agents and transactors instead of having the transactors or agents fetch the data directly. initial begin //set interfaces in config space ovm_container #(virtual wishbone_bus_syscon_if)::set_value_in_global_config("WB_BUS_IF". €The example code below shows calling the ovm_container convenience method set_value_in_global_config() which creates a configuration object. strings. wb_bus_if).) that communicate with the DUT through that particular interface. or objects that derive from ovm_object. puts a virtual interface property inside the object and then places the object in the configuration database.mentor. The test class fetches the virtual interface from the configuration database and places it in a configuration object that is made available for the particular components (agents. This approach in general has three steps. • If you are using emulation. monitors etc. 3.com . // Top level module for a wishbone system with bus connection // multiple masters and slaves module top_mac.Copyright (c) 2011 Mentor Graphics Corporation . a container.. // WISHBONE interface instance // Supports up to 8 masters and up to 8 slaves wishbone_bus_syscon_if wb_bus_if(). . Mentor has created a general-purpose container object named ovm_container that this is available to download from the OVMworld contributions site (link here??). . this method works with protocol modules€ in the "Dual Top" methodology.http://uvm. run_test("test_mac_simple_duplex"). end endmodule // create and start running test UVM/OVM Online Methodology Cookbook . in order to store a virtual interface handle in the database. or "wrapper" object that holds the handle must be created and placed in the configuration database.VirtInterfaceConfigOVMContainer 28 VirtInterfaceConfigOVMContainer € Setting Virtual Interface Properties in the Testbench with the Configuration Database using ovm_container This is the recommended approach in assigning the actual interface reference to the virtual interface handles inside the testbench. 1. into the configuration database.
virtual wishbone_bus_syscon_if m_v_wb_bus_if.. The test then places the configuration object into the configuration database for providing access for the particular components (agents. // set local virtual if property endfunction . //set configuration info wb_config_0 = new(). monitors etc. // get config object .. set_wishbone_config_params(). // WISHBONE master driver class wb_m_bus_driver extends ovm_driver .... . class test_mac_simple_duplex extends ovm_test.build().."wb_config". m_v_wb_bus_if = m_config.) that communicate with the DUT through that particular interface. . endclass UVM/OVM Online Methodology Cookbook .com ....wb_config_0. drivers. // config object for WISHBONE BUS 29 function void set_wishbone_config_params().http://uvm.v_wb_bus_if = ovm_container #(virtual wishbone_bus_syscon_if)::get_value_from_config(this.connect(). super. endfunction function void connect(). . wb_txn).build().. super.v_wb_bus_if. function void build(). . // Virtual Interface wb_config m_config. The second argument to this method must be the same string that was used to place the virtual interface in the configuration database.mentor.VirtInterfaceConfigOVMContainer Making the Virtual Interface Available in the Testbench The test class creates a configuration object which has a virtual interface property.. // put in config endfunction function void build(). wb_config_0. . 0).Copyright (c) 2011 Mentor Graphics Corporation .. super. #(wb_txn. wb_config wb_config_0. // other WISHBONE bus configuration settings set_config_object("*".... m_config = wb_config::get_config(this).. endclass // virtual interface Setting Virtual Interface Property in Transactor The component that actually accesses the DUT via the virtual interface sets its virtual interface property from the virtual interface in the supplied configuration object.. endfunction .. "WB_BUS_IF"). It then assigns this property by calling the ovm_container convenience method get_value_from_config() (link) which returns the virtual interface from the configuration database.
The component that actually accesses the DUT via the virtual interface sets its virtual interface property from the virtual interface in the supplied configuration object. There is a discussion here as to why one would take the approach of the test class fetching and distributing the information to the agents and transactors instead of having the transactors or agents fetch the data directly. package test_params_pkg. This approach in general has 4 steps. A virtual interface is declared in a package. // WISHBONE bus virtual interface virtual wishbone_bus_syscon_if v_wb_bus_if.. Test class gets the virtual interface information from the package and assigns the virtual interface in a configuration object that is distributed to the appropriate components (agents.€ The recommended approach is to sue the test parameters package. monitors etc. In the top module containing the DUT and interface instance an assignment is made to the virtual interface in the package to point to the interface instance.com .€ An alternate approach.. 1. 3.Copyright (c) 2011 Mentor Graphics Corporation . import ovm_pkg::*.VirtInterfaceConfigPkg 30 VirtInterfaceConfigPkg € Setting Virtual Interface Properties in the Tesbench using a Package An alternative to using ovm_containerto provide virtual interface information to the test class is to use a package. Declaring Virtual Interface in the Test Parameters Package In the test parameters package declare a virtual interface pointer.http://uvm. drivers. It is the same in that the test uses a configuration object and the configuration database to distribute the virtual interface . 4. endpackage UVM/OVM Online Methodology Cookbook . The disadvantage is this approach is it can not be used with protocol modules which means this approach can not easily support emulation. . which is not recommended but is in industry use is to use the agent package. 2.€ This article will focus on the recomended approach. It differs in that a package is used to convey the virtual interface handle to the test class instead of using ovm_container. Using the Test Parameters Package This approach to assigning the actual interface reference to the virtual interface handles inside the testbench is very similar to the recommended approach using the configuration database with ovm_container.mentor.) that communicate with the DUT through that particular interface. It is recommended that this package be the test parameters package.
build().. .. run_test("test_mac_simple_duplex"). end endmodule // create and start running test 31 Making the Virtual Interface available in the Testbench The test class creates a configuration object which has a virtual interface property. drivers.. . //set configuration info wb_config_0 = new().) that communicate with the DUT through that particular interface. set_wishbone_config_params().com .. super. . endfunction ..http://uvm. module top_mac..wb_config_0. import test_params_pkg::*. . // Set WISHBONE bus virtual interface in config obj to virtual interface in test_params_pkg wb_config_0. // config object for WISHBONE BUS function void set_wishbone_config_params(). The test then places the configuration object into the configuration database for providing access for the particular components (agents. .. monitors etc. It then assigns this property from the virtual interface in the test parameters package.v_wb_bus_if = v_wb_bus_if. wb_config wb_config_0.. .. The virtual interface property may be imported or explicitly referenced. set_config_object("*"..mentor.. class test_mac_simple_duplex extends ovm_test.."wb_config"..Copyright (c) 2011 Mentor Graphics Corporation .. // WISHBONE interface instance // Supports up to 8 masters and up to 8 slaves wishbone_bus_syscon_if wb_bus_if().VirtInterfaceConfigPkg Assign Virtual Interface in the Test Parameters Package In the top module containing the DUT and the interface instance make an assignment in an initial block to point the virtual interface in the test parameters package to the interface instance. endclass UVM/OVM Online Methodology Cookbook . 0). // put in config endfunction function void build(). initial begin //set WISHBONE virtual interface in test_params_pkg v_wb_bus_if = wb_bus_if.
// Virtual Interface wb_config m_config. // WISHBONE master driver class wb_m_bus_driver extends ovm_driver . // set local virtual if property endfunction . super.Copyright (c) 2011 Mentor Graphics Corporation ...VirtInterfaceConfigPkg Setting Virtual Interface Property in Transactor The component that actually accesses the DUT via the virtual interface sets its virtual interface property from the virtual interface property in the supplied configuration object. .v_wb_bus_if.build(). super..mentor. // get config object . m_v_wb_bus_if = m_config.connect().... m_config = wb_config::get_config(this).com . endfunction function void connect()... wb_txn). virtual wishbone_bus_syscon_if m_v_wb_bus_if. endclass UVM/OVM Online Methodology Cookbook . 32 #(wb_txn.http://uvm. function void build().
. `include "wb_m_bus_driver. Virtual Interface Variable in Package It is recommended that the virtual interface variable be created in the package of the agent that connects to the interface instance. endpackage // virtual wishbone interface pointer UVM/OVM Online Methodology Cookbook .svh" .. ..€ From the package. It has the following disadvantages that limit reusability: • Parameterized interfaces cannot be declared in the package with generic parameter values . or do not have multiple instances of an interface and is not recommended for general use.http://uvm.mentor. This method has the advantage of simplicity. for example.VirtInterfacePackage 33 VirtInterfacePackage € Setting Virtual Interface Properties in the Testbench with Packages An easy way of assigning the actual interface reference to the virtual interface handles inside the testbench is by creating a virtual interface variable in a package. monitors etc.they must use actual values. Because of its disadvantages however this approach should only be considered for relative simple designs that do not have parameterized interfaces. Any changes to parameter values would then force a recompilation.. package wishbone_pkg.Copyright (c) 2011 Mentor Graphics Corporation . • It introduces an additional dependency on an external variable. any change to the virtual interface name would require changes in any components that referenced the variable. of the agent.com . the virtual interface variable becomes directly accessible to all components which include the drivers.. So.. virtual wishbone_bus_syscon_if v_wb_bus_if. .svh" `include "wb_bus_monitor.
#(wb_txn. . . m_v_wb_bus_if = v_wb_bus_if... just assign the actual interface instance to the package variable: module top_mac. // WISHBONE interface instance wishbone_bus_syscon_if wb_bus_if(). .Copyright (c) 2011 Mentor Graphics Corporation . initial begin //set virtual interface to wishbone bus wishbone_pkg::v_wb_bus_if = wb_bus_if. function void connect()..http://uvm. // set local virtual if property endfunction . there is only one line in the driver that would need to change. end endmodule 34 Any component that uses the virtual interface should create a local handle and assign the package variable to the local handle in the connect() method. since the package variable is visible.. but this step makes the code more reusable.mentor.. .. wb_txn). UVM/OVM Online Methodology Cookbook .connect().com . super. For example.... if the package variable name changes.. virtual wishbone_bus_syscon_if m_v_wb_bus_if. endclass Strictly speaking.VirtInterfacePackage In the top level module.. // wishbone master driver class wb_m_bus_driver extends ovm_driver . the use of a local virtual interface handle is not necessary..
you must pass the virtual interface handle down through intermediate levels of the hierarchy that have no use for the virtual interface. you would have to embed extra decision-making code (as in the examples above). and calls an equivalent function (also named assign_vi) on one or more child components.€ Many users naturally assume that this is the recommended method because of its use in the example. i++) begin slaves[i]. end for(int i = 0. end endfunction : assign_vi In the agent: function void assign_vi(virtual interface xbus_if xmi). This is repeated down the hierarchy until a leaf component is reached.To reach leaf components in the environment. UVM/OVM Online Methodology Cookbook . this.assign_vi(xi).assign_vi(xi).assign_vi(xi).xmi = xmi.Copyright (c) 2011 Mentor Graphics Corporation .assign_vi(xmi).VirtInterfaceFunctionCallChain 35 VirtInterfaceFunctionCallChain € Function Call Chaining It is unfortunate that this approach to assigning€actual interface reference to the virtual interface handles inside the testbench is the one that is used in the xbus example that is prevalent in the OVM user's guide. i < num_masters. i++) begin masters[i]. these functions must be updated • Unnecessary extra work .assign_vi(xmi).assign_vi(xbus_tb_top.If the test environment hierarchy changes. In the connect() function of test env: xbus0. end endfunction : assign_vi In the monitor: function void assign_vi(virtual interface xbus_if xmi).com . In the xbus env: function void assign_vi(virtual interface xbus_if xi). i < num_slaves.http://uvm.mentor. endfunction There are two main reasons why this method should not be used. monitor.xi0). or write each function to iterate over all children or and call the function on each child. xi0 = xi. driver. if (is_active == OVM_ACTIVE) begin sequencer.assign_vi(xmi). Also. if( bus_monitor != null) begin bus_monitor. Any components that need the virtual interface declare a local handle and assign the function argument to the local handle. end for(int i = 0. • It is not reusable . to make this method more reusable with respect to environment hierarchy changes. This approach is not recommended. It involves creating a function (called assign_vi in the example) that takes a virtual interface handle as an argument.
com .VirtInterfaceFunctionCallChain This requires even more unnecessary work.Copyright (c) 2011 Mentor Graphics Corporation .http://uvm. 36 UVM/OVM Online Methodology Cookbook .mentor.
m_id).. Then a standard virtual interface connection can be made to the BFM and the testbench transactors can directly access the BFM trasaction tasks..BusFunctionalModels 37 BusFunctionalModels € Bus Functional Models for DUT€communication Sometimes a the DUT connection is not directly to the ports of the DUT but rather is made through a BFM. slave 0: 000000 . bit [2:0] m_id). Example code for the wrapper module is below: module wb_bus_wrapper #(int WB_ID = 0). wb_bfm. There are several different "flavors" of BFM: Verilog Module BFM € Can be modified If the BFM is a Verilog module the first choice with this type of connection is to modify the BFM to be an interface... the DUT and an instance of an interface as shown in the diagram below. wb_bus_bfm_if).WB_ID). .mentor. Or it simply can not be edited. // WISHBONE BFM instance wishbone_bus_syscon_bfm wb_bfm().Copyright (c) 2011 Mentor Graphics Corporation . initial //set interface in config space ovm_container #(virtual wishbone_bus_bfm_if)::set_value_in_global_config( $sformatf("WB_BFM_IF_%0d".). The interface acts as a "proxy" for the BFM to the testbench transactors.€ See the diagram below. endinterface // Interface instance wishbone_bus_bfm_if #(WB_ID) wb_bus_bfm_if(.0fffff wb_slave_mem #(mem_slave_size) wb_s_0 (. // Interface interface wishbone_bus_bfm_if #(int ID = WB_ID) (input bit clk).com ..wb_write_cycle(req_txn. For example to do a wishbone bus write transaction the driver would call the write task in the interface which in turn would call the write task in the BFM..clk)).. It may have an instance of a module in which case it can not be changed to an interface.). UVM/OVM Online Methodology Cookbook . In this case a wrapper module is introduced. // WISHBONE 0. As shown in the diagram below. typically the BFM will have tasks for generating DUT transactions.http://uvm. Verilog Module BFM € Can not be modified The Verilog BFM may not be able to be modified for several reasons. The wrapper module contains the instance of the BFM. endtask // other tasks not shown .. // MAC 0 eth_top mac_0(. // Methods //WRITE 1 or more write cycles task wb_write_cycle(wb_txn req_txn.clk(wb_bfm.
com .BusFunctionalModels 38 endmodule UVM/OVM Online Methodology Cookbook .mentor.Copyright (c) 2011 Mentor Graphics Corporation .http://uvm.
// protocol module for MAC MII interface mac_mii_protocol_module #(.. //----------------------------------// WISHBONE 0. ). connection and support logic. ). This top level module contains the DUT and its associated interfaces.100fff // It is WISHBONE Master 0 eth_top mac_0 ( . protocol modules. //----------------------------------// MAC 0 // It is WISHBONE slave 1: address range 100000 . wire [3:0] MRxD. slave 0: 000000 . reuse etc. Dual top is a necessity for emulation.. import test_params_pkg::*. wb_bus_if). The code to create the testbench is placed in its own module.com ..€ The other top module containing the test bench stays running in the simulator. endmodule UVM/OVM Online Methodology Cookbook .€ If the testbench is only going to be used in simulation dual top is not necessary but may however still provide a useful level of encapsulation for modularity.Copyright (c) 2011 Mentor Graphics Corporation . // WISHBONE interface instance // Supports up to 8 masters and up to 8 slaves wishbone_bus_syscon_if wb_bus_if(). ). import ovm_container_pkg::*. Verilog allows for more than one top level module in a simulation. // wires for MAC MII connection wire [3:0] MTxD.INTERFACE_NAME("MIIM_IF")) mii_pm( . All this "stuff" can get messy and hard to manage. It also contains the code to create the testbench..mentor. A different way to manage all this stuff is to encapsulate everything associated directly with the DUT in a wrapper module.. initial //set WISHBONE virtual interface in config space ovm_container #(virtual wishbone_bus_syscon_if)::set_value_in_global_config("WB_BUS_IF".http://uvm. Communicating the virtual interface connection between the DUT wrapper module and the testbench is done using the configuration database with ovm_container approach. Neither of these two modules are instantiated but rather are treated as top level modules.DualTop 39 DualTop € Typically a DUT-TB setup has a single SystemVerilog module as the top level.0fffff // this is 1 Mbytes of memory wb_slave_mem #(mem_slave_size) wb_s_0 ( .. import ovm_pkg::*.€ The DUT€wrapper is the stuff that goes in the emulator. This arrangement is referred to as dual top. DUT Wrapper module In this example the MAC DUT and its associated interfaces and protocol module and the WISHBONE slave memory along with the WISHBONE bus logic are contained in DUT wrapper module top_mac module top_mac.
DualTop 40 Testbench top module In the top module that creates the testbench is an initial block that calls run_test(). normal: clean cmp vsim +nowarnTSCALE -c top top_mac -suppress 3829 -do "run -all" .€ These are necessary for compilation of the run_test() line of code. // This the top for the tesbench in a dual top setup // The dut is in the top_mac dut wrapper module module top.Copyright (c) 2011 Mentor Graphics Corporation . import tests_pkg::test_mac_simple_duplex. UVM/OVM Online Methodology Cookbook .. initial run_test("test_mac_simple_duplex")..mentor. import ovm_pkg::run_test.http://uvm.€ Note the imports ovm_pkg::run_test and tests_pkg::test_mac_simple_duplex. endmodule // create and start running test Questasim with more than one top level module The call to vsim includes more than one top module #Makefile ...com .
• The top level module is protected from changes to the virtual interface registration/connection technique.€ The one shown in the example is the Media Independent Interface (MII) which is where Ethernet packets are transferred to the physical interface. // // Rx output output logic logic[3:0] INTERFACE_NAME = "") ( Transmit Transmit Transmit Transmit clock (from PHY) nibble (to PHY) enable (to PHY) error (to PHY) mrx_clk_pad_o.€ While it is not required that protocol modules be used together with the dual top methodology it is likely to be used mainly in connection with the dual top approach since it is also required for emulation. QVL instances (which are not allowed inside an interface).com . and so forth. a QVL€MII€monitor and code for putting the interface instance location in the configuration database using ovm_container. // Tx output logic mtx_clk_pad_o. // input logic mtxen_pad_o. // Receive clock (from PHY) mrxd_pad_i. • You can instantiate QVL instances (which would not be allowed inside the SV interface) as well as add other assertions that might not already be present in the interface. They may however still provide a useful level of encapsulation for modularity. protocol modules protect the top level from changes: • Any re-mapping due to changes in the interface can be done inside the protocol module.€ If the testbench is only going to be used in simulation protocol modules are not necessary. module mac_mii_protocol_module #(string input logic wb_rst_i.mentor. // input logic[3:0] mtxd_pad_o.€ A MAC has multiple interfaces.€ In this example the protocol module contains the MII€interface instance. // Receive nibble (from PHY) UVM/OVM Online Methodology Cookbook .Copyright (c) 2011 Mentor Graphics Corporation .http://uvm. // input logic mtxerr_pad_o. associated assertions. When emulation is a consideration protocol modules provide a level of encapsulation necessary to isolate the changes that occur in the agent and interface in moving between simulation and emulation.ProtocolModules 41 ProtocolModules € Protocol modules are wrapper modules that encapsulate a DUT interface. By adopting encapsulation. Example: In this example an Ethernet Media Access Controller (MAC) is the DUT. reuse etc.
Copyright (c) 2011 Mentor Graphics Corporation . assign miim_if. .reset(wb_rst_i). . .Mdo_OE = md_padoe_o // Instantiate QVL Checker qvl_gigabit_ethernet_mii_monitor mii_monitor( . .half_duplex(1'b0) ).MTxEn = mtxen_pad_o.areset(1'b0). miim_if). // Connect interface to protocol signals through module ports assign mtx_clk_pad_o = miim_if. . // Instantiate interface mii_if miim_if(). input logic md_pad_o.rx_dv(miim_if. assign miim_if.MCrs assign assign assign assign md_pad_i = miim_if.mrx_clk.Mdi_I miim_if.. mrxerr_pad_i. .col(miim_if. // Connect interface to testbench virtual interface string interface_name = (INTERFACE_NAME == "") ? $sformatf("%m") : INTERFACE_NAME.MRxD).rx_er(miim_if. mrxdv_pad_i = miim_if.MTxErr = mtxerr_pad_o .mtx_clk). input logic mdc_pad_o. This is guaranteed to be unique.MColl assign mcrs_pad_i = miim_if.Mdo_O = md_pad_o miim_if. input logic md_padoe_o ). . then it is up to the designer to make sure that the names chosen are unique within the enclosing module.MCrs) .com . // Receive data valid (from PHY) // Receive data error (from PHY) // Collision (from PHY) // Carrier sense (from PHY) // MII data input (from I/O cell) // MII Management data clock (to PHY) // MII data output (to I/O cell) // MII data output enable (to I/O cell) 42 // Common Tx and Rx output logic output logic // MII Management interface output logic md_pad_i.rx_clk(miim_if. mcoll_pad_i.MTxD). end endmodule It should be noted that if the parameter INTERFACE _ NAME is not set. . mcrs_pad_i. UVM/OVM Online Methodology Cookbook .txd(miim_if. . .tx_er(miim_if. If this parameter is explicitly set.MRxErr . mrxerr_pad_i = miim_if.ProtocolModules output output logic logic mrxdv_pad_i. assign mcoll_pad_i = miim_if. . the hierarchical path of this module). initial begin ovm_container #(virtual mii_if)::set_value_in_global_config(interface_name.tx_clk(miim_if. . mrxd_pad_i = miim_if.MRxDV . .mtx_clk.MRxDV).MRxErr).MColl).MTxEn). . . .mrx_clk).http://uvm.mentor. then the default value is€%m (i. assign assign assign assign mrx_clk_pad_o = miim_if.MTxD = mtxd_pad_o. .MTxErr). assign miim_if.MRxD.e.rxd(miim_if.crs(miim_if. .Mdc_O = mdc_pad_o miim_if. import ovm_container_pkg::*.tx_en(miim_if.
endtask endmodule UVM/OVM Online Methodology Cookbook .. with a Bus Functional Model (BFM) which drives transactions on the DUT or the internals of the DUT using the SystemVerilog bind construct.€ The full code may be downloaded with the other example code shown later. ). // WISHBONE bus arbitration logic . int data_width = 32..). endtask //READ 1 or more cycles task wb_read_cycle(wb_txn req_txn. output logic rst. Example BFM Here is a diagram showing a BFM for the WISHBONE bus that will be used in the examples here.com . .€ The abstract/concrete class approach should only be considered when virtual interfaces can not be used or as a secondary approach in the case of legacy BFM's that can not be modified to be an interface. logic along with tasks which generate WISHBONE bus transactions (read.. int num_slaves = 8.. The most typical use is with BFMs. There is also a form of this approach that is in use that is known within Mentor Graphics as Two Kingdoms.. . .http://uvm. clock.. write etc. As with using virtual interfaces this approach may be set up for the transactors in the testbench to communicate with the pins of the DUT. reset etc. bit [2:0] m_id = 1).. Here is code from the BFM.. The discussion in this article going forward will focus only on use of the abstract/concrete class approach with BFMs. Virtual interfaces is the recommended approach for DUT-TB communication. output wb_txn rsp_txn). module wishbone_bus_syscon_bfm #(int num_masters = 8.Connect/AbstractConcrete 43 Connect/AbstractConcrete € Abstract/Concrete Class approach to DUT-TB communication A handle based approach to DUT-TB communication that does not use virtual interfaces is referred to in the OVM industry as the abstract/concrete class approach.Copyright (c) 2011 Mentor Graphics Corporation . int addr_width = 32) ( // WISHBONE common signals output logic clk. . bit [2:0] m_id = 1.mentor.. The wishbone bus BFM is connected to the WISHBONE bus and has the WISHBONE bus arbitration... endtask // Monitor bus transactions task monitor(output wb_txn txn). //Slave address decode .. // BFM tasks //WRITE 1 or more write cycles task wb_write_cycle(wb_txn req_txn.
http://uvm.€ Additionally it does not strictly follow the abstract/concrete class pattern with the use of a base class handle in the drivers. The concrete class is defined inside of a wrapper module which also instantiates the BFM.Copyright (c) 2011 Mentor Graphics Corporation . UVM/OVM Online Methodology Cookbook . More details. Abstract/concrete class use model This approach is recommended as it follows the recommended use model for passing information from the DUT to the testbench which is discussed in detail here in the article on virtual interfaces. including ports.€ A factory override is set up of the concrete class for the base class. monitors etc. Inside the testbench a base handle is created and then a factory create is called on the handle resulting in a concrete object being created. The implementations of the methods are not in the abstract class but rather are in a derived class which is referred to as the concrete class. In this diagram an instance of the BFM is created inside the wrapper module. More details.€ There is the recommended use model which follows the abstract/concrete class pattern.€ It is not recommended as it does not follow the recommended use model for passing information from the DUT to the testbench which is discussed in detail here in the article on virtual interfaces. Two Kingdoms use model This approach is what is known as the Two Kingdoms.com . The abstract class has pure virtual methods and properties which define a public interface for accessing information. functions. instead it uses the factory.mentor.method_name). Inside the testbench a base class handle inside of the transactors (drivers. tasks. In this use model an actual instance of the concrete class is created inside of the wrapper module where the concrete class is defined. The methods of the concrete class access the BFM methods by hierarchical reference through this instance (bmf_instance_name. class handles.Connect/AbstractConcrete 44 Abstract/Concrete Classes First an abstract class (SystemVerilog virtual class) is defined. module instances etc. is the wrapper module and hence its methods can access anything defined inside of the wrapper module (wb_bus_protocol_module). diagrams and an example using a BFM are here. DUT Connection Since it is defined inside the wrapper module the scope of the concrete class. Two different use models After declaration of the abstract class and the concrete class inside the wrapper module there are two use models.) is made to point to this derived class instance. wb_bus_concr_c in the example. through use of ovm_container and the configuration database. variables. monitors etc to point to the concrete class instance but rather the drivers and monitors themselves are the abstract/concrete classes. Then there is a use model that is called the two kingdoms that is not recommended. diagrams and an example using a BFM are here.
€ It may also provide code that writes/reads variables inherited from the abstract class.€ Note too that the abstract class inherits from ovm_component and so inherits the phase methods etc. int data_width = 32.€ Note the pure virtual methods which define a public interface to this class.com . // wait for an interrupt pure virtual task wb_irq(wb_txn req_txn.€ It is defined inside the wrapper module wb_bus_protocol_module which is a protocol module. .. module wb_bus_protocol_module #(int WB_ID = 0. int num_slaves = 8. and in particular the BFM module instance. bit [2:0] m_id. ovm_component parent).http://uvm. including ports.€ This class is defined inside of a wrapper module that includes an instance of the BFM.€ As part of the public interface too is an event to represent the posedge of the clock.new(name. //READ 1 or more cycles pure virtual task wb_read_cycle(wb_txn req_txn. bit [2:0] m_id).. For example the concrete driver class wb_write_cycle() task€ calls the wb_write_cycle() task inside the BFM.€ Below is the code for an example abstract class called wb_bus_abs_c.€ Note that this class inherits from the abstract class and provides implementations of the methods. endfunction // API methods //WRITE 1 or more write cycles pure virtual task wb_write_cycle(wb_txn req_txn. UVM/OVM Online Methodology Cookbook . € At the bottom of the wb_bus_protocol_module is the instance (wb_bfm) of the BFM (wishbone_bus_syscon_bfm). output logic rst.€ Since it is defined inside the wrapper module the scope of the concrete class.Copyright (c) 2011 Mentor Graphics Corporation . tasks.Connect/AbstractConcreteOVMContainer 45 Connect/AbstractConcreteOVMContainer € Abstract Class The Abstract class is defined as part of the agent in the testbench and is included in the agent package. is the wrapper module and hence its methods can access anything defined inside of the wrapper module.mentor. super. int num_masters = 8. class handles.€ It is required to override any pure virtual methods. functions. endclass Concrete Class The concrete class is derived from the abstract class. output wb_txn rsp_txn). event pos_edge_clk. //Get a wb transaction from the bus pure virtual task monitor(output wb_txn txn). variables. Here is the code for the concrete class wb_bus_concr_c. output wb_txn rsp_txn). function new(string name. int addr_width = 32) ( // Port declarations // WISHBONE common signals output logic clk.€ These methods are straight forward in that they are "proxy" methods that simply call the corresponding method inside the BFM.parent). providing implementations. // Abstract class for abstract/concrete class wishbone bus communication //---------------------------------------------virtual class wb_bus_abs_c extends ovm_component.
).Connect/AbstractConcreteOVMContainer ). function new(string name = "". endtask // wait for an interrupt task wb_irq(wb_txn req_txn. such as a driver or monitor.http://uvm. endfunction // API methods // simply call corresponding BFM methods //WRITE 1 or more write cycles task wb_write_cycle(wb_txn req_txn.parent).wb_irq(req_txn. and made to point to an instance of an interface connected to the DUT. .mentor. With a virtual interface connection a virtual interface handle is placed inside the€ transactor. wb_bfm. . UVM/OVM Online Methodology Cookbook ...Copyright (c) 2011 Mentor Graphics Corporation . output wb_txn rsp_txn). m_id). endtask endclass . endtask task monitor(output wb_txn txn). endmodule 46 Connecting the testbench to the DUT The testbench DUT connection with the abstract and concrete classes is similar to virtual interface connections. wb_bfm. wb_bfm. // Concrete class declaration class wb_bus_concr_c #(int ID = WB_ID) extends wb_bus_abs_c.wb_write_cycle(req_txn. output wb_txn rsp_txn).monitor(txn).wb_read_cycle(req_txn.. forever @ (posedge clk) -> pos_edge_clk. endtask //READ 1 or more cycles task wb_read_cycle(wb_txn req_txn.€ An instance of the concrete class is made inside the wrapper module(wb_bus_protocol_module) and the abstract class handle is made to point to the concrete class instance.€ In the abstact/concrete class approach a handle of the abstract class type is placed inside the transactor. wb_bfm.com . super. .rst( rst ).new(name.. // WISHBONE BFM instance wishbone_bus_syscon_bfm wb_bfm( .. bit [2:0] m_id). rsp_txn). bit [2:0] m_id. rsp_txn).clk( clk ). endtask task run(). ovm_component parent = null). m_id..
. // WISHBONE BFM instance wishbone_bus_syscon_bfm wb_bfm( .com .clk( clk ).. The code below shows the instance of the concrete class inside the wrapper module and a method (a "lazy allocator" ie a method that doesn't allocate the instance until it is needed) used for creating the concrete class instance.WB_ID) . ).. int num_slaves = 8. int data_width = 32. // lazy allocation of concrete class function wb_bus_abs_c get_wb_bus_concr_c_inst().rst( rst ). .Copyright (c) 2011 Mentor Graphics Corporation . ). if(wb_bus_concr_c_inst == null) wb_bus_concr_c_inst = new().Connect/AbstractConcreteOVMContainer 47 In the diagram above the DUTs and the wb_bus_protocol_module are wrapped in a wrapper module the wb_bus_wrapper. .http://uvm. In the code above inside the initial block a handle to UVM/OVM Online Methodology Cookbook . . return (wb_bus_concr_c_inst). int addr_width = 32) ( // Port declarations // WISHBONE common signals output logic clk. module wb_bus_protocol_module #(int WB_ID = 0. int num_masters = 8. // Concrete class declaration class wb_bus_concr_c #(int ID = WB_ID) extends wb_bus_abs_c. get_wb_bus_concr_c_inst()). .. endclass // instance of concrete class wb_bus_concr_c wb_bus_concr_c_inst. endfunction initial //set concrete class object in config space ovm_container #(wb_bus_abs_c)::set_value_in_global_config( $sformatf("WB_BUS_CONCR_INST_%0d".€ This is for modularity and convenience in instantiating multiple wishbone buses.mentor. output logic rst. endmodule The location of the concrete class instance is provided to the transactor in the same manner as in virtual interface connections using ovm_container to pass a handle that points to the concrete class instance to the test class and then through a configuration object from the test class to the transactor...
. super.build().get(req_txn).Copyright (c) 2011 Mentor Graphics Corporation .parent). endfunction . bit [2:0] m_id.OVM_LOW ) WRITE: wb_write_cycle(req_txn). class test_mac_simple_duplex extends ovm_test.€ This approach is recommended as it follows the recommended use model for passing information from the DUT to the testbench which is discussed in detail here in the article on virtual interfaces. set_wishbone_config_params().. super. 0). // put in config .new(name. wb_txn)."wb_config". wb_config_0 = new(). $sformatf("WB_BUS_BFM_DRIVER_C_INST_%0h".m_wb_bus_abs_c. function void set_wishbone_config_params().. $sformatf("wb_txn %0d the wb_txn_type was type NONE".get_transaction_id()).. // concrete class object . In the test class the handle to the concrete driver class instance is fetched from the configuration database and placed inside a configuration object which is made available to the wishbone agent. . // WISHBONE master driver class wb_bus_bfm_driver extends ovm_driver #(wb_txn. RMW: wb_rmw_cycle(req_txn).pos_edge_clk) #1. // Assign abstract class handle to concrete object m_wb_bus_abs_c = m_config.m_wb_bfm_driver = ovm_container #(wb_bus_bfm_driver_base)::get_value_from_config(this. req_txn. wb_config_0. endfunction function void build(). // get transaction @ ( m_wb_bus_abs_c. mac_env env_0...build(). wb_bus_abs_c m_wb_bus_abs_c.Connect/AbstractConcreteOVMContainer the concrete instance is placed inside the configuration space using ovm_container. // Wishbone bus master ID wb_config m_config.m_wb_master_id. m_config = wb_config::get_config(this). this)..http://uvm..txn_type) //what type of transaction? NONE: `ovm_info($sformatf("WB_M_DRVR_%0d".. READ: wb_read_cycle(req_txn).mentor.m_id)... endfunction task run().wb_config_0. endfunction function void build(). forever begin seq_item_port. ovm_component parent). // get config object m_id = m_config. // config object for WISHBONE BUS 0 . // sync to clock edge + 1 time step case(req_txn. wb_config wb_config_0.m_wb_id)).com . wb_drv_ap = new("wb_drv_ap". function new(string name. wb_config_0. set_mii_config_params(). `ovm_component_utils(wb_bus_bfm_driver) ovm_analysis_port #(wb_txn) wb_drv_ap.. UVM/OVM Online Methodology Cookbook . super. endclass 48 Inside the driver an abstract class handle is made to point to the concrete class instance by fetching the location from the configuration object provided by the test class. wb_txn req_txn.. set_config_object("env_0*".
m_wb_bus_abs_c.m_id). seq_item_port. m_id.€ In this example an integer value which is the WISHBONE bus id (WB_ID) is supplied to make a unique string with.mentor.wb_write_cycle(req_txn. rsp_txn).clone()). A way to do this is to parameterize the wrapper class and the concrete class. "Wishbone RMW instruction not implemented yet". $cast(orig_req_txn.wb_irq(req_txn. //broadcast orignal transaction endtask //RMW ( read-modify_write) virtual task wb_rmw_cycle(ref wb_txn req_txn).put(rsp_txn). MACs etc. wb_txn orig_req_txn.€ This is done to make a correlation between bus id's and the concrete classes. The details for the multiple instances are not shown in this article but can be viewed in the the source code.get_transaction_id()) ) endcase end endtask //READ 1 or more cycles virtual task wb_read_cycle(wb_txn req_txn).€ Separate configurtion objects are generated for each of the wishbone environments.€ The full source code in this article actually has two wishbone wrapper class instances inside of top_mac instead of the one shown in the diagrams and so ther are two WISHBONE buses.write(orig_req_txn).Connect/AbstractConcreteOVMContainer WAIT_IRQ: fork wb_irq(req_txn).write(rsp_txn). Multiple instance considerations When there are multiple instances of the DUT & BFM then€ each concrete class instance needs to be "uniquified" so the correct pairing can be made. //broadcast read transaction with results endtask //WRITE 1 or more write cycles virtual task wb_write_cycle(wb_txn req_txn). `ovm_info($sformatf("WB_M_DRVR_%0d". wb_txn rsp_txn. // send rsp object back to sequence wb_drv_ap. req_txn.Copyright (c) 2011 Mentor Graphics Corporation . //save off copy of original req transaction m_wb_bus_abs_c.OVM_LOW ) endtask // wait for an interrupt virtual task wb_irq(wb_txn req_txn). m_id). wb_txn rsp_txn.€ Another approach to making the concrete class instance unique is described in the article on protocol modules (see at the bottom). join_none default: `ovm_error($sformatf("WB_M_DRVR_%0d". wb_drv_ap. req_txn. m_wb_bus_abs_c. On the testbench side it has a wishbone environment for each of the WISHBONE buses instead of just one as shown in the diagrams. $sformatf("wb_txn %0d the wb_txn_type was type illegal".com . rsp_txn).m_id). UVM/OVM Online Methodology Cookbook . // send rsp object back to sequence endtask endclass 49 When the driver receives a WISHBONE€write transaction for example in the run task it calls its wb_write_cycle() task which uses the abstract class handle (m_wb_bus_abs_c) to call the wb_write_cycle() method in the concrete class which in turn calls the wb_write_cycle() method in the BFM.put(rsp_txn). seq_item_port.wb_read_cycle(req_txn.http://uvm.
com/w/index.mentor.com/w/index.mentor.mentor.com/w/index.com/w/index.mentor.com/w/index.php?oldid=3962 €Contributors: Mentor Config/Params Package €Source: http://uvm.php?oldid=3970 €Contributors: Mentor Connect/Virtual Interface €Source: http://uvm.com/w/index.mentor.php?oldid=3721 €Contributors: Mentor VirtInterfaceConfigOVMContainer €Source: http://uvm.http://uvm.php?oldid=3703 €Contributors: Mentor Connect/AbstractConcrete €Source: http://uvm.php?oldid=3701 €Contributors: Mentor Config/Overview €Source: http://uvm.mentor.com/w/index.php?oldid=3696 €Contributors: Mentor Config/Container €Source: http://uvm.php?oldid=3723 €Contributors: Mentor ProtocolModules €Source: http://uvm.php?oldid=3683 €Contributors: Mentor ParameterizedTests €Source: http://uvm.com/w/index.mentor.php?oldid=3704 €Contributors: Mentor VirtInterfacePackage €Source: http://uvm.com/w/index.Copyright (c) 2011 Mentor Graphics Corporation .php?oldid=3695 €Contributors: Mentor DualTop €Source: http://uvm.com .mentor.php?oldid=3681 €Contributors: Mentor Connect/SV Techniques €Source: http://uvm.com/w/index.com/w/index.mentor.com/w/index.mentor.php?oldid=3705 €Contributors: Mentor UVM/OVM Online Methodology Cookbook .php?oldid=3685 €Contributors: Mentor Connect/AbstractConcreteOVMContainer €Source: http://uvm.mentor.php?oldid=3694 €Contributors: Mentor VirtInterfaceFunctionCallChain €Source: http://uvm.mentor.Article Sources and Contributors 50 Article Sources and Contributors Connect/Dut Interface €Source: http://uvm.com/w/index.com/w/index.com/w/index.com/w/index.com/w/index.php?oldid=3968 €Contributors: Mentor SVCreationOrder €Source: http://uvm.mentor.mentor.mentor.php?oldid=3973 €Contributors: Mentor VirtInterfaceConfigPkg €Source: http://uvm.mentor.php?oldid=3738 €Contributors: Mentor BusFunctionalModels €Source: http://uvm.mentor.mentor.
1.php?title=File:SV_Creation_Order_diag_1.png €License: unknown €Contributors: Mentor Image:Works With UVM 1.php?title=File:DUT-TB_diag_OVM_5.mentor.jpg €License: unknown €Contributors: Mentor Image:Test params pkg diag 1.jpg €License: unknown €Contributors: Mentor UVM/OVM Online Methodology Cookbook .php?title=File:Two_kingdoms_diag_7.php?title=File:DUT-TB_diag_6.jpg €Source: http://uvm.jpg €Source: http://uvm.mentor.com/w/index.jpg €Source: http://uvm.com/w/index.1.com/w/index.jpg €License: unknown €Contributors: Mentor Image:Protocol modules diag 2.mentor.mentor.php?title=File:DUT-TB_diag_OVM_5.com/w/index.1.mentor.jpg €Source: http://uvm. Licenses and Contributors 51 Image Sources.0.0.jpg €Source: http://uvm.com/w/index.mentor.jpg €Source: http://uvm.php?title=File:Works_With_UVM_1.mentor.jpg €License: unknown €Contributors: Mentor Image:DUT-TB_diag_OVM_5.http://uvm.Copyright (c) 2011 Mentor Graphics Corporation .jpg €License: unknown €Contributors: Mentor Image:SV Creation Order diag 1.jpg €License: unknown €Contributors: Mentor Image:DUT-TB diag 6.mentor.jpg €Source: http://uvm.Image Sources. Licenses and Contributors Image:Works With OVM 2.jpg €License: unknown €Contributors: Mentor Image:Two kingdoms diag 7.mentor.mentor.png €License: unknown €Contributors: Mentor Image:DUT-TB diag OVM_5.com/w/index.png €Source: http://uvm.mentor.png €Source: http://uvm.1.com/w/index.php?title=File:Protocol_modules_diag_2.com .php?title=File:Works_With_OVM_2.jpg €Source: http://uvm.com/w/index.php?title=File:Test_params_pkg_diag_1.com/w/index.com/w/index.php?title=File:Virtual_interface_diag_1.jpg €License: unknown €Contributors: Mentor Image:Virtual interface diag 1.
http://uvm.Copyright (c) 2011 Mentor Graphics Corporation .com .mentor.License 52 License Copyright 2010 Mentor Graphics Corp UVM/OVM Online Methodology Cookbook .
the recipient agrees to make every reasonable effort to prevent unauthorized use of this information. In accepting this document. 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. MGC 06-10 TECH9050-w .Mentor Graphics UVM/OVM Documentation / Methodology Cookbook For the latest product information.c o m © 2010 Mentor Graphics Corporation. call us or visit: w w w. all rights reserved.m e n t o r. All trademarks mentioned are this document are trademarks of their respective owners. provided that this entire notice appears in all copies.