The Open Verification Methodology (OVM) has been available for download under the Apache 2.0 license since January 2008. Signs of an ecosystem have gradually emerged since then. As just one example, consider the OVM Forum.
As of this writing in early 2010, the forum has more than 1,300 topic threads containing more than 5,200 posts, which almost certainly makes it the most vibrant Web destination devoted to test-bench reuse topics.
However, from perusing the forum and speaking with colleagues working on verification of IC designs, it's clear that to date OVM has been used more to tinker with than to transform the building, use and maintenance of test-benches.
Verification engineers are still using events in their scoreboards to communicate with the monitor, still writing jumbo drivers with hundreds of interface instances and still propagating these interfaces using successive assign_vi tasks or arguments in the constructor.
For the uninitiated, all these are signs of poorly optimized architecture—and of the yet-to-be-realized promise of OVM.
A major part of this promise is that OVM components can be configured into various flavors via configuration classes, which is the subject of this article.
OVM configuration classes
Configuration classes collectively offer a means to assign values to variables within OVM components and retrieve them later using a string-based mechanism, which progressively searches for the variable name from top to bottom of the component hierarchy.
Like most of the best ideas in computer engineering, the mechanism sounds simple though is potentially powerful in various applications and scenarios. Among these are the following:
1) Configuring OVM Verification Components (OVCs) into various modes without adding any code;
2) Propagating the interfaces into components from the top level without affecting the intermediate levels, as what happens when the assign_vi mechanism is used; and,
3) Creating an intuitive configuration file for the verification IP (VIP) that can be used to control the top level configuration parameters such as packet-to-packet delay, request-to-data delay and so on.
Configuration classes can be used to change the nature of a verification environment. The direct application of configuration classes. Examples including statically and dynamically configuring individual variables using set_config_int and get_ config_int have been already much written about.
This article discusses what until now has been an infrequently described application of OVM, using configuration classes to shape the nature of the components rather than nitpicking its individual parameters.
Propagation of interfaces
Pin-level components such as drivers and monitors need access to interfaces within their methods. There are two popular mechanisms to achieve this:
1) Propagating the interfaces through a task called assign_vi which forms part of all components from the top to the pin level of the hierarchy.
2) Propagating the interfaces through the class constructor
Both cases are marked by a chain of interfaces that start at the test-bench top and cascade down to the driver and monitor, which exist deep down in the test-bench hierarchy. So for example, propagating an interface in a five layered environment from agent to driver/monitor requires five unnecessary layers of assign_vi tasks.
This approach will work, but is associated with many problems. One is that the user inadvertently gives access to the interface in transaction level blocks such as tests, because they come in the same hierarchy, thus making the transaction layers prone to bad coding practices such as driving and snooping of design interfaces.
Another is that the user will have to use multiple assign_vi tasks for each interface or a single assign_vi/constructor with multiple interfaces as arguments. In either scenario, the user will have to modify every component in the hierarchy if there is any new interface added to the environment.
Using configuration classes for interface connections helps to mitigate this unwieldy complexity in at least two ways:
1) By making the interface a part of the VIP configuration class; and,
2) By having a separate configuration class for the virtual interface alone.
In both instances, the user merely has to define a configuration class with the desired interface and then use the set_con-fig_object/get_config_object on the components requiring this interface.
The code in Listing 1 below depicts the reuse of the VIP configuration class for propagating the interface and other configuration parameters into the verification components from the test-bench top.
|Listing 1: This code depicts the reuse of the VIP configuration class for propagating the interface and other configuration parameters into the verification components from the test-bench top.|
However, this approach cannot be used in all cases. For example, consider an environment used for both block-and chip-level verification. In such an environment, the configuration class might change when moving from block-to chip-level even as interfaces from which the monitors snoop remain the same.
The antidote, described in Listing 2 below , is to use a separate virtual interface container class, which enables interoperability and can be passed between components using set_con-fig_object.
|Listing 2: The antidote is to use a separate virtual interface container class, which enables interoperability and can be passed between components using set_config_object.|
The previous examples show one of the main benefits of smart application of OVM configuration classes—namely, that none of the intermediate components are affected by the interface propagation. Indeed, OVM configuration classes can enable nearly unbounded configurability.
One of the countless examples: building a generic monitor that works with two or three similar interfaces requires only creating a generic interface inside your monitor and then configuring it with the required interface from the configuration classes as against creating multiple interfaces of different types, which then gets connected to master interfaces through assign_vi tasks or constructor.
An issue plaguing OVM users is the availability of normal ovm_component options in the sequences. The problem stems out from the fact that ovm_sequences fall under an ovm_sequence_item hierarchy that is an extended format of the ovm_object.
Due to this, the built-in functionalities available within the ovm_component class is unavailable inside the ovm_sequences . It is a little known OVM information that the ovm_sequence hierarchy has a built-in handle called m_sequencer that can be used to access all the ovm_component features.
The same handle can be used to access configuration classes also from the sequences. Subsequent examples (Listing 3 below ) depict how to access the configuration classes in a sequence, a technique that can be used in environments with or without a default sequencer.
|Listing 3: Here's how to access the configuration classes in a sequence, a technique that can be used in environments with or without a default sequencer.|
Building and configuring OVM components always starts from the top. Configuration classes are propagated down through the hierarchy, affecting all the components encountered in the path. There are, however, scenarios where a lower level component has to set a value higher up in the hierarchy.
For example, a user might want to adjust a configuration parameter at the top level of test case. The challenge here is that the usage of a set_config_object from the env level effectively restricts the hierarchy of the configuration object from the top file, and a test component above the hierarchy does not have visibility to this configuration object in its build task.
Although OVM does not offer a straightforward means of directly addressing this problem, a work-around, shown in Listing 4 below , is to set the set_config_object from the default hierarchy of the test called ovm_test_top in the test bench env file.
This will ensure that the configuration parameter is visible to the test. A final caveat: The configuration parameters can be made visible across different instantiations by setting the set_config_object call for both hierarchies with their corresponding configuration classes:
|Listing 4: Although OVM does not offer a straightforward means of directly addressing this problem, a workaround is to set the set_config_object from the default hierarchy of the test called ovm_test_top in the test bench env file|
Configuration classes, when used properly, greatly improve the configurability and adaptability of a verification environment. Whether it may be about simply configuring your verification components or propagating interfaces, the application of configuration classes are profound.
The simple string based code is truly one of the biggest contributions of OVM towards verification methodology space and is one of the key reasons OVM is a sea change in the verification world.
Arjun Mohan is an Application Engineer and Ashish Kumar is Lead Application Engineer at Mentor Graphics.