1. 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

    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.

  2. Download Paper