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
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 PlaygroundOutput
# 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.