Logo

Virtual Class in System Verilog

23 Sep 2023
4 mins

We will continue our discussion of the OOPs concept in this article. In past articles we have seen how encapsulation, polymorphism and other OOPs concept is implemented in SV. This article will cover the data abstraction concept and how it is implemented in SV. Lets explore

Introduction

System Verilog provides virtual classes which can be used for data abstraction. Abstract classes or virtual classes are classes that cannot be instantiated but can be used as base classes for other classes. These classes can define common behavior and interfaces for their subclasses but leave some details to be implemented by the subclasses. Thus, we see that abstract classes can provide a high level of abstraction and flexibility for the code.

Definition of abstract class

Abstract classes are defined using virtual keyword. This is like virtual functions but in this case, we use virtual keyword with class.

Syntax
virtual class <class_name>;
    <class body>
endclass

How to use abstract class?

Abstract classes cannot be instantiated directly as they are not actual classes. We need to create a sub-class from this abstract class which can be instantiated and used in the code. Creating a sub-class of abstract class is like creating a sub-class of normal classes. We use extends keyword to define a sub-class.

Ex – class <sub_class> extends <virtual_class_name>;

Sub-class will have access to all the data fields and methods present in abstract classes and can override it. It might seem that all the things can be done normally, then what is the need of abstract classes.

Example

virtual class Animal;
    // Declare some properties and methods common to all animals
    string name;
    int age;
    function void eat();
        // Implement some generic behavior for eating
        $display("%s is eating", name);
    endfunction
    // Declare some methods that are specific to each subclass
    virtual function void make_sound();
        // Leave this method empty or with a default behavior
        $display("%s is making a sound", name);
    endfunction
    virtual function void move();
        // Leave this method empty or with a default behavior
        $display("%s is moving", name);
    endfunction
endclass

Need of Abstract Classes

Abstract classes or virtual classes provide a way by which we can define a common layout on which other classes can be based on.

We know that data abstraction in simple terms means using the set of data out of a larger data set for our case. For example, a data set for a student can have lot of fields but for a librarian not all the data are necessary. Abstract classes are used to limit the data so that all classes which are needed for a specific task can include those limited data and tasks.

Advantages of virtual class

Abstract classes can help you achieve several benefits in your System Verilog code, such as:

  • Polymorphism: We can use abstract classes to define a common interface for different types of objects and use virtual methods to invoke the appropriate behavior at run time.
  • Encapsulation: Implementation details of an abstract class can be hidden from its users, and only the relevant methods and properties are exposed.
  • Inheritance: We can use abstract classes to create hierarchies of classes that share some characteristics but differ in others.

Pure virtual functions

These are special kinds of method definition which can only be used inside a virtual class. By using a pure keyword with the method definition we do not need to write the body of method inside virtual class.

The method body needs to be defined by all the sub-classes which is derived from abstract class. If a sub-class does not provide a implementation of the pure virtual function then there will be a compilation error.

This is helpful when we know that we need a method for a certain task, but the implementation may be different in other scenarios. This also ensures that all the needed methods are present in a class.

Synatx – pure virtual <method_name>();

We cannot have a method body defined while using pure virtual methods. Doing so will lead to compile time errors.

Example

virtual class Animal;
    // Declare some properties and methods common to all animals
    string name;
    int age;
    function void eat();
        // Implement some generic behavior for eating
        $display("%s is eating", name);
    endfunction
    // Declare some methods that are specific to each subclass
    pure virtual function void make_sound();

    pure virtual function void move();
endclass

Usage Example

In this example, we are creating a virtual class vehicle which consists of data and method needed for the sub-class. We are creating various sub-classes from this abstract class and defining body for the change_gear() method. change_gear is a pure-virtual method and thus all sub-classes must have a definition of this method.

virtual class vechile;
    int no_of_seat, no_of_gears, no_of_wheels;
    string brnd_name, model_name;

    function void printf;
        $display("\nDetails of vechile:");
        $display("Brand name = ", brnd_name);
        $display("Model name = ", model_name);
        $display("No. of Gears = ", no_of_gears);
        $display("No. of Seats = ", no_of_seat);
        $display("No. of Wheels = ", no_of_wheels);
    endfunction

    pure virtual function void change_gear(); 

endclass //car

class car extends vechile;
    int gear_no;
    function new();
        no_of_gears = 5;
        no_of_seat = 4;
        no_of_wheels = 4;
    endfunction //new()

    virtual function void change_gear();
        if(gear_no<no_of_gears) begin
            gear_no++;
            $display("gear changed");
        end
        else
            $display("Max gear reached");
    endfunction
endclass //car extends vechile

class truck extends vechile;
    int gear_no;
    function new();
        no_of_gears = 12;
        no_of_seat = 2;
        no_of_wheels = 6;
    endfunction //new()

    function void change_gear();
        if(gear_no<no_of_gears) begin
            gear_no++;
            $display("gear changed");
        end
        else
            $display("Max gear reached");
    endfunction
endclass //car extends vechile

class scooter extends vechile;
    function new();
        no_of_gears = 0;
        no_of_seat = 2;
        no_of_wheels = 2;
    endfunction //new()

    function void change_gear();
        $display("Oooooops, no gear found");
    endfunction
endclass //scooter extends vechile

module abstract_class;
    car verna;
    truck v36;
    vechile v;
    scooter activa;
    initial begin
        verna = new();
        verna.brnd_name = "Hundai";
        verna.model_name = "Verna";
        verna.printf;
        //verna.change_gear();

        v36 = new();
        v36.brnd_name = "Sacala";
        v36.model_name = "v36";
        v36.printf;

        activa = new();
        activa.brnd_name = "Honda";
        activa.model_name = "Activa";
        activa.printf;

        $display("\nChanging car gear");
        verna.change_gear();

        $display("Changing truck gear");
        v36.change_gear();

        $display("Changing scooter gear");
        activa.change_gear();
        // v = new();
    end
endmodule
Try this code in EDA Playground
Output
# Details of vechile:
# Brand name = Hundai
# Model name = Verna
# No. of Gears =           5
# No. of Seats =           4
# No. of Wheels =           4
# 
# Details of vechile:
# Brand name = Sacala
# Model name = v36
# No. of Gears =          12
# No. of Seats =           2
# No. of Wheels =           6
# 
# Details of vechile:
# Brand name = Honda
# Model name = Activa
# No. of Gears =           0
# No. of Seats =           2
# No. of Wheels =           2
# 
# Changing car gear
# gear changed
# Changing truck gear
# gear changed
# Changing scooter gear
# Oooooops, no gear found

Conclusion

In this article we learnt about abstract/virtual classes and how it can make the code more robust and re-usable by abstracting the data. Also, virtual classes provide a skeleton over which classes can be built ensuring that all the derived classes contain certain data and methods.