Virtual Class in System Verilog
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
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.
Abstract classes are defined using
virtual keyword. This is like virtual functions but in this case, we use virtual keyword with class.
virtual class <class_name>; <class body> endclass
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.
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.
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
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.
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.
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.
pure virtual <method_name>();
We cannot have a method body defined while using pure virtual methods. Doing so will lead to compile time errors.
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
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 is a pure-virtual method and thus all sub-classes must have a definition of this method.
Try this code in EDA Playground
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
# 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
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.