What Does the Sequence Say? Powering Productivity with Polymorphism
In a SystemVerilog UVM testbench a UVM sequence is much like a program or a function call or a test. Writing interesting sequences can help with productivity and coverage closure. On one hand a sequence is simply a list of instructions, but on the other hand how those instructions are built or how they are used with other instructions can improve the test. This paper will demonstrate easy ways to incorporate new transactions and sequences into a SystemVerilog UVM Testbench.

-
Introduction
This paper assumes some familiarity with SystemVerilog1 and the UVM2. The examples here will be simple, but some of the concepts will be easier with a deeper background. Certainly, new users to the UVM can understand these concepts and can apply them to their first testbench. This is not a primer for new object-oriented programmers.
Our UVM testbenches in this paper will resemble the architecture below. A collection of UVM components (sequencer and driver) will be constructed in an environment (or agent). A sequence will be constructed by a test or a virtual sequence. It will be “started” (run) on the sequencer. It will generate transactions which will “go into the sequencer” and then get picked up by the driver.
The driver will cause those transactions to be interpreted and the appropriate bus signals to be driven. This is basic UVM. Nothing fancy. The basic testbench is very simple. Our productivity boost will come from not changing any existing code, but by simply adding a few lines of new code and “overriding” the factory constructions.
Figure 1: Basic UVM Testbench with Two Interfaces
Understanding Inheritance and Polymorphism
The Base Class
Polymorphism is about inheritance in an object-oriented programming world. Polymorphism is simple. But the details get hard sometimes. A polymorphic object is much like the base class, but “better”. For example, if we had a base class describing a BALL object, we could derive a BASKETBALL and a RACQUETBALL from the BALL object. We could further derive a kids BASKETBALL and a professional BASKETBALL from a BASKETBALL.
class ball; virtual function string get_name(); return "Ball"; endfunction virtual function void print(); $display("%s", get_name()); endfunction endclass
The class ‘ball’ is our base class. It defines two functions, get_name() and print(). They are virtual functions. Virtual functions are important later when the polymorphic object handles are used. This is important. When a handle is used to call a function, the function called could be from the DECLARED class of the object (ball) or the actual handle type (in the case of polymorphic assignments) – the function in the ACTUAL, DERIVED class.
If the function is declared as a virtual function, then the derived version is used in the case of a polymorphic assignment. That’s what we want. Generally, just always declare functions and tasks as virtual. It will usually be what is wanted.
-
Download Paper