Example Usage of Systemverilog Interface Class
Interface class is a very common concept in many object-oriented programming languages. In Systemverilog, it was introduced since 2012 version, but still rarely seen in verification environment.
Interface Class vs Interface
The first thing we need to address here is the confusion between interface and interface class in Systemverilog. These are two different concepts and serve different purposes.
- The interface in Systemverilog is a group of signals, or methods, and is used for connecting the signals between the blocks (hardware module and software obj).
- The interface class in the other hand, is a very common term in Object Oriented Programming. It is used to define a set of methods that are used for a specific purpose. Think of it as a template, when a class implements an interface class, that class must follow this template and construct all the required methods.
To understand the interface class concept, let’s look at an example below, where interface class is not used at first and how it helps the issue when coming into use in the later implementation.
A Problem Needed to Be Solved
Let’s consider this case:
- We have memory manager component
mem_mgr
in our verification env. - This
mem_mgr
will have a functionbackdoor_obj_data
to write data to the memory backdoor. - In the the test we will call this function to write a data of our objs to SoC memory.
- Assuming in current env, we need to support 2 type of data packets:
aes_pkt
anduart_pkt
.
So when designing the mem_mgr
class, not using interface class, we might implement it as below:
In the above implementation of the backdoor_obj_data()
function, there are some rules that must be followed:
- Firstly, the input argument of the function
backdoor_obj_data
need to beuvm_object
. Since all transaction objects in the uvm env will be extends from this base class. We cannot let the argument asbackdoor_obj_data(aes_pkt m_obj)
because we also need to run this function withuart_pkt
obj. - Secondly, each class
uart_pkt
andaes_pkt
must have them_addr
variable andm_data
queue. - Thirdly, we need to cast the
m_obj
from typeuvm_object
to eitheruart_pkt
oraes_pkt
. Otherwise we will meet an error sinceuvm_object
type does not havem_addr
andm_data
in it.
This implementation has several issues:
- The
mem_mgr
job is to backdoor data to memory, it should not need to be aware of which class it supports, which isaes_pkt
anduart_pkt
. - If we need to support more type of data, we must modify the function
backdoor_obj_data()
as what we do foraes_pkt
anduart_pkt
. - The
aes_pkt
anduart_pkt
are usually mantained by different programmers working in the same verification environment. Basically, letting all verification engineers modifying 1 file is not a good idea. If just one of the programmers does not follow the rules above, such as using different variable name instead ofm_addr
, the whole verification environment will be break. And other engineers will not be able to run simulation. - This implementation makes the
mem_mgr
become very messy later when more and more class type need to be suppported to backdoor to memory.
Using an Interface Class
Now, let’s implement the mem_mgr
using interface class and see how it helps in this case.
Define a Interface Class
Firstly, we need to define an interface class. It’s a good practice to use an adjective to name an interface class, and it’s also should be named after what it’s capable of.
In this example, let’s create an memory_backdoorable
interface class. Since the object that implements this interface class can be backdoored by our memory manager (backdoorable).
In this interface, we define a pure virtual function get_data_info
. This function will be called by our memory manager to get the data, and its address to backdoor to the SoC memory.
Any object wishes to have data backdoored by the memory manager must implement this interface class and create this function.
Implement an Interface Class
Now, since the aes_pkt
needs to be backdoored to SoC memory, we will implements
the memory_backdoorable
interface.
As this interface has a pure function get_data_info
, it is required to be defined in the aes_pkt
.
This function will output the addr
, and the data
queue which are later used by mem_mgr
to write data to SoC memory.
Using Interface Class as Input Arguments
Back to the implementation of mem_mgr
, now we will use the memory_backdoorable
as the input argument for backdoor_obj_data()
function.
We can clearly see that:
- The
mem_mgr
will not need to know which class type it is getting backdoor data from. Therefore, no need to casting and checking if the type is supported as another implementation. - We can also avoid any modification if new type of class is needed to be backdoor by
mem_mgr
. If new class type needs to be backdoor bymem_mgr
, it need to implements thememory_backdoorable
and create theget_data_info
function. - Also, by using the interface class, we can eliminate the implicit coding conventions such as backdoorable class must have
m_addr
andm_data
variable. All the requirements are defined explicit in the interface class. So it is easier for any verification engineer to follow.
If we look at the test_a
where the backdoor_obj_data
action is triggered, it’s still the same as the requirements, but the code of mem_mgr
is much more simplier, and more important, the mem_mgr
is totally independent from the aes_pkt
and uart_pkt
.
Later, when another class, let’s say spi_pkt
, needs to be backdoored by mem_mgr
, we just need to make sure that the new class spi_pkt
implements memory_backdoorable
and its required method get_data_info
. The mem_mgr
will remain untouch.
Some side notes
Sometimes it seems a bit difficult to follow the flow of data, we just need to clarify these three places and the action of each one:
- Where the related data for the targeted operation come from: In this example the object of
aes_pkt
anduart_pkt
will provide data for backdoor operation. - Where the action is performed: The
mem_mgr
is where the data backdoor action is actually performed. - Where the action is triggered: The test is where the backdoor action is triggered, by calling the
mem_mgr.backdoor_obj_data()
function with the input argument is any object implementing thememory_backdoorable
interface class.
Further reading
- Interface class is a basic concept in other oop languages, if you’re insterested, get to know the SOLID Principles to understand why we should use the interface class.
- There are several DVCon papers that share other application of interface class such as:
- SystemVerilog Interface Classes - More Useful Than You Thought
- Design Patterns by Example for SystemVerilog Verification Environments Enabled by SystemVerilog 1800-2012
[Tags
systemverilog
]