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. A 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.
(S)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.
--> virtualfunctionvoid build()
This phase is used to construct various child components/ports/exports and configures them.
--> virtualfunctionvoid connect()
This phase is used for connecting the ports/exports of the components.
--> virtualfunctionvoid end_of_elaboration()
This phase is used for configuring the components if required.
--> virtualfunctionvoid start_of_simulation()
This phase is used to print the banners and topology.
--> virtualtask run()
In this phase , Main body of the test is executed where all threads are forked off.
--> virtualfunctionvoid extract()
In this phase, all the required information is gathered.
--> virtualfunctionvoid check()
In this phase, check the results of the extracted information such as un responded requests in scoreboard, read statistics registers etc.
--> virtualfunctionvoid report()
This phase is used for reporting the pass/fail status.
Only build() method is executed in top down manner. i.e after executing parent build() method, child objects build() methods are executed. All other methods are executed in bottom-up manner. The run() method is the only method which is time consuming. The run() method is forked, so the order in which all components run() method are executed is undefined.
Ovm_test
Ovm_test is derived from ovm_component class and there is no extra functionality is added. 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> . User can also select the testcase by passing the testcase name as string to ovm_root::run_test(<testcase_string>) method.
In the above <testcase_string> is the object type of the testcase class.
Lets implement environment for the following topology. I will describe the implementation of environment , testcase and top module. Agent, monitor and driver are implemented similar to environment.
1)Extend ovm_env class and define user environment.
class env extends ovm_env;
2)Declare the utility macro. This utility macro provides the implementation of create() and get_type_name() methods and all the requirements needed for factory.
`ovm_component_utils(env)
3)Declare the objects for agents.
agent ag1;
agent ag2;
4)Define the constructor. In the constructor, call the super methods and pass the parent object. Parent is the object in which environment is instantiated.
function new(string name , ovm_component parent = null);
super.new(name, parent);
endfunction: new
5)Define build method. In the build method, construct the agents.
To construct agents, use create() method. 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.
6)Define connect(),end_of_elaboration(),start_of_simulation(),run(),extract(),check(),report() methods.
Just print a message from these methods, as we dont have any logic in this example to define.