INTRODUCTION

The OVM Class Library provides the building blocks needed to quickly develop wellconstructed and reusable verification components and test environments in SystemVerilog. OVM library contains: Component classes for building testbench components like generator/driver/monitor etc. Reporting classes for logging, Factory for object substitution. Synchronization classes for managing concurrent process. Policy classes for printing, comparing, recording, packing, and unpacking of ovm_object based classes. TLM Classes for transaction level interface. Sequencer and Sequence classes for generating realistic stimulus. And Macros which can be used for shorthand notation of complex implementation.

OVM TESTBENCH

Ovm components, ovm env and ovm test are the three main building blocks of a testbench in ovm based verification.

Ovm_env
Ovm_env is extended from ovm_componented and does not contain any extra functionality. Ovm_env is used to create and connect the ovm_components like driver, monitors , sequeners etc. An environment class can also be used as sub-environment in another environment. As there is no difference between ovm_env and ovm_component , we will discuss about ovm_component, in the next section.

Verification Components
Ovm verification component classes are derived from ovm_component class which provides features like hierarchy searching, phasing, configuration, reporting, factory and transaction recording. Following are some of the ovm component classes Ovm_agent Ovm_monitor Ovm_scoreboard Ovm_driver Ovm_sequencer NOTE: ovm_env and ovm_test are also extended from ovm_component. A typical ovm verification environment:

An agent typically contains three subcomponents: a driver, sequencer, and monitor. If the agent is active, subtypes should contain all three subcomponents. If the agent is passive, subtypes should contain only the monitor.

About Ovm_component Class:
Ovm_compoenent class is inherited from ovm_report_object which is inherited from ovm_object. As I mentioned previously, ovm_component class provides features like hierarchy searching, phasing, configuration, reporting, factory and transaction recording. We will discuss about phasing concept in this section and rest of the features will be discussed as separate topics.

OVM phases
OVM Components execute their behavior in strictly ordered, pre-defined phases. Each phase is defined by its own virtual method, which derived components can override to incorporate component-specific behavior. By default , these methods do nothing.

--> virtual task run() In this phase . --> virtual function void end_of_elaboration() This phase is used for configuring the components if required. all the required information is gathered. --> virtual function void connect() This phase is used for connecting the ports/exports of the components. --> virtual function void extract() In this phase. --> virtual function void start_of_simulation() This phase is used to print the banners and topology.--> virtual function void build() This phase is used to construct various child components/ports/exports and configures them. Main body of the test is executed where all threads are forked off. --> virtual function void check() .

check the results of the extracted information such as un responded requests in scoreboard. Ovm_test Ovm_test is derived from ovm_component class and there is no extra functionality is added. monitor and driver are implemented similar to environment. Agent. Lets implement environment for the following topology. i. In the above <testcase_string> is the object type of the testcase class. Only build() method is executed in top down manner. The run() method is the only method which is time consuming. --> virtual function void report() This phase is used for reporting the pass/fail status. testcase and top module. .In this phase. The advantage of used ovm_test for defining the user defined test is that the test case selection can be done from command line option +OVM_TESTNAME=<testcase_string> .e after executing parent build() method. read statistics registers etc. User can also select the testcase by passing the testcase name as string to ovm_root::run_test(<testcase_string>) method. so the order in which all components run() method are executed is undefined. child objects build() methods are executed. I will describe the implementation of environment . All other methods are executed in bottom-up manner. The run() method is forked.

agent ag1.1)Extend ovm_env class and define user environment. . ovm_component parent = null). 4)Define the constructor. call the super methods and pass the parent object. 2)Declare the utility macro. function new(string name . This utility macro provides the implementation of create() and get_type_name() methods and all the requirements needed for factory. endfunction: new 5)Define build method. Parent is the object in which environment is instantiated. In the build method. construct the agents. The advantage of create() over new() is that when create() method is called. it will check if there is a factory override and constructs the object of override type. class env extends ovm_env. use create() method. To construct agents. In the constructor.new(name. `ovm_component_utils(env) 3)Declare the objects for agents. super. parent). agent ag2.

this). endfunction 6)Define connect().start_of_simulation(). OVM_LOG). `ovm_component_utils(env) agent ag1. super. ag1 = agent::type_id::create("ag1".check(). ovm_report_info(get_full_name(). OVM_LOG). ag1 = agent::type_id::create("ag1".this). parent). endfunction function void end_of_elaboration(). ovm_report_info(get_full_name().report() methods. ovm_report_info(get_full_name(). function void connect(). ag2 = agent::type_id::create("ag2".this).this)."Connect". endfunction function void build()."End_of_elaboration". endfunction Complete code of environment class: class env extends ovm_env.new(name. ovm_report_info(get_full_name(). endfunction . OVM_LOG).extract(). as we dont have any logic in this example to define. super. endfunction function void connect(). ovm_report_info(get_full_name(). Just print a message from these methods. OVM_LOG).function void build(). agent ag2. ovm_component parent). OVM_LOG)."Build". function new(string name.end_of_elaboration().build()."Build".run(). ag2 = agent::type_id::create("ag2"."Connect".

OVM_LOG). ovm_report_info(get_full_name()."Run".function void start_of_simulation(). OVM_LOG). . OVM_LOG). endtask function void extract(). endfunction task run(). endfunction function void check(). function new (string name="test1"."Start_of_simulation". ovm_report_info(get_full_name(). OVM_LOG)."Check". In the constructor."Report". call the super method and construct the environment object. 2)Declare component ustilits using utility macro."Extract". `ovm_component_utils(test1) 2)Declare environment class handle. 3)Define constructor method. endfunction function void report(). ovm_report_info(get_full_name(). 1)Extend ovm_test and define the test case class test1 extends ovm_test. ovm_report_info(get_full_name(). ovm_component parent=null). env t_env. OVM_LOG). ovm_report_info(get_full_name(). endfunction endclass Now we will implement the testcase.

print().this).this).new (name. `ovm_component_utils(test1) env t_env. #1000. endfunction : new function void end_of_elaboration(). OVM_LOG). global_stop_request(). endfunction : new 4)Define the end_of_elaboration method. OVM_LOG)."End_of_elaboration". endfunction task run (). super. function new (string name="test1". In this method.new (name. ovm_report_info(get_full_name(). t_env = new("t_env". parent). #1000. This print() method will print the topology of the test."End_of_elaboration".super. t_env = new("t_env". endtask : run endclass . function void end_of_elaboration(). task run (). call the print() method. parent). global_stop_request(). ovm_component parent=null). endfunction 4)Define the run method and call the global_stop_request() method. ovm_report_info(get_full_name(). print(). endtask : run Testcase source code: class test1 extends ovm_test.

t_env.tar Browse the code in ovm_phases. run_test() method must be called from initial block.ag2.t_env..t_env. endmodule Download the source code ovm_phases.ag2.t_env. Run_test() mthod Phases all components through all registered phases. initial run_test().t_env.drv [ovm_test_top.ag1.t_env.ag1 [ovm_test_top.drv [ovm_test_top.t_env.t_env.t_env.ag1.t_env.t_env.ag2 [ovm_test_top.ag2.t_env.ag1] Build ovm_test_top.ag1.t_env.t_env [ovm_test_top.t_env.ag2] Connect ovm_test_top.ag1.t_env.ag1] Connect ovm_test_top.ag1.mon [ovm_test_top.ag1.drv] Build ovm_test_top.drv [ovm_test_top.mon] Connect ovm_test_top.ag2.t_env.ag2.t_env.t_env. ovm_test_top.t_env] Build ovm_test_top.drv] End_of_elaboration .t_env] Connect ovm_test_top.ag1.ag1.t_env.drv [ovm_test_top.mon] Build ovm_test_top. module top.mon [ovm_test_top.mon [ovm_test_top.t_env.ag2.drv] Connect ovm_test_top.t_env.mon] Build ovm_test_top.ag2 [ovm_test_top.t_env.ag1.ag2.mon [ovm_test_top.Top Module: To start the testbench.t_env [ovm_test_top.ag1.drv] Build ovm_test_top.t_env.ag2] Build ovm_test_top.ag1 [ovm_test_top.t_env.drv] Connect ovm_test_top.ag2.mon] Connect ovm_test_top.tar Command to run the simulation your_tool_simulation_command +path_to_ovm_pkg -f filelist +OVM_TESTNAME=test1 Log file: [RNTST] Running test test1.t_env.drv [ovm_test_top.t_env..

ovm_test_top.ag1[ovm_test_top.mon[ovm_test_top.ag1]Start_of_simulation ovm_test_top.mon] End_of_elaboration ovm_test_top.drv] End_of_elaboration ovm_test_top.t_env] Build ovm_test_top.ag1.ag2] End_of_elaboration ovm_test_top. Observe the above log report: 1)Build method was called in top-down fashion.t_env.t_env. Look at the following part of message.ag2.ag2.ag1.t_env..t_env.t_env.t_env.t_env.mon [ovm_test_top.t_env.ag1.t_env.t_env.ag2.mon] Build .mon]Start_of_simulation ovm_test_top.t_env.t_env..t_env.ag1.t_env.t_env.drv[ovm_test_top.ag2.ag1.drv]Start_of_simulation ovm_test_top.ag2.ag2.mon [ovm_test_top. ovm_test_top. .t_env.mon [ovm_test_top..t_env.t_env.ag1 [ovm_test_top.mon] End_of_elaboration ovm_test_top.drv [ovm_test_top.t_env [ovm_test_top.ag2.ag2 [ovm_test_top.t_env [ovm_test_top.t_env. .mon]Start_of_simulatio .ag1.ag1.ag1.t_env.ag1] Build ovm_test_top.t_env.drv] Build ovm_test_top.ag1.t_env.ag1] End_of_elaboration ovm_test_top.ag1.drv [ovm_test_top.drv[ovm_test_top.drv]Start_of_simulation ovm_test_top.t_env.ag2. .t_env..ag1 [ovm_test_top.t_env.t_env.t_env] End_of_elaboration ovm_test_top [ovm_test_top] End_of_elaboration ---------------------------------------------------------------------Name Type Size Value ---------------------------------------------------------------------ovm_test_top test1 ovm_test_top@2 t_env env t_env@4 ag1 agent ag1@6 drv driver drv@12 rsp_port ovm_analysis_port rsp_port@16 sqr_pull_port ovm_seq_item_pull_+ sqr_pull_port@14 mon monitor mon@10 ag2 agent ag2@8 drv driver drv@20 rsp_port ovm_analysis_port rsp_port@24 sqr_pull_port ovm_seq_item_pull_+ sqr_pull_port@22 mon monitor mon@18 ovm_test_top.mon[ovm_test_top.

t_env.ag2.t_env.ag2 [ovm_test_top.drv [ovm_test_top.ag1] Connect ovm_test_top.ag1 [ovm_test_top.ag2] Connect ovm_test_top.ag1.mon] Connect ovm_test_top.t_env.ag2.t_env.drv] Connect ovm_test_top.ag2.ag2.t_env] Connect 3)Following part of log file shows the testcase topology.t_env [ovm_test_top.t_env.mon [ovm_test_top.drv [ovm_test_top.ag2.t_env.drv [ovm_test_top.ovm_test_top.t_env.t_env.ag1.ag1.ag2.ag2] Build ovm_test_top.t_env.t_env.t_env. Through this interface.mon] Connect ovm_test_top. OVM REPORTING The ovm_report_object provides an interface to the OVM reporting facility.ag2 [ovm_test_top.ag1.drv] Build ovm_test_top.mon] Build 2)Connect method was called in bottopm up fashion.ag2. ovm_test_top. Look at the below part of log file.t_env.t_env.t_env.t_env.t_env.drv] Connect ovm_test_top.ag2.mon [ovm_test_top.t_env.t_env.mon [ovm_test_top. components issue the various messages with different severity levels that occur during .

indicating its relative importance.int line=0) virtual function void ovm_report_warning (string id. id.string message.string message.simulation.The message text verbosity -. Users can configure what actions are taken and what file(s) are output for individual messages from a particular component or for all messages from all components in the environment.string message.Do nothing . If the verbosity level of a report is greater than the configured maximum verbosity level of its report object.int verbosity=OVM_NONE. Reporting Methods: Following are the primary reporting methods in the OVM. Actions: These methods associate the specified action or actions with reports of the givenseverity.string filename="". subject to the configured action and file descriptor settings. If this number is less than or equal to the effective verbosity level.int verbosity=OVM_MEDIUM.the verbosity of the message.int line=0) virtual function void ovm_report_fatal (string id. string filename="".a unique id to form a group of messages. Following are the actions defined: OVM_NO_ACTION -. string filename="".string message. then the report is issued.int line=0) Arguments description: id -. virtual function void ovm_report_info (string id. it is ignored. verbosity level.If required to print filename and line number from where the message is issued. or severity-id pair. message -.int verbosity=OVM_MEDIUM. A report consists of an id string. use macros.string filename="".int verbosity=OVM_LOW.int line=0) virtual function void ovm_report_error (string id. severity. `__FILE__ and `__LINE__. filename/line -. and the textual message itself.

ovm_action action) .Callback the hook method .string id.ovm_action action) function void set_report_severity_id_action (ovm_severity severity.OVM_DISPLAY -. user can set the verbosity levels and set actions. function void set_report_verbosity_level (int verbosity_level) function void set_report_severity_action (ovm_severity severity.Display report to standard output OVM_LOG -. Configuration: Using these methods.Write to a file OVM_COUNT -.ovm_action action) function void set_report_id_action (string id.Count up to a max_quit_count value before exiting OVM_EXIT -.Terminates simulation immediately OVM_CALL_HOOK -.

endfunction task run().`__FILE__. messages from rpting::run() method are of different verbosity level. parent).svh" import ovm_pkg::*.OVM_NONE. `include "ovm. . ovm_report_info(get_full_name().OVM_NONE ". 3 objects of rpting are created and different verbosity levels are set using set_report_verbosity_level() method. super.new(name. "Info Message : Verbo lvl .Example Lets see an example: In the following example.`__LINE__). `ovm_component_utils(rpting) function new(string name. class rpting extends ovm_threaded_component. In the top module.ovm_component parent).

150 ". rpt1. ovm_report_info(get_full_name().set_report_verbosity_level(OVM_MEDIUM). initial begin rpt1 = new("rpt1".OVM_LOW ".150).null). rpting rpt1. rpt2 = new("rpt2". "Error Message from rpting \n\n". ovm_report_info(get_full_name(). rpting rpt2. endtask endclass module top.OVM_LOW). "Info Message : Verbo lvl .set_report_verbosity_level(OVM_LOW). end endmodule Download the source code ovm_reporting.OVM_LOW).null).tar Command to run the simulation . rpting rpt3. ovm_report_error(get_full_name(). "Info Message : Verbo lvl .OVM_MEDIUM". rpt2.tar Browse the code in ovm_reporting. "Warning Messgae from rpting".null). run_test(). rpt3 = new("rpt3". rpt3.OVM_MEDIUM).OVM_LOG).set_report_verbosity_level(OVM_NONE). ovm_report_warning(get_full_name(). "Info Message : Verbo lvl .ovm_report_info(get_full_name().

In this section. In ovm. Generally transactions are extended from ovm_transaction if randomization is not done in sequence and transactions are extended from ovm_sequence_item if the randomization is done in sequence. rand bit [7:0] length. we will see ovm_transaction only. rand bit [7:0] data[]. ovm_sequence_item will be addressed in another section.your_tool_simulation_command +path_to_ovm_pkg ovm_log_example.OVM_NONE OVM_INFO @0:rpt1[rpt1] Info Message : Verbo lvl .OVM_NONE OVM_ERROR @ 9200 [TIMOUT] Watchdog timeout of '23f0' expired.OVM_MEDIUM OVM_WARNIN@0:rpt[rpt1] Warning Messgae from rpting OVM_ERROR @0:rpt1[rpt1] Error Message from rpting OVM_INFOreporting. rand byte fcs.sv(13)@0:rpt3[rpt3]Info Message:Verbo lvl . The packets. OVM TRANSACTION A transaction is data item which is eventually or directly processed by the DUT. pixels are data items. endclass Core Utilities: .OVM_LOW OVM_INFO @0:rpt1[rpt1] Info Message : Verbo lvl .sv(13)@0:rpt1[rpt1]Info Message:Verbo lvl .150 OVM_INFO @0:rpt1[rpt1] Info Message : Verbo lvl . rand bit [7:0] da.OVM_NONE OVM_INFO@ 0:rpt2[rpt2] Info Message : Verbo lvl .OVM_LOW OVM_WARNING@0:rpt2[rpt2] Warning Messgae from rpting OVM_ERROR@0:rpt2[rpt2] Error Message from rpting OVM_INFOreporting.sv Log file: OVM_INFO reporting. rand bit [7:0] sa. instructions.sv(13)@0:rpt2[rpt2]Info Message:Verbo lvl . Example of a transaction: class Packet extends ovm_transaction. transactions are extended from ovm_transactions class or ovm_sequence_item class.

does not use hook methods concepts. FIG: OVM OBJECT UTILITIES User Defined Implementations: User should define these methods in the transaction using do_<method_name> and call them using <method_name>. transaction id and timings of the transaction. . The methods used to model. packing and unpacking are already defined in ovm_object. Ovm_transaction adds more features line transaction recording . comparing. copying. transform or operate on transactions like print. Following table shows calling methods and user-defined hook do_<method_name> methods. Clone and create methods. cloning. recording.ovm_transaction class is extended from ovm_object.

rand bit [7:0] sa. Example of field automation macros: class Packet extends ovm_transaction. rand bit [7:0] da. OVM_ALL_ON|OVM_NOPACK) `ovm_field_int(sa. first declare all the data fields. OVM_ALL_ON|OVM_NOPACK) `ovm_field_array_int(data. rand byte fcs. all the above defines methods can be defined automatically. rand bit [7:0] data[]. OVM_ALL_ON|OVM_NOPACK) `ovm_field_int(fcs. `ovm_object_utils_begin(Packet) `ovm_field_int(da. rand bit [7:0] length.Shorthand Macros: Using the field automation concept of ovm. then place the field automation macros between the `ovm_object_utils_begin and `ovm_object_utils_end macros. OVM_ALL_ON|OVM_NOPACK) . To use these field automation macros. OVM_ALL_ON|OVM_NOPACK) `ovm_field_int(length.

ARG is the instance name of the variable and FLAG is used to control the field usage in core . Following table shows all the field automation macros. ovm defined corresponding field automation macros. Each `ovm_field_* macro has at least two arguments: ARG and FLAG. For most of the data types in systemverilog.`ovm_object_utils_end endclass.

svh" import ovm_pkg::*. Packing and unpacking methods are done in do_pack() amd do_unpack() method. class Packet extends ovm_transaction. All these flags can be ored. Lets see a example: In the following example. all the utility methods are defined using field automation macros except Packing and unpacking methods. `include "ovm. Example of Flags: `ovm_field_int(da. Using NO_* flags. FLAG is set to OVM_ALL_ON.utilities operation. Following table shows ovm field automation flags: By default. can turn of particular field usage in a paerticuler method. OVM_ALL_ON|OVM_NOPACK) The above macro will use the field "da" in all utilities methods except Packing and unpacking methods. . //Define the enumerated types for packet types typedef enum { GOOD_FCS. NO_* flags takes precedency over other flags. BAD_FCS } fcs_kind_t.

size inside { [1 : 6]}. } constraint solve_size_length { solve data.$bits(sa)).do_pack(packer). byte fcs. endfunction : cal_fcs `ovm_object_utils_begin(Packet) `ovm_field_int(da. endfunction : post_randomize ///// method to calculate the fcs ///// virtual function byte cal_fcs.size before length. packer. OVM_ALL_ON|OVM_NOPACK) `ovm_field_int(sa. fcs = cal_fcs(). result = fcs ^ result.rand fcs_kind_t rand rand rand rand rand fcs_kind. else fcs = 8'b1. packer. for (i = 0. bit [7:0] sa. super. . OVM_ALL_ON|OVM_NOPACK) `ovm_field_int(length. super.size. constraint payload_size_c { data. bit [7:0] data[]. result = result ^ length.$bits(da)). return result.i< data. result = result ^ da. integer i. bit [7:0] da.pack_field_int(length. OVM_ALL_ON|OVM_NOPACK) `ovm_object_utils_end function void do_pack(ovm_packer packer). packer. OVM_ALL_ON|OVM_NOPACK) `ovm_field_array_int(data.size.i++) result = result ^ data[i].pack_field_int(da. result = result ^ sa.} constraint length_c { length == data. endfunction : new function void post_randomize(). OVM_ALL_ON|OVM_NOPACK) `ovm_field_int(fcs.$bits(length)). result = 0. byte result . } function new(string name = "").new(name).pack_field_int(sa. if(fcs_kind == GOOD_FCS) fcs = 8'b0. bit [7:0] length.

unpack_field_int($bits(da)). length = packer. if(pkt2. pkt1.use_metadata = 1. pkt2. void'(pkt1.print().unpack_bytes(pkdbytes).pkdbytes. else $display(" *** Something went wrong in Packing or Unpacking or compare *** \n \n").compare(pkt1)) $display(" Packing. data = new[length].do_pack(packer)."). sa = packer. endfunction : do_unpack endclass : Packet ///////////////////////////////////////////////////////// //// Test to check the packet implementation //// ///////////////////////////////////////////////////////// module test.$bits(fcs)).8). data.unpack_field_int($bits(length)). Packet pkt2 = new("pkt2"). packer.unpack_field_int($bits(sa)). fcs = packer. endmodule . ovm_default_packer. endfunction : do_pack function void do_unpack(ovm_packer packer). end else $display(" *** Randomization Failed ***"). da = packer.foreach(data[i]) packer. byte unsigned pkdbytes[]. $display("Size of pkd bits %d".unpack_field_int(8). super.pack_field_int(fcs. int sz.delete().randomize) begin $display(" Randomization Sucessesfull.size()). pkt2.unpack_field_int($bits(fcs)).pack_bytes(pkdbytes)). foreach(data[i]) data[i] = packer.print().pack_field_int(data[i].Unpacking and compare worked"). initial repeat(10) if(pkt1. Packet pkt1 = new("pkt1").

tar Command to run the simulation your_tool_simulation_command +path_to_ovm_pkg -packet. ---------------------------------------------------------------------Name Type Size Value ---------------------------------------------------------------------pkt1 Packet pkt1@3 da integral 8 'h1d sa integral 8 'h26 length integral 8 'h5 data da(integral) 5 [0] integral 8 'hb1 [1] integral 8 'h3f [2] integral 8 'h9e [3] integral 8 'h38 [4] integral 8 'h8d fcs integral 8 'h9b ---------------------------------------------------------------------Size of pkd bits 9 ---------------------------------------------------------------------Name Type Size Value ---------------------------------------------------------------------pkt2 Packet pkt2@5 da integral 8 'h1d sa integral 8 'h26 length integral 8 'h5 data da(integral) 5 [0] integral 8 'hb1 [1] integral 8 'h3f [2] integral 8 'h9e [3] integral 8 'h38 [4] integral 8 'h8d fcs integral 8 'h9b ---------------------------------------------------------------------Packing.Download the source code ovm_transaction.sv Log report: Randomization Sucessesfull.Unpacking and compare worked .tar Browse the code in ovm_transaction.

This could not be easy if there are many driver objects. Using the ovm fatroy.100mps and 1G. you have a driver component. it is very easy to solve the above two requirements. how will you replace the base driver component which is deep in the hierarchy of your environment ? Using hierarchical path. You would like the extend the driver component for error injection scenario. How to add one more driver to the current drivers list of drivers so that from the testcase you could configure the environment to work for 10G. For example: In your environment. you have different drivers to support different interfaces for 10mbps. Now you want to reuse the same environment for 10G verification.OVM FACTORY The factory pattern is an well known object-oriented design pattern.your current environment can only select 10mmps/100mps/1G drivers using configuration settings. . as a driver components . you could replace the driver object with the extended driver. One more example: In your Ethernet verification environment. objects are constructed dynamically based on the specification type of the object. Registration: While defining a class . User can alter the behavior of the pre-build code without modifying the code. They are based on ovm component/object type or ovm compoenent/object name. Only classs extended from ovm_object and ovm_component are supported for this. while building the components. Using this method. To do this job easier. After defining the extended driver class with error injection. ovm has predefined macros. 1) Registration 2) Construction 3) Overriding The factory makes it is possible to override the type of ovm component /object or instance of a ovm component/object in2 ways. its type has to be registered with the ovm factory. There are three basic steps to be followed for using ovm factory. The factory method design pattern defining a separate method for creating the objects. Inside somewhere deep in the hierarchy. From the testcase. Then you should also take care of its connections with the other components of testbenchs like scoreboard etc. user from environment or testcase can replace any object which is at any hierarchy level with the user defined object. `ovm_component_utils(class_type_name) `ovm_component_param_utils(class_type_name #(params)) `ovm_object_utils(class_type_name) `ovm_object_param_utils(class_type_name #(params)) . whose subclasses can then override to specify the derived type of object that will be created.

This function constructs the appropriate object based on the overrides and constructs the object and returns it. For ovm_object based classes. EXAMPLE: class_type object_name. The context argument. string context = " ") The Create() function returns an instance of the component type. Syntax : static function T create(string name. EXAMPLE: Example of above macros class packet extends ovm_object. T. object_name = class_type::type_id::creat("object_name". The new instance will have the given leaf name and parent. doesnt need the parent handle as second argument. supersedes the parents context. int mode=0) extends ovm_component. subject to any factory overrides based on the context provided by the parents full name. it is not required for type-based overriding. static method create() should be used. ovm_component parent. int mode=0) extends ovm_object. `ovm_component_param_utils(driver#(T. . `ovm_object_utils(packet) endclass class packet #(type T=int. So while constructing the ovm based components or ovm based objects . represented by this proxy.this). if supplied. do not use new() constructor. `ovm_component_utils(driver) endclass class monitor #(type T=int. Registration is required for name-based overriding .For ovm_*_param_utils are used for parameterized classes and other two macros for nonparameterized class. `ovm_object_param_utils(packet #(T.mode)) endclass Construction: To construct a ovm based component or ovm based objects.mode)) endclass class driver extends ovm_component.

request to create an object of original_type_name can be overriden with override_type_name. request to create an object of original_type can be overriden with override_type. function void set_inst_override_by_name (string original_type_name. print() method. prints the state of the ovm_factory. ovm_object_wrapper override_type. and type overrides. bit replace = 1) Using the above method. All the instances of objects with name "Original_type_name" will be overriden with objects of name "override_type_name" using set_inst_override_by_name() method. function void set_type_override_by_name (string original_type_name. If argument "replace" is 1. previous overrides will remain. registered types. When multiple overrides are done . ovm_object_wrapper override_type. string full_inst_path ) The above method is used to override the object instances of "original_type" with "override_type" . function void set_type_override_by_type (ovm_object_wrapper original_type. then previous overrides will be replaced otherwise. string override_type_name.Overriding: If required. . we can control whether to override the previous override or not. User can override based of name string or class-type. "override_type" is extended from"original_type". then using the argument "replace" . string full_inst_path ) Original_type_name and override_type_name are the class names which are registered in the factory. There are 4 methods defined for overriding: function void set_inst_override_by_type (ovm_object_wrapper original_type. user could override the registered classes or objects. bit replace = 1 ) Using the above method. instance overrides. string override_type_name.

. we will define driver_2 class and by extending monitor class. In this example. This example is based on the environment build in topic OVM TESTBENCH . monitor and driver are constructed using create() method. By extending driver class . 3)In this example. there is one driver class and one monitor class. we will define monitor_2 class. Topology of this test environment is shown below.this). There are no over rides in this test case. you can see the macro `ovm_component_utils(type_name) 2) Construction In file agant. drv = driver::type_id::create("drv".this).sv file. In this testcase . Refer to that section for more information about this example. a one testcase is already developed in topic OVM_TESTBENCH. Lets look at the 3 steps which I discussed above using the example defined in OVM TESTBENCH 1) Registration In all the class. mon = monitor::type_id::create("mon".Now we will see a complete example.

OVM_LOG). factory. global_stop_request(). `ovm_component_utils(monitor_2) function new(string name. `ovm_component_utils(test_factory) env t_env.set_type_override_by_type(driver::get_type().print_all_overrides().new(name. To know about the overrides which are done.driver_2::get_type()."*"). endfunction endclass class monitor_2 extends monitor. endfunction : new function void end_of_elaboration(). class driver_2 extends driver."*"). we will override driver with driver_2 and Using set_type_override_by_name. factory. super.new(name. ovm_component parent). we will override monitor with monitor_2. parent).set_type_override_by_name("monitor". parent). function new (string name="test1". Using set_type_override_by_type.new (name. `ovm_component_utils(driver_2) function new(string name. factory. super. super. endfunction endclass class test_factory extends ovm_test. t_env = new("t_env". #1000. endtask : run endclass . ovm_report_info(get_full_name(). ovm_component parent=null)."monitor_2".this). print(). endfunction : end_of_elaboration task run (). call print_all_overrides() method of factory class. parent). ovm_component parent)."End_of_elaboration".From the testcase .

Command to run this example with test1 is your_tool_simulation_command +incdir+path_to_ovm -f filelist +OVM_TESTNAME=test1 .tar Command to simulate Command to run the example with the testcase which is defined above: Your_tool_simulation_command +incdir+path_to_ovm -f filelist +OVM_TESTNAME=test_factory Method factory.with testcase test1 which does note have overrides.we can see overridden driver and monitor.print_all_overrides() displayed all the overrides as shown below in the log file. #### Factory Configuration (*) No instance overrides are registered with this factory Type Overrides: Requested Type -------------driver monitor Override Type ------------driver_2 monitor_2 In the below text printed by print_topology() method .Download the example: ovm_factory. ---------------------------------------------------------------------Name Type Size Value ---------------------------------------------------------------------ovm_test_top test_factory ovm_test_top@2 t_env env t_env@4 ag1 agent ag1@6 drv driver_2 drv@12 rsp_port ovm_analysis_port rsp_port@16 sqr_pull_port ovm_seq_item_pull_+ sqr_pull_port@14 mon monitor_2 mon@10 ag2 agent ag2@8 drv driver_2 drv@20 rsp_port ovm_analysis_port rsp_port@24 sqr_pull_port ovm_seq_item_pull_+ sqr_pull_port@22 mon monitor_2 mon@18 ---------------------------------------------------------------------- In the below text printed by print_topology() method .tar Browse the code in ovm_factory.

For example.---------------------------------------------------------------------Name Type Size Value ---------------------------------------------------------------------ovm_test_top test1 ovm_test_top@2 t_env env t_env@4 ag1 agent ag1@6 drv driver drv@12 rsp_port ovm_analysis_port rsp_port@16 sqr_pull_port ovm_seq_item_pull_+ sqr_pull_port@14 mon monitor mon@10 ag2 agent ag2@8 drv driver drv@20 rsp_port ovm_analysis_port rsp_port@24 sqr_pull_port ovm_seq_item_pull_+ sqr_pull_port@22 mon monitor mon@18 ---------------------------------------------------------------------- OVM SEQUENCE 1 Introduction A sequence is a series of transaction. then to excursing a meaningful operation like "adding 2 variables" which requires a series of transaction "PUSH_A PUSH_B ADD POP_C " will take longer time.MUL. extended. and combined sequentially and hierarchically in various ways.Sequencer 4. If the instructions are generated randomly. A complete sequence generation requires following 4 classes.Sequence 3. sequences can be reused.PUSH_B. randomized.SUB. Sequences can be combined sequentially and hierarchically.DIV and POP_C are the instructions.ADD.Driver Ovm_sequence_item : User has to define a transaction by extending ovm_sequence_item. Easy to control the generation of transaction. User can define the complex stimulus. 1. Advantages of ovm sequences : Sequences can be reused. ovm_sequence_item class . it would be easy to exercise the DUT. lets say PUSH_A. Stimulus generation is independent of testbench. for a processor.Sequence item. 2. By defining these series of "PUSH_A PUSH_B ADD POP_C ".

class ovm_driver #( type REQ = ovm_sequence_item. There are two types of sequencers : ovm_sequencer and ovm_push_sequencer class ovm_sequencer #( type REQ = ovm_sequence_item. type RSP = REQ ) Ovm_sequencer: Ovm_sequencer is responsible for the coordination between sequence and driver.provides the basic functionality for objects. The ovm_sequence class provides the interfaces necessary in order to create streams of sequence items and/or other sequences. both sequence items and sequences. type RSP = REQ . When multiple sequences are running in parallel. type RSP = REQ ) class ovm_push_sequencer #( type REQ = ovm_sequence_item. There are two types of drivers: ovm_driver and ovm_push_driver. These transactions can be directed. then sequencer is responsible for arbitrating between the parallel sequences. The response transaction from the driver is optional. Sequencer sends the transaction to driver and gets the response from the driver. For more information about ovm_sequence_item Refer to link OVM_TRANSACTION Ovm_sequence: User should extend ovm_sequence class and define the construction of sequence of transactions. virtual class ovm_sequence #( type REQ = ovm_sequence_item. constrained randomized or fully randomized. to operate in the sequence mechanism. type RSP = REQ ) Ovm driver: User should extend ovm_driver class to define driver component. ovm driver is a component that initiate requests for new transactions and drives it to lower level components.

If user specifies only REQ type. in push mode ovm_push_sequencer is connectd to ovm_push_driver. There are multiple methods called during this operation. REQ and RSP types by default are ovm_sequence_type types. If a transaction is created using "create()" . Ovm_sequencer and ovm_driver are parameterized components with request and response transaction types. Sequence And Driver Communication: The above image shows how a transaction from a sequence is sent to driver and the response from the driver is sent to sequencer. User can specify REQ and RSP of different transaction types. type RSP = REQ ) In pull mode . First when the body() method is called 1) A transaction is created using "create()" method. ovm_sequencer is connected to ovm_driver . then RSP will be REQ type.) class ovm_push_driver #( type REQ = ovm_sequence_item.

6) The transaction which is sent from sequence . when "seq_item_port. the response transaction from driver is taken by sequence and processes it. Using get_responce(res). If more than one sequence is getting executed by sequencer. then by calling "seq_item_port.get_next_item()" is called. again the steps 1 to 7 are repeated five times. 5) After calling the send_request() method. in the driver this transaction is available as "seq_item_port. then the sequencer un blocks wait_for_grant() method. wait_for_grant() method is called. send the transaction to the driver. "wait_for_item_done()" method is called. Then driver can drive this transaction to bus or lower level. then it can be overridden if required using ovm factory.get_next_item(req)" method argument. This method is blocking method. Then using the send_request() method. 4) After the wait_for_grant() un blocks. 3) In the run task of the driver. then based on arbitration rules. 7) Once the driver operations are completed. un blocks the wait_for_grant() method. This is a blocking method and execution gets blocks at this method call. or its properties can be filled directly. After this step.put(rsp)". wait_for_item_done() method of sequence gest unblocked. then transaction can be randomized. .method. 2) After a transaction is created.

ADD.ADD.POP_C} inst_t.MUL.new(name).PUSH_B. OVM_ALL_ON) `ovm_object_utils_end function new (string name = "instruction"). class instruction extends ovm_sequence_item. `ovm_object_utils_begin(instruction) `ovm_field_enum(inst_t. typedef enum {PUSH_A.POP_C} inst_t. Sequence Item 1) Extend ovm_sequence_item and define instruction class.inst.6.7 can be skipped and item_done() method from driver should be called as shown in above image.SUB. typedef enum {PUSH_A.PUSH_B. . then steps 5. 2) Define the instruction as enumerated types and declare a variable of instruction enumerated type. rand inst_t inst.SUB.DIV and POP_C. Simple Example Lest write an example: This is a simple example of processor instruction. 3) Define operational method using ovm_field_* macros. super. function new (string name = "instruction"). endfunction Sequence item code: class instruction extends ovm_sequence_item.ADD. `ovm_object_utils_begin(instruction) `ovm_field_enum(inst_t.DIV.SUB.DIV.MUL.inst. rand inst_t inst. Various instructions which are supported by the processor are PUSH_A.PUSH_B.If a response from driver is not required. OVM_ALL_ON) `ovm_object_utils_end 4) Define the constructor.MUL.

wait_for_item_done(). 2) Define the constructor. class operation_addition extends ovm_sequence #(instruction). req = instruction::type_id::create("req"). instruction_sequencer) 4) In the body() method. For construction of a transaction. super. we will use the create() method.new(name). }). send_request(req). Using the `ovm_sequence_utils macro. `ovm_sequence_utils(operation_addition. . register the "operation_addition" sequence with "instruction_sequencer" sequencer. Not using in this example. assert(req. virtual task body(). ADD and POP_C. Then send the transaction to driver using send_request() method. first call wait_for_grant(). endfunction endclass Sequence We will define a operation addition using ovm_sequence.super. then construct a transaction and set the instruction enum to PUSH_A .randomize() with { inst == instruction::PUSH_A. This macro adds the sequence to the sequencer list. //get_response(res). wait_for_grant(). endfunction 3) Lets name the sequencer which we will develop is "instruction_sequencer". Set REQ parameter to "instruction" type.new(name). req = instruction::type_id::create("req"). Repeat the above steps for other instructions PUSH_B. 1) Define a sequence by extending ovm_sequence. Then call the wait_for_item_done() method. The instruction sequence should be "PUSH A PUSH B ADD POP C". This macro will also register the sequence for factory overrides. This is optional. function new(string name="operation_addition").

function new(string name="operation_addition"). Not using in this example. wait_for_grant(). req.inst = instruction::PUSH_B.inst = instruction::POP_C.wait_for_grant(). //get_response(res). req = instruction::type_id::create("req"). endtask Sequence code class operation_addition extends ovm_sequence #(instruction). endfunction `ovm_sequence_utils(operation_addition.inst = instruction::ADD. //get_response(res). send_request(req). wait_for_grant().inst = instruction::PUSH_B. //get_response(res). req. super. instruction_sequencer) virtual task body(). wait_for_item_done(). req. wait_for_grant(). This is optional. req. req = instruction::type_id::create("req").new(name). instruction req.randomize() with { inst == instruction::PUSH_A. send_request(req). send_request(req). req = instruction::type_id::create("req"). assert(req. wait_for_item_done(). . wait_for_item_done(). wait_for_grant(). //get_response(res). wait_for_item_done(). send_request(req). req = instruction::type_id::create("req"). }).

1) Define instruction_sequencer by extending ovm_sequencer. req. place the macro `ovm_update_sequence_lib_and_item(). `ovm_update_sequence_lib_and_item(instruction) endfunction 3) Place the ovm_sequencer_utils macro. wait_for_item_done(). automatically a user defined sequence will be started. req. //get_response(res). Ovm sequencer has seq_item_export and res_export tlm ports for connecting to ovm driver. class instruction_sequencer extends ovm_sequencer #(instruction). req = instruction::type_id::create("req"). send_request(req). ovm_component parent). wait_for_grant(). //get_response(res). req = instruction::type_id::create("req"). Using "start_default_sequence()" method. endtask endclass Sequencer: Ovm_sequence has a property called default_sequence. then a random transaction are generated. Using set_config_string.new(name. We will discuss about the predefined sequences in next section. super. user can override the default sequence to any user defined sequence. Default sequence is a sequence which will be started automatically.inst = instruction::POP_C. wait_for_item_done().send_request(req).inst = instruction::ADD. function new (string name. wait_for_grant(). Inside the constructor. //get_response(res). wait_for_item_done(). parent). so that when a sequencer is started. This macro registers the sequencer for factory overrides. . If over rides are not done with user defined sequence. "default_sequence" can also be started. This macro creates 3 predefined sequences. 2) Define the constructor. send_request(req).

1) Seq_item_port: To get a item from sequencer.`ovm_sequencer_utils(instruction_sequencer) Sequencer Code. Driver can also send response back using this port. function new (string name. `ovm_update_sequence_lib_and_item(instruction) endfunction `ovm_sequencer_utils(instruction_sequencer) endclass Driver: ovm_driver is a class which is extended from ovm_componenet. Seq_item_port methods: . ovm_component parent).new(name. Ovm driver has 2 TLM ports. driver uses this port. Pull mode means. driver pulls the transaction from the sequencer when it requires. This driver is used in pull mode. super. class instruction_sequencer extends ovm_sequencer #(instruction). parent). 2) Rsp_port : This can also be used to send response back to sequencer.

Lets implement a driver: 1) Define a driver which takes the instruction from the sequencer and does the processing. #10. class instruction_driver extends ovm_driver #(instruction). get the transaction from the sequencer and process it.get_next_item(req). function new (string name. // Provide implementations of virtual methods such as get_type_name and create `ovm_component_utils(instruction_driver) // Constructor . while(1) begin seq_item_port. In this example. after taking the transaction. Driver class has a port "seq_item_port".new(name. using the item_done() method. we will print the transaction and wait for 10 units time. `ovm_component_utils(instruction_driver) 3) Define Constructor method. task run (). super. endfunction 4) Define the run() method. transactions are taken from the sequencer and drive them on to dut interface or to other components. parent). Using the method seq_item_port.item_done(). end endtask endclass Driver class code: class instruction_driver extends ovm_driver #(instruction).$time. 2) Place the ovm_component_utils macro to define virtual methods like get_type_name and create.inst. In this example we will just print the instruction type and wait for some delay. Once the processing is done. indicate to the sequencer that the request is completed.req. $display("%0d: Driving Instruction %s".get_next_item(). ovm_component parent). seq_item_port.name()). In this methods. Run() method is executed in the "run phase".

function new (string name, ovm_component parent); super.new(name, parent); endfunction task run (); forever begin seq_item_port.get_next_item(req); $display("%0d: Driving Instruction %s",$time,req.inst.name()); #10; // rsp.set_id_info(req); These two steps are required only if // seq_item_port.put(esp); responce needs to be sent back to sequence seq_item_port.item_done(); end endtask endclass Driver And Sequencer Connectivity: Deriver and sequencer are connected using TLM. Ovm_driver has seq_item_port which is used to get the transaction from ovm sequencer. This port is connected to ovm_sequencer seq_item_export Using "<driver>.seq_item_port.connect(<sequencer>.seq_item_export);" driver and sequencer can be connected. Simillarly "res_port" of driver which is used to send response from driver to sequencer is connected to "res_export" of the sequencer using ""<driver>.res_port.connect(<sequencer>.res_export);".

Testcase: This testcase is used only for the demo purpose of this tutorial session. Actually, the sequencer and the driver and instantiated and their ports are connected in a agent component and used. Lets implement a testcase 1) Take instances of sequencer and driver and construct both components. sequencer = new("sequencer", null); sequencer.build(); driver = new("driver", null); driver.build(); 2) Connect the seq_item_export to the drivers seq_item_port. driver.seq_item_port.connect(sequencer.seq_item_export); 3) Using set_confg_string() method, set the default sequence of the sequencer to "operation_addition". Operation_addition is the sequence which we defined previous.

set_config_string("sequencer", "default_sequence", "operation_addition"); 4) Using the start_default_sequence() method of the sequencer, start the default sequence of the sequencer. In the previous step we configured the addition operation as default sequene. When you run the simulation, you will see the PUSH_A,PUSH_B ADD and POP_C series of transaction. sequencer.start_default_sequence(); Testcase Code: module test; instruction_sequencer sequencer; instruction_driver driver; initial begin set_config_string("sequencer", "default_sequence", "operation_addition"); sequencer = new("sequencer", null); sequencer.build(); driver = new("driver", null); driver.build(); driver.seq_item_port.connect(sequencer.seq_item_export); sequencer.print(); fork begin run_test(); sequencer.start_default_sequence(); end #2000 global_stop_request(); join end endmodule

Download the example: ovm_basic_sequence.tar Browse the code in ovm_basic_sequence.tar Command to simulate Your_tool_simulation_command +incdir+path_to_ovm testcase.sv

. OVM SEQUENCE 2 Pre Defined Sequences: Every sequencer in ovm has 3 pre defined sequences. we can see that transactions are generates as we defined in ovm sequence..Log file Output OVM_INFO @ 0 [RNTST] Running test . They are 1)Ovm_random_sequence 2)Ovm_exhaustive_sequence. Ovm_random_sequence : . 0: Driving Instruction PUSH_A 10: Driving Instruction PUSH_B 20: Driving Instruction ADD 30: Driving Instruction POP_C From the above log . 3)Ovm_simple_sequence All the user defined sequences which are registered by user and the above three predefined sequences are stored in sequencer queue.

This sequence randomly selects and executes a sequence from the sequencer sequence library. then non of the sequence is executed. The print() method of the sequencer in that example printed the following ---------------------------------------------------------------------Name Type Size Value ---------------------------------------------------------------------sequencer instruction_sequen+ sequencer@2 rsp_export ovm_analysis_export rsp_export@4 seq_item_export ovm_seq_item_pull_+ seq_item_export@28 default_sequence string 18 operation_addition count integral 32 -1 max_random_count integral 32 'd10 sequences array 4 [0] string 19 ovm_random_sequence [1] string 23 ovm_exhaustive_sequ+ [2] string 19 ovm_simple_sequence [3] string 18 operation_addition max_random_depth integral 32 'd4 num_last_reqs integral 32 'd1 num_last_rsps integral 32 'd1 ---------------------------------------------------------------------- Some observations from the above log: The count is set to -1. There are 3 . In the previous example from OVM_SEQUENCE_1 section. from sequence id 2 to till the last sequence. If the "count" variable of the sequencer is set to -1. From the above image. If the "count" variable of the sequencer is set to 0. The sequencer when automatically started executes the sequence which is point by default_sequence. ovm_exaustive_sequence: This sequence randomly selects and executes each sequence from the sequencers sequence library once in a randc style. By default default_sequence variable points to ovm_random_sequence. then some random number of sequences from 0 to "max_random_count" are executed. The default sequencer is set to operations_addition. ovm_simple_sequence: This sequence simply executes a single sequence item. By default "mac_random_count" is set to 10. all the sequences are executed randomly. and ovm_exhaustive_sequence. "Count" and "mac_random_count" can be changed using set_config_int(). excluding ovm_random_sequence itself. excluding itself and ovm_random_sequence.

the "default_seuence" is set to "ovm_exhaustive_sequence" using the set_config_string. in file sequence.sv file.sv Log File 0: Driving Instruction PUSH_B 10: 20: 30: 40: 50: 60: 70: 80: Driving Driving Driving Driving Driving Driving Driving Driving Instruction Instruction Instruction Instruction Instruction Instruction Instruction Instruction PUSH_A PUSH_B SUB POP_C PUSH_A PUSH_B MUL POP_C 90: Driving Instruction PUSH_A 100: Driving Instruction PUSH_B 110: Driving Instruction ADD 120: Driving Instruction POP_C From the above log . we can see that all the 3 user defined sequences and predefined ovm_simple_sequence are executed. operation_multiplication. there are 4 seuqneces. set_config_string("sequencer". Download the example ovm_sequence_1. "default_sequence". operation_subtraction. "ovm_exhaustive_sequence").predefined sequences and 1 user defined sequence. In the testcase.tar Command to run the summation Your_tool_simulation_command +incdir+path_to_ovm testcase. .sv file.tar Browse the code in ovm_sequence_1. Lets look at a example: In the attached example. they are operation_addition.

If user is interested . send the item. wait for grant.Mid_do And Post_do . Following are the steps defined with the "sequence action macro". we have seen the implementation of body() method of sequence. randomize the item. user can print the transaction or the randomized transaction can be fined tuned. Pre_do(). We have seen these steps as Creation of item. All these steps have be automated using "sequence action macros". There are some more additional steps added in these macros. These methods should not be clled by user directly. Syntax: virtual task pre_do(bit is_item) virtual function void mid_do(ovm_sequence_item this_item) virtual function void post_do(ovm_sequence_item this_item) Pre_do() is a task . mid_do() and post_do() are callback methods which are in ovm sequence.Sequence Action Macro: In the previous sections. the behavior may be unexpected. Example Of Pre_do. he can use these methods. in mid_do() method. The body() method implementation requires some steps. For example. if the method consumes simulation cycles.

virtual task pre_do(bit is_item).OVM_LOW). This macro has all the above defined phases. Lets just print a message from this method. "Seuqnce Action Macro Phase : PRE_DO ". endtask 2)Define pre_do() method.new(name). Lets just print a message from this method. ovm_report_info(get_full_name().Lets look at a example: We will define a sequence using `ovm_do macro. endtask 3)Define mid_do() method.OVM_LOW). endfunction 4)Define post_do() method. just call messages.OVM_LOW). 1)Define the body method using the `ovm_do() macro. ovm_report_info(get_full_name(). endfunction . virtual task body(). virtual function void post_do(ovm_sequence_item this_item). function new(string name="demo_ovm_do").OVM_LOW). "Seuqnce Action Macro Phase : MID_DO ". "Seuqnce Action Macro Phase : Before ovm_do macro ". Before and after this macro. super. ovm_report_info(get_full_name(). ovm_report_info(get_full_name(). "Seuqnce Action Macro Phase : After ovm_do macro ". "Seuqnce Action Macro Phase : POST_DO ". `ovm_do(req). virtual function void mid_do(ovm_sequence_item this_item).OVM_LOW). Lets just print a message from this method. ovm_report_info(get_full_name(). endfunction Complet sequence code: class demo_ovm_do extends ovm_sequence #(instruction). instruction req.

"Seuqnce Action Macro Phase : POST_DO ". "Seuqnce Action Macro Phase : After ovm_do macro ". "Seuqnce Action Macro Phase : MID_DO ". endfunction virtual function void post_do(ovm_sequence_item this_item). "Seuqnce Action Macro Phase : Before ovm_do macro ".sv Log file report: OVM_INFO@0:reporter[sequencer. instruction_sequencer) virtual task pre_do(bit is_item).demo_ovm_do] Seuqnce Action Macro Phase : PRE_DO OVM_INFO@0:reporter[sequencer. ovm_report_info(get_full_name().OVM_LOW).demo_ovm_do] Seuqnce Action Macro Phase : MID_DO 0: Driving Instruction MUL . ovm_report_info(get_full_name(). endtask endclass Download the example ovm_sequence_2. ovm_report_info(get_full_name().demo_ovm_do] Seuqnce Action Macro Phase : Before ovm_do macro OVM_INFO@0:reporter[sequencer.OVM_LOW).OVM_LOW).tar Browse the code in ovm_sequence_2.OVM_LOW). "Seuqnce Action Macro Phase : PRE_DO ".`ovm_sequence_utils(demo_ovm_do. ovm_report_info(get_full_name().OVM_LOW). endtask virtual function void mid_do(ovm_sequence_item this_item). ovm_report_info(get_full_name(). endfunction virtual task body(). `ovm_do(req).tar Command to run the simulation Your_tool_simulation_command +incdir+path_to_ovm testcase.

Constraint block) Only create phase is skipped. Essentially. All the above defined 7 phases will be executed. rest all the phases will be executed.OVM_INFO@10:reporter[sequencer. `ovm_rand_send_with(item/sequence . `ovm_rand_send(item/sequence) Only create phase is skipped. User should use `ovm_create to create the sequence or item. Constraint block will be applied which . `ovm_do_with(item/sequence. Constraint block) This is the same as `ovm_do except that the constraint block in the 2nd argument is applied to the item or sequence in a randomize with statement before execution. Using `ovm_create. Only the create phase will be executed. rest of all the phases will be executed. create phase can be executed. List Of Sequence Action Macros: These macros are used to start sequences and sequence items that were either registered with a <`ovm-sequence_utils> macro or whose associated sequencer was already set using the <set_sequencer> method.demo_ovm_do] Seuqnce Action Macro Phase : POST_DO OVM_INFO@10:reporter[sequencer. User should use `ovm_create to create the sequence or item.demo_ovm_do] Seuqnce Action Macro Phase : After ovm_do macro The above log file shows the messages from pre_do. rest of all the phases will be executed. an `ovm_do without the create or randomization. `ovm_create(item/sequence) This action creates the item or sequence using the factory. `ovm_do(item/sequence) This macro takes as an argument a ovm_sequence_item variable or sequence .mid_do and post_do methods. `ovm_send(item/sequence) Create phase and randomize phases are skipped.

Following macros are used on sequence or sequence items on a different sequencer. `ovm_do_on(item/sequence. `ovm_do_pri(item/sequence.sequencer) This is the same as `ovm_do except that it also sets the parent sequence to the sequence in which the macro is invoked. and it sets the sequencer to the specified sequencer argument. `ovm_send_pri(item/sequence.sequencer) This is the same as `ovm_create except that it also sets the parent sequence to the sequence in which the macro is invoked. . `ovm_rand_send_pri(item/sequence. `ovm_create_on(item/sequence. and it sets the sequencer to the specified sequencer argument. constraint block .priority) This is the same as `ovm_send except that the sequence item or sequence is executed with the priority specified in the argument. priority ) This is the same as `ovm_do except that the sequence item or sequence is executed with the priority specified in the argument.sequencer.priority) This is the same as `ovm_rand_send except that the sequence item or sequence is executed with the priority specified in the argument. priority) This is the same as `ovm_do_pri except that the given constraint block is applied to the item or sequence in a randomize with statement before execution.constraint block) This is the same as `ovm_rand_send_pri except that the given constraint block is applied to the item or sequence in a randomize with statement before execution. and it sets the sequencer to the specified sequencer argument. priority) This is the same as `ovm_do_pri except that it also sets the parent sequence to the sequence in which the macro is invoked. `ovm_do_pri_with(item/sequence .priority. `ovm_rand_send_pri_with(item/sequence. `ovm_do_on_pri(item/sequence.randomization.

ovm_report_info(get_full_name().inst = instruction::PUSH_B. The user must supply brackets around the constraints. ovm_report_info(get_full_name().sequencer. and it sets the sequencer to the specified sequencer argument.OVM_LOW). and it sets the sequencer to the specified sequencer argument.OVM_LOW). ovm_report_info(get_full_name().sequencer. Examples With Sequence Action Macros: virtual task body(). `ovm_do(req) endtask virtual task body(). `ovm_create(req) req.priority.constraint block) This is the same as `ovm_do_pri_with except that it also sets the parent sequence to the sequence in which the macro is invoked. constraint block) This is the same as `ovm_do_with except that it also sets the parent sequence to the sequence in which the macro is invoked.OVM_LOW). `ovm_send(req) endtask virtual task body(). `ovm_do_with(req. "Executing Sequence Action Macro ovm_do". "Executing Sequence Action Macro ovm_do_with ".OVM_LOW). `ovm_create(req) `ovm_rand_send(req) endtask Download the example . }) endtask virtual task body(). `ovm_do_on_pri_with(item/sequence. ovm_report_info(get_full_name(). "Executing Sequence Action Macro ovm_create and ovm_send".{ inst == ADD.`ovm_do_on_with(item/sequence. "Executing Sequence Action Macro ovm_create and ovm_rand_send".

virtual task pre_body() virtual task post_body() Example In this example.tar Browse the code in ovm_sequence_3. . instruction req. These methods can be used for initialization.new(name). These callbacks are called only when start_sequence() of sequencer or start() method of the sequence is called. which are executed before and after the sequence body() method execution. class demo_pre_body_post_body extends ovm_sequence #(instruction). function new(string name="demo_pre_body_post_body"). synchronization with some events or cleanup. I just printed messages from pre_body() and post_body() methods.ovm_sequence_3. super.tar Command to sun the simulation Your_tool_simulation_command +incdir+path_to_ovm testcase.sv Log file report 0: Driving Instruction PUSH_B OVM_INFO@10:reporter[***]Executing 10: Driving Instruction ADD OVM_INFO@20:reporter[***]Executing 20: Driving Instruction PUSH_B OVM_INFO@30:reporter[***]Executing 30: Driving Instruction DIV OVM_INFO@40:reporter[***]Executing 40: Driving Instruction MUL Sequence Action Macro ovm_do_with Sequence Action Macro ovm_create and ovm_send Sequence Action Macro ovm_do Sequence Action Macro ovm_create and ovm_rand_send OVM SEQUENCE 3 Body Callbacks: Ovm sequences has two callback methods pre_body() and post_body(). User should not call these methods.

ovm_report_info(get_full_name().tar Command to sun the simulation Your_tool_simulation_command +incdir+path_to_ovm testcase." pre_body() callback ". `ovm_do(req). ovm_report_info(get_full_name().. ovm_report_info(get_full_name(). endtask endclass Download the example ovm_sequence_4. endtask virtual task body()." post_body() callback ". "body() method: Before ovm_do macro ".OVM_LOW). "body() method: After ovm_do macro ". OVM_INFO @ 0: reporter [***] pre_body() callback OVM_INFO @ 0: reporter [***] body() method: Before ovm_do macro 0: Driving Instruction SUB OVM_INFO @ 10: reporter [***] body() method: After ovm_do macro OVM_INFO @ 10: reporter [***] post_body() callback Hierarchical Sequences .OVM_LOW).tar Browse the code in ovm_sequence_4.endfunction `ovm_sequence_utils(demo_pre_body_post_body..sv Log file report OVM_INFO @ 0 [RNTST] Running test . endtask virtual task post_body(). instruction_sequencer) virtual task pre_body().OVM_LOW). ovm_report_info(get_full_name().OVM_LOW).

One main advantage of sequences is smaller sequences can be used to create sequences to generate stimulus required for todays complex protocol. These child sequences can be used as normal sequences. }). child sequence start() method should be called sequentially in body method. In the below example you can see all the 3 steps mentioned above. { inst == PUSH_B. In this example. repeat(4) begin `ovm_do_with(req. I have defined 2 child sequences. To create a sequence using another sequence. following steps has to be done 1)Extend the ovm_sequence class and define a new class. Sequence 1 code: This sequence generates 4 PUSH_A instructions. end endtask Sequential Sequence code: This sequence first calls sequence 1 and then calls sequence 2. }). 3)Start the child sequence using <instance>. class sequential_sequence extends ovm_sequence #(instruction).start() method in body() method. end endtask Sequence 2 code: This sequence generates 4 PUSH_B instructions. repeat(4) begin `ovm_do_with(req. virtual task body(). seq_a s_a. . Sequential Sequences To executes child sequences sequentially. virtual task body(). { inst == PUSH_A. 2)Declare instances of child sequences which will be used to create new sequence.

endfunction `ovm_sequence_utils(sequential_sequence.sv Log file report 0: Driving Instruction PUSH_A 10: Driving Instruction PUSH_A 20: Driving Instruction PUSH_A 30: Driving Instruction PUSH_A 40: Driving Instruction PUSH_B 50: Driving Instruction PUSH_B 60: Driving Instruction PUSH_B 70: Driving Instruction PUSH_B If you observe the above log. function new(string name="sequential_sequence"). `ovm_do(s_a). endtask endclass From the testcase.tar Command to sun the simulation Your_tool_simulation_command +incdir+path_to_ovm testcase. you can see sequence seq_a is executed first and then sequene seq_b is executed. Download the example ovm_sequence_5. instruction_sequencer) virtual task body().new(name). "sequential_sequence" is selected as "default_sequence".seq_b s_b. . child sequence start() method should be called parallel using fork/join in body method. `ovm_do(s_b). super. Parallelsequences To executes child sequences Parallel.tar Browse the code in ovm_sequence_5.

tar Command to sun the simulation Your_tool_simulation_command +incdir+path_to_ovm testcase. 0: Driving Instruction PUSH_A 10: Driving Instruction PUSH_B 20: Driving Instruction PUSH_A 30: Driving Instruction PUSH_B 40: Driving Instruction PUSH_A 50: Driving Instruction PUSH_B 60: Driving Instruction PUSH_A 70: Driving Instruction PUSH_B . super. seq_b s_b. fork `ovm_do(s_a) `ovm_do(s_b) join endtask endclass Download the example ovm_sequence_6. function new(string name="parallel_sequence").Parallel Sequence code: class parallel_sequence extends ovm_sequence #(instruction). endfunction `ovm_sequence_utils(parallel_sequence.new(name)... seq_a s_a.sv Log file report OVM_INFO @ 0 [RNTST] Running test . instruction_sequencer) virtual task body().tar Browse the code in ovm_sequence_6.

the arbitration algorithms is set to SEQ_ARB_FIFO.OVM SEQUENCE 4 Sequencer Arbitration: When sequencers are executed parallel. they are To set the arbitaration. sequencer grants to one of the sequencer. end endtask . using the arbitration mechanism. sequencer will arbitrate among the parallel sequence. Sequence code 1: virtual task body(). There are 6 different arbitration algorithms. By default . In this example. function void set_arbitration(SEQ_ARB_TYPE val) Lets look at a example. use the set_arbitration() method of the sequencer. then the sequencer. repeat(3) begin `ovm_do_with(req. { inst == MUL. }). I have 3 child sequences seq_mul seq_add and seq_sub each of them generates 3 transactions. When all the parallel sequences are waiting for a grant from sequencer using wait_for_grant() method.

endfunction `ovm_sequence_utils(parallel_sequence.set_arbitration(SEQ_ARB_RANDOM). im setting it to SEQ_ARB_RANDOM.new(name). repeat(3) begin `ovm_do_with(req. m_sequencer. end endtask Sequence code 3: virtual task body(). }). repeat(3) begin `ovm_do_with(req. before starting child sequences. { inst == SUB. set the arbitration using set_arbitration().Sequence code 2: virtual task body(). super. fork `ovm_do(add) `ovm_do(sub) `ovm_do(mul) join endtask endclass Download the example . { inst == ADD. class parallel_sequence extends ovm_sequence #(instruction). instruction_sequencer) virtual task body(). seq_sub sub. function new(string name="parallel_sequence"). In this code. seq_add add. }). seq_mul mul. end endtask Parallel sequence code: In the body method.

.tar Command to sun the simulation Your_tool_simulation_command +incdir+path_to_ovm testcase. One is using the start method of the sequence and other using the set_priority() method of the sequence. 0: Driving Instruction MUL 10: Driving Instruction SUB 20: Driving Instruction MUL 30: Driving Instruction SUB 40: Driving Instruction MUL 50: Driving Instruction ADD 60: Driving Instruction ADD 70: Driving Instruction SUB 80: Driving Instruction ADD Log file report for when SEQ_ARB_FIFO is set. In the second log file. Setting The Sequence Priority: There are two ways to set the priority of a sequence.ovm_sequence_7.sv Log file report for when SEQ_ARB_RANDOM is set. By default. the transactions are given equal priority and are in fifo order. all the transaction of the sequences are generated in random order. 0: Driving Instruction ADD 10: Driving Instruction SUB 20: Driving Instruction MUL 30: Driving Instruction ADD 40: Driving Instruction SUB 50: Driving Instruction MUL 60: Driving Instruction ADD 70: Driving Instruction SUB 80: Driving Instruction MUL If you observe the first log report. the priority of a sequence is 100. Higher numbers indicate higher priority.tar Browse the code in ovm_sequence_7.

add = new("add"). mul = new("mul"). join endtask endclass Download the example . Code : class parallel_sequence extends ovm_sequence #(instruction). seq_mul mul. seq_sub sub. endfunction `ovm_sequence_utils(parallel_sequence. m_sequencer. For sequence seq_mul set the weight to 200.400). sub = new("sub").virtual task start (ovm_sequencer_base sequencer.start(m_sequencer.this. seq_add add.set_arbitration(SEQ_ARB_WEIGHTED). instruction_sequencer) virtual task body(). integer this_priority = 100. super. bit call_pre_post = 1) function void set_priority (int value) Lets look a example with SEQ_ARB_WEIGHTED. For sequence seq_add set the weight to 300. fork sub.this.300).new(name). add. ovm_sequence_base parent_sequence = null. In the below example. For sequence seq_sub set the weight to 400.start(m_sequencer. function new(string name="parallel_sequence"). start() method is used to override the default priority value. mul.start(m_sequencer.200).this.

p_sequencer is a handle to its sequencer. 7) Defines p_sequencer variable. then use macro `ovm_sequence_utils_begin(TYPE_NAME.tar Command to sun the simulation Your_tool_simulation_command +incdir+path_to_ovm testcase. 4) Implements the static get_type() method. 8) Implements m_set_p_sequencer() method.sv Log file report 0: Driving Instruction MUL 10: Driving Instruction ADD 20: Driving Instruction SUB 30: Driving Instruction SUB 40: Driving Instruction ADD 50: Driving Instruction ADD 60: Driving Instruction ADD 70: Driving Instruction MUL 80: Driving Instruction SUB OVM SEQUENCE 5 Sequencer Registration Macros Sequence Registration Macros does the following 1) Implements get_type_name method. 5) Implements the virtual get_object_type() method. 2) Implements create() method. 3) Registers with the factory.SQR_TYPE_NAME) `ovm_field_* macro invocations here .tar Browse the code in ovm_sequence_8.ovm_sequence_8.SQR_TYPE_NAME) If there are local variables in sequence. If there are no local variables. 6) Registers the sequence type with the sequencer type. then use following macro `ovm_sequence_utils(TYPE_NAME.

`ovm_sequence_utils_end Macros `ovm_field_* are used for define utility methods.num_inst). end endtask endclass Download the example ovm_sequence_9. $psprintf("Num of transactions %d".5.sv .7 }. repeat(num_inst) begin `ovm_do_with(req. rand integer num_inst . instruction req.instruction_sequencer) `ovm_field_int(num_inst. endfunction virtual task body(). constraint num_c { num_inst inside { 3. { inst == MUL. OVM_ALL_ON) `ovm_sequence_utils_end function new(string name="seq_mul"). ovm_report_info(get_full_name(). `ovm_sequence_utils_begin(seq_mul. These `ovm_field_* macros are discussed in OVM_TRANSACTION Example to demonstrate the usage of the above macros: class seq_mul extends ovm_sequence #(instruction).tar Browse the code in ovm_sequence_9.OVM_LOW). }. }).tar Command to sun the simulation Your_tool_simulation_command +incdir+path_to_ovm testcase. super.new(name).

integer num_inst = 4. sequence members can be updated if the variable is configured. using the sequencer get_config_* methods. So from the sequence. When using set_config_* . But there is a workaround to this problem. 2) In the body method. OVM_INFO @ 0: reporter [sequencer. Sequence has handle name called p_sequencer which is pointing the Sequencer on which it is running. .. path to the variable should be sequencer name.Log OVM_INFO @ 0: reporter [RNTST] Running test . so get_config_* methods are implemented for it. call the get_config_int() method to get the integer value if num_inst is configured from testcase. class seq_mul extends ovm_sequence #(instruction).instruction_sequencer) `ovm_field_int(num_inst. instruction req.seq_mul] Num of transactions 0: Driving Instruction MUL 10: Driving Instruction MUL 20: Driving Instruction MUL 30: Driving Instruction MUL 40: Driving Instruction MUL 5 Setting Sequence Members: set_config_* can be used only for the components not for the sequences. OVM_ALL_ON) `ovm_sequence_utils_end function new(string name="seq_mul"). as we are using the sequencer get_config_* method. `ovm_sequence_utils_begin(seq_mul.. Following method demonstrates how this can be done: Sequence: 1) num_inst is a integer variables which can be updated. Sequencer is a component . By using configuration you can change the variables inside components only not in sequences.

using the set_config_int() method.new(name). module test. instruction_sequencer sequencer.seq_item_port. repeat(num_inst) begin `ovm_do_with(req.3). endfunction virtual task body(). { inst == MUL. "seq_mul").start_default_sequence(). end endtask endclass Testcase: From the testcase. sequencer = new("sequencer". end #3000 global_stop_request(). driver.build(). driver.num_inst). The instance path argument should be the sequencer path name. "num_inst".seq_item_export). "default_sequence".num_inst)).build(). configure the num_inst to 3. void'(p_sequencer. $psprintf("Num of transactions %d".connect(sequencer.super.OVM_LOW). sequencer. }).print(). sequencer. null). initial begin set_config_string("sequencer". fork begin run_test(). instruction_driver driver. driver = new("driver". .get_config_int("num_inst". set_config_int("sequencer". null). ovm_report_info(get_full_name(). sequencer.

num_inst value is 3. There are 2 mechanisms to get exclusive access: Lock-unlcok Grab-ungrab Lock-Unlock task lock(ovm_sequencer_base sequencer = Null) function void unlock(ovm_sequencer_base sequencer = Null) .tar Command to sun the simulation Your_tool_simulation_command +incdir+path_to_ovm testcase.seq_mul] Num of transactions 0: Driving Instruction MUL 10: Driving Instruction MUL 20: Driving Instruction MUL 3 From the above log we can see that seq_mul.join end endmodule Download the example ovm_sequence_10. OVM_INFO @ 0: reporter [sequencer.sv Log OVM_INFO @ 0: reporter [RNTST] Running test .tar Browse the code in ovm_sequence_10.. OVM SEQUENCE 6 Exclusive Access A sequence may need exclusive access to the driver which sequencer is arbitrating among multiple sequence.. Some operations require that a series of transaction needs to be driven without any other transaction in between them. Then a exclusive access to the driver will allow to a sequence to complete its operation with out any other sequence operations in between them.

a sequence can requests for exclusive access. { inst == PUSH_B. it will unblock. Sequence 1 code: virtual task body(). A lock is granted after all earlier requests are completed and no other locks or grabs are blocking this sequence. repeat(4) begin `ovm_do_with(req. the lock/unlock will be applied on the current default sequencer. }). endtask . { inst == POP_C. lock(). repeat(4) begin `ovm_do_with(req. then call the unclock() method. Using unlock(). In this example there are 3 sequences with each sequence generating 4 transactions. }). All these 3 sequences will be called in parallel in another sequence. Lets see an example. end endtask Sequence 3 code: In this sequence . If sequencer is null. end unlock(). A lock() is blocking task and when access is granted. After completing all the transaction driving. virtual task body(). { inst == PUSH_A. end endtask Sequence 2 code: virtual task body(). A lock request will be arbitrated the same as any other request. repeat(4) begin `ovm_do_with(req.Using lock() method . removes any locks or grabs obtained by this sequence on the specified sequencer. call the lock() method to get the exclusive access to driver. }).

To get the exclusive access without arbitration. then transactions from seq_a and seq_c are not generated. we can observe that . Lock() will be arbitrated before giving the access. fork `ovm_do(s_a) `ovm_do(s_b) `ovm_do(s_c) join endtask Download the example ovm_sequence_11.Parallel sequence code: virtual task body(). Grab-Ungrab task grab(ovm_sequencer_base sequencer = null) .tar Browse the code in ovm_sequence_11. grab() method should be used.sv Log file: 0: Driving Instruction PUSH_A 10: Driving Instruction POP_C 20: Driving Instruction PUSH_A 30: Driving Instruction PUSH_B 40: Driving Instruction PUSH_B 50: Driving Instruction PUSH_B 60: Driving Instruction PUSH_B 70: Driving Instruction POP_C 80: Driving Instruction PUSH_A 90: Driving Instruction POP_C 100: Driving Instruction PUSH_A 110: Driving Instruction POP_C From the above log file.tar Command to sun the simulation Your_tool_simulation_command +incdir+path_to_ovm testcase. when seq_b sequence got the access.

sv 0: Driving Instruction PUSH_A 10: Driving Instruction POP_C 20: Driving Instruction PUSH_A 30: Driving Instruction PUSH_B 40: Driving Instruction PUSH_B 50: Driving Instruction PUSH_B 60: Driving Instruction PUSH_B 70: Driving Instruction POP_C 80: Driving Instruction PUSH_A 90: Driving Instruction POP_C 100: Driving Instruction PUSH_A 110: Driving Instruction POP_C . A grab() is granted when no other grabs or locks are blocking this sequence. grab().tar Browse the code in ovm_sequence_12. { inst == PUSH_B. repeat(4) begin `ovm_do_with(req. If no argument is supplied. then current default sequencer is chosen. #25. It will be arbitrated before any other requests. A grab() is blocking task and when access is granted. end ungrab().tar Command to sun the simulation Your_tool_simulation_command +incdir+path_to_ovm testcase. Example: virtual task body(). endtask Download the example ovm_sequence_12. Ungrab() method removes any locks or grabs obtained by this sequence on the specified sequencer. it will unblock.function void ungrab(ovm_sequencer_base sequencer = null) grab() method requests a lock on the specified sequencer. A grab() request is put in front of the arbitration queue. }).

bitstream_t value: In set_config_int. Using set_config_* methods. This mechanism can be used only with components. It is the responsibility of the lower level component to get the data from the component table and update the appropriate table. ovm_bitstream_t value) function void set_config_string (string inst_name. string and object of ovm_object based class respectively. Set_config_* Methods: Following are the method to configure integer . ovm_object value. function void set_config_int (string inst_name. string value) function void set_config_object (string inst_name. a integral value that can be anything from 1 bit to 4096 bits. inst_name and field_name are strings of hierarchal path. bit clone : If this bit is set then object is cloned. Without this mechanism. which restricts reusability. string field_name. These methods must be called in build phase of the component. Higher level component can set the configuration data in level component table. user can configure integer. Sequences and transactions cannot be configured using this mechanism. bit clone = 1) Arguments description: string inst_name: Hierarchical string path. There is also a global configuration table. . the data is stored w. When set_config_* method is called. string field_name. user should access the lower level component using hierarchy paths.OVM CONFIGURATION Configuration is a mechanism in OVM that higher level components in a hierarchy can configure the lower level components variables. They can include wile card "*" and "?" characters.r. string field_name: Name of the field in the table.t strings in a table. string field_name. string and objects of lower level components.

. Example: "abc"."bbc" .. "*abc" -All the lower level components which ends with "abc". Example: "xabc". Automatic Configuration: To use the atomic configuration. then followed by one more character.then followed by "c". Example: "abc".."xyzabc" ."axc" …."aac"."abx" . There are two ways to get the configuration data: 1)Automatic : Using Field macros 2)Manual : using gte_config_* methods.. all the configurable fields should be defined using ovm component field macros and ovm component utilities macros."abcxy". "a?c" -All the lower level components which start with "a" ."abcxyz" . Example: "abc"..."xbc"."abb". Ovm component utility macros: For non parameterized classes `ovm_component_utils_begin(TYPE) `ovm_field_* macro invocations here `ovm_component_utils_end For parameterized classes...."*" matches zero or more characters "?" matches exactly one character Some examples: "*" -All the lower level components. then followed by one more character and then followed by "c". `ovm_component_param_utils_begin(TYPE) . "ab?" -All the lower level components which start with "ab" ."xyabc".. "?bc" -All the lower level components which start with any one character . Example: "abcx". "abc*" -All the lower level components which starts with "abc"....

string str_cfg. OVM_DEFAULT) . a integer and a string are defined in env. agent and monitor are define. agent. Refer to link OVM_TRANSACTION Example: Following example is from link OVM_TESTBENCH 2 Configurable fields. class driver extends ovm_driver. integer int_cfg. monitor and driver classes. all other components env. `ovm_component_utils_begin(driver) `ovm_field_int(int_cfg. Topology of the environment using these classes is Driver class Source Code: Similar to driver class.`ovm_field_* macro invocations here `ovm_component_utils_end For OVM Field macros.

ovm_component parent)."int_cfg".int_cfg set_config_int("*.ag1.ag?.ag2. //t_env.drv.*".ag2. //t_env. //t_env.str_cfg set_config_string("*.mon". super. OVM_DEFAULT) `ovm_component_utils_end function new(string name."int_cfg".`ovm_field_string(str_cfg.drv set_config_int("t_env.32)."str_cfg".ag2.str_cfg //t_env.drv.32). endfunction endclass Testcase: Using set_config_int() and set_config_string() configure variables at various hierarchal locations.mon. endfunction function void build().tar Command to run the simulation your_tool_simulation_command +path_to_ovm_pkg -f filelist +OVM_TESTNAME=test1 ."pars"). Download the source code ovm_configuration_1. parent).new(name. //t_env.32).ag2.ag1.str_cfg set_config_string("t_env".ag1.ag1."int_cfg". super.*".ag1.tar Browse the code in ovm_configuration_1.mon set_config_int("t_env.mon.ag2.str_cfg //t_env."str_cfg".build().int_cfg //t_env. //t_env.drv.mon.ag2."abcd").drv".str_cfg //t_env.

user can get the required data if the data is available in the table. then the function returns "0".OVM_LOW). endfunction function void build(). string and object of ovm_object based class respectively. `ovm_component_utils(driver) function new(string name. inout string value) function bit get_config_object (string field_name. string str_cfg. inout ovm_object value.new(name.build(). check the return value.str_cfg)). parent). Example: Driver class code: class driver extends ovm_driver. inout ovm_bitstream_t value) function bit get_config_string (string field_name. ovm_component parent). ovm_report_info(get_full_name(). Manual Configurations: Using get_config_* methods. void'(get_config_int("int_cfg". input bit clone = 1) If a entry is found in the table with "field_name" then data will be updated to "value" argument .int_cfg. we can see the variables int_cfg and str_cfg of all the components and they are as per the configuration setting from the testcase.int_cfg)). super. endfunction . function bit get_config_int (string field_name. super. $psprintf("int_cfg %0d : str_cfg %0s ". Following are the method to get configure data of type integer . If entry is not found. void'(get_config_string("str_cfg". integer int_cfg.str_cfg).From the above log report of th example. So when these methods are called.

ag2 int_cfg x : str_cfg OVM_INFO @ 0: ovm_test_top. then information for all children components are printed recursively.ag2. print_config_matches static bit print_config_matches = 0 .endclass Download the source code ovm_configuration_2.tar Browse the code in ovm_configuration_2.ag1. If "field" is specified and non-empty. ovm_component comp = null.t_env int_cfg x : str_cfg abcd OVM_INFO @ 0: ovm_test_top.drv int_cfg 32 : str_cfg pars OVM_INFO @ 0: ovm_test_top.drv int_cfg 32 : str_cfg pars OVM_INFO @ 0: ovm_test_top.tar Command to run the simulation your_tool_simulation_command +path_to_ovm_pkg -f filelist +OVM_TESTNAME=test1 Log file OVM_INFO @ 0: ovm_test_top. If "recurse" is set.t_env.t_env.t_env. bit recurse = 0 ) This method prints all configuration information for this component.t_env.t_env.ag1.t_env.ag1 int_cfg x : str_cfg OVM_INFO @ 0: ovm_test_top.mon int_cfg 32 : str_cfg pars OVM_INFO @ 0: ovm_test_top.mon int_cfg 32 : str_cfg pars Configuration Setting Members: print_config_settings function void print_config_settings ( string field = "". The field may not contain wildcards. if any.ag2. then only configuration settings matching that field. are printed.

t_env str_cfg string abcd .*.drv ovm_test_top.*.t_env.ag1.t_env [auto-configuration] Auto-configuration matches for component ovm_test_top.ag1.ag1.Setting this static variable causes get_config_* to print info about matching configuration settings as they are being applied.* str_cfg string pars ovm_test_top. Download the source code ovm_configuration_3.t_env.drv.ag1.ag?.*.rsp_port ovm_test_top.drv.* int_cfg int 32 When print_config_matches is set to 1. These two members will be helpful to know while debugging.drv. Last entry for a given field takes precedence. Config set from Instance Path Field name Type Value -----------------------------------------------------------------------------ovm_test_top(test1) ovm_test_top.sqr_pull_port ovm_test_top.tar Browse the code in ovm_configuration_3.ag1.rsp_port ovm_test_top.ag?.*.t_env (env).t_env.sqr_pull_port ovm_test_top.* int_cfg int 32 ovm_test_top.* int_cfg int 32 ovm_test_top.ag1.t_env.ag1.*.t_env.* str_cfg string pars ovm_test_top.drv.ag1.tar Command to run the simulation your_tool_simulation_command +path_to_ovm_pkg -f filelist +OVM_TESTNAME=test1 Log file When print_config_settings method is called ovm_test_top. OVM_INFO @ 0: ovm_test_top.

in/CM_00_INDEX.http://testbench.html .

Sign up to vote on this title
UsefulNot useful