Class#
Class is user define data type. Classes contains a set of “properties” and “methods” in it. Both properties and methods are treated as Members of the class.
generally,
- Class Properties are the variables inside a class and
- Class Methods are the Functions/Tasks inside a class.
Class declaration does not occupy any memory. we can define a class in systemverilog inside a module or outside of a module.
Class declaration syntax:
class class_name;
// declare class properties
// define class method (task and function)
endclass
Example:
class home;
bit light;
int fan ;
string switch;
task open_electricity();
switch = "ON"
$display("switch is %s so electricity is open",switch);
endtask
endclass
In the above example class home contains light, fan, switch as properties of the class and open_electricity is a method of the class.
Class Instance (or) Class handle#
A handle is an indirect reference to a class object, like a pointer to an address in memory.
syntax:
class_name class_handle;
In the below code home is a class and h1 is the handle of that class. It can hold the handle to an object of class home, but until assigned with class constructor (i.e, new function) it is always null. At this point, the class object does not exist yet.
code snippet:
class home; //define class
//declare class properties
bit light;
int fan ;
string switch;
//define class method(task/function)
task open_electricity();
switch = "ON";
$display("switch is %s so electricity is open",switch);
endtask:open_electricity
endclass:home
module tb;
home h1;
initial begin:BEGIN_I
$display("Let's declare handle");
$display("Check wheather the object is created or not");
if (h1==null)
$display("object is empty");
else
$display("object is not empty");
end:BEGIN_I
endmodule:tb
output:
- In above code we create a handle h1 for class home and check it is null or not.
- In the below Fig-2 we can see that it display object is empty. so, we can say that object was not created.
Fig-2: output of class handle
Class constructor#
The “new()” function is called as class constructor. On calling “new()” function it allocates the memory and returns the address to the class handle. Constructing an object allocate the space in the memory needed to hold the properties of an object.
syntax:-
class_handle_name = new();
class object:-#
An object is an instance of that class. An object is used by first declaring a variable of that class type (that holds an object handle) and then creating an object of that class (using the new() function) and assigning it to the variable.
In simple way if we create an object then we assign a memory for that handle of the class.
syntax:-
class_handle_name = new();
The above statement will create an object and assign to handle h1. We can create a object in either 2 step or 1 step also.
There are 2 ways to create an object:-
1. Two step process:
step - 1: home h1;
step - 2: h1 = new();
2. One step process:
step - 1: home h1 = new();
code snippet:-
class home; //define class
//declare class properties
bit light;
int fan ;
string switch;
//define class method(task/function)
task open_electricity();
switch = "ON";
$display("switch is %s so electricity is open",switch);
endtask:open_electricity
endclass:home
module tb;
home h1; //creating handle
initial begin:BEGIN_I
$display("Using new() method we can create an object");
h1=new();
if (h1==null)
$display("object is empty");
else
$display("object is not empty");
end:BEGIN_I
endmodule:tb
output:-
On below fig-3 we can see that after create an object the memory to a class handle was created so it display object is not empty.
Accessing class properties and methods
With the help of ’ . ’ we can access class properties and method. Class properties and methods can be accessed by using object names followed by property or method name.
syntax:-
<class_handle>.<class_properties> = 1;
<class_handle>.<class_method>;
code snippet:-
class home; //define class
//declare class properties
bit light;
int fan;
string switch;
//define class method(task/function)
task open_electricity();
switch = "ON";
$display("\t switch is %0s so electricity is open",switch);
endtask:open_electricity
endclass:home
module check_electricity;
initial begin:BEGIN_I
home h1; //creating handle
h1=new(); //Creating Object for the Handle
h1.light=1; // access the properties
h1.fan=1;
$display("");
h1.open_electricity; //access the method
$display("\t light is %0d(ON) and fan is also %0d(ON)",h1.light,h1.fan);
$display("");
end:BEGIN_I
endmodule:check_electricity
On the above code home is a class. They have properties and method. Then here create a handle h1 for class home and the create a object using new() function the access the class properties by h1.light and h1.fan and access the class method by h1.open_electricity.
output:-
In below fig-4 we see that access the properties and give the value of light = 1 and fan = 1 it print the light is 1 and fan is also 1.
This keyword#
The “this” keyword resolves the ambiguity of a compiler when class properties and arguments passed to class methods are the same. In simple terms, “this” keyword is a used to call the value of class properties inside the class method.
syntax:-
this.class_property;
code snippet:-
class base_class;
string fan ="OFF" ;
string switch="OFF";
function void open_electricity();
string fan="ON";
string switch="ON";
this.fan=fan;
this.switch=switch;
$display("Inside class method :- switch is %0s that's why fan is %0s",switch,fan);
endfunction:open_electricity
endclass:base_class
module check_electricity;
base_class b1;
initial begin:BEGIN_I
b1=new();
b1.open_electricity;
$display("Outside class :- switch is %0s that's why fan is %s",b1.switch,b1.fan);
end:BEGIN_I
endmodule:check_electricity
From above example we can see that, fan & switch is class properties and argument of function is same and we assign fan to fan but using this keyword it is differentiate.
output:-
In this code we mention the this keyword before the fan and switch then he print the value switch is ON and fan is also ON inside the class as well as outside the class.
what happens if do not use the “this” keyword in the above code ?
If did not mention the this keyword before assigning the fan to fan or switch to switch then inside the method the it display the overwrite value of properties but outside the class it display the default or given value of properties.
code snippet:-
class base_class;
string fan ="OFF" ;
string switch="OFF";
function void open_electricity();
string fan="ON";
string switch="ON";
fan=fan;
switch=switch;
$display("Inside class method :- switch is %0s that's why fan is %0s",switch,fan);
endfunction:open_electricity
endclass:base_class
module check_electricity;
base_class b1;
initial begin:BEGIN_I
b1=new();
b1.open_electricity;
$display("Outside class :- switch is %0s that's why fan is %s",b1.switch,b1.fan);
end:BEGIN_I
endmodule:check_electricity
output:-
On the below fig we can see that if we did not mention the this keyword then it display inside method switch is ON that’s why fan is ON but outside the class it display the switch is OFF that’s why fan is OFF.
super keyword#
The “super” keyword is used in a child or derived class to refer to class members of parent class. If the method of the parent class is overridden in the child class, then using the “super” keyword parent class method can be accessed from the child class if both class members have the same name for class properties and methods.
syntax:-
super.class_method;
code snippet:-
class base_class;
string fan,switch; //properties of class
function void display(); //method of class
switch="ON";
$display("Here using super keyword we can get both display() methods");
$write("switch is %s " ,switch);
endfunction:display
endclass:base_class
class sub_class extends base_class;
string fan="ON";
function void display();
super.display;
$write("that's why fan is %s \n" ,fan);
endfunction:display
endclass:sub_class
sub_class s1; //creating handle for class
module super_example;
initial begin:BEGIN_I
s1 =new(); //create an object
s1.display(); //access the sub_class method
end:BEGIN_I
endmodule:super_example
output:-
On below fig we can see that it display the parent class method and child class method by using the child class handle so it display the switch is ON that’s why fan is also ON and it display the single line because here use the $write .
scope resolution#
We have a scope resolution operator in classes which is used to access the class properties and methods outside of the class using class name and followed by symbol :: and then the propeties and methods of a class.
extern keyword#
An “extern” keyword is used for methods which provides a facility for class methods to define them outside of the class body.
If the method definition is lengthy (many lines of code inside a method), the extern method provides better readability and cleaner implementation of the class.
An extern keyword is used for method declaration and a class name with a scope resolution operator is used for method definition.
Note:-
- Method definition and declaration should have the same number of argument lists, data types, and argument names.
- For the extern function return type should be the same if used.
syntax:-
Step - 1: method declaration - extern indicates out-of-body declaration
extern function function_name;
extern task task_name;
Step - 2: method implementation outside class body using scope resolution operator
function class_name::function_name;
task class_name::task_name;
code snippet:-
class home;
string switch;
string fan = "OFF";
extern function void display();
endclass:home
function void home::display();
string switch="OFF";
$display("The switch is %0s that's why fan is %0s",fan,switch);
endfunction:display
module extern_example;
home h;
initial begin:BEGIN_I
h=new();
$display("Using extern keyword we are creating prototype for our function in the class");
$display("Then we are declaring the function outside the class");
h.display;
end:BEGIN_I
endmodule:extern_example
output:-
Here class method is define the outside the class but after access it by using class handle it display the switch is OFF that’s why fan is also OFF.
Chaining Constructs#
- The function new() is called a class constructor. This constructor is used to create objects for class handle. Creating an object means we are allocating some memory to that class.
- Chaining constructor means when we are extending the child class from parent class then all the properties and methods from parent class will be comming into child class.
- you can use same methods in both parent and child class then the child class will overwrite the methods of parent class.
- But in the case of new() function you can use the same new() in both parent and child class but there is no point of overwriting the parent class new().
- By default the simulator will call the super.new() statement inside the extended class this is only happening in new() method.
code snippet:
class parent;
int a;
function new();
a = 1;
endfunction
extern function void display();
endclass:parent
class child extends parent;
int b;
function new();
b = 2;
endfunction
extern function void display();
endclass:child
function void parent::display();
$display("a = %0d",a);
endfunction
function void child::display();
super.display(); // Super is a keyword used to get the method of same name from extended class.
$display("b = %0d",b);
endfunction
module basic_chain_construct();
child c;
initial begin
c = new;
c.display();
end
endmodule:basic_chain_construct
output:
Here in the above code we are trying to create 2 classes which has one new() and one display() methods in it. so we are not calling super.new() in child constructor.
Even though we are getting both the values of a and b which we set in two different constructers. so, we can say that an internal super.new() was there inside a constructor.
Constant class properties#
To make class properties read-only, a const specifier is used. Since class objects are dynamic in nature, Systemverilog provides two types of constants. They are
1.Global constants
2.Instance constants
In both we use the ‘const’ keyword to declare the constant values.
1.Global Constants#
During variable declaration, an initial value is assigned, such class properties known as global constants. The value of a variable can be changed inside the class constructor even after declaration. It cannot be override the value of constant variable in any other functions or in any module.
syntax:-
const int b=2;
Code Snippet
class data;
string a;
const int b=1;//global constant
function new();
a="team";
endfunction:new
function void display();
$display("a=%0d,b=%0d",a,b);
endfunction:display
endclass:data
module global_class;
data p1;
initial begin:BEGIN_I
p1=new();
$display("");
p1.display();
// p1.b=2;// invalid usage of b
//-------------------------------------------------------
//Here we assigned the b value in class properties using 'const' again we
//should not assign the value for 'b' even though we declared the values it throws the
//errors.
//--------------------------------------------------------
$display("");
end:BEGIN_I
endmodule:global_class
Output:-
In the below figure you can see that value of b is ‘1’ only because we declared it as a constant value. Even if we want to change the value of ‘b’ it throws errors. It won’t take the values after it declares as constant.
2.Instance Constants#
During variable declaration, an initial value is not assigned, such class properties are known as instance constants. An instance constant allows a user to assign value in run time only once in the class constructor.
syntax:-const int b;
function new();
b=9;
endfunction
Code Snippet:-
class data;
const int a;
string b;
function new();
a=5;
b="bhavana";
endfunction:new
function void display();
$display("a=%0d,b=%0d",a,b);
endfunction:display
endclass:data
module instance_class;
data t1;
initial begin:BEGIN_I
t1=new();
//t1.a=2;
//-------------------------------------------------------
// Here we should not assign value for the 'a' because
// we declared the 'a' as constant variable.
// so if we assign any value to the 'a' it throws errors
// it won't take any value eventhough we declared.
//-------------------------------------------------------
t1.b="bjt";
$display("");
t1.display();
$display("");
end:BEGIN_I
endmodule:instance_class
Output:-
In below figure we can a value is constant because here we declared it as constant and in instance constant we can declare value only in the constructor.
parameterized classes#
Parameterized classes are useful when the same class needs to be instantiated differently. The default parameter can be set in the class definition. These parameters can be overridden when it is instantiated.
The parameter value can be used to define a set of attributes in class. default values can be overridden by passing a new set of parameters during instantiation this is called parameter overriding.
Parameterized by value#
syntax:-
class Vector #(parameter WIDTH=1);
bit [WIDTH-1:0] data;
endclass
Code Snippet:-
class mirafra #(parameter branch,employes);
bit [branch-1:0]b1;
bit [employes-1:0]b2;
function new();
b1=13;
b2=9;
endfunction
function void disp();
$display("b1=%0d,b2=%0d",b1,b2);
endfunction
endclass:mirafra
mirafra#(3,2) m;
module value;
initial begin:BEGIN_I
m=new();
$display("");
$display("contents of m ");
m.disp();
$display("");
end:BEGIN_I
endmodule:value
Output
In the below figure we can see the output of paramerized class by value where we consider int parameters branch and employess as the width of 32 bit.
Parameterized by type(datatype)#
Datatype is parameterized in this case and can also be over ridden in instantiated.
syntax
class Stack #(parameter type T=int);
T items[64], idx=0;
function void push(input T val);
function T pop();
endclass
Code Snippet
class data #(parameter a,type team=string);//parameter declaration
bit [a-1:0]d;
team c;
function new();
d=20;
c="Mirafra";
endfunction
function void disp();
$display("d=%0d,c=%0s",d,c);
endfunction
endclass:data
data#(4) p1;
module test;
initial begin:BEGIN_I
p1=new();
$display("");
$display("contents of p1");
p1.disp();
$display("");
end:BEGIN_I
endmodule:test
Output:-
In the below figure we can see that output of parameter by datatype as we considered T as the string in the paraenter.
Copying Objects#
There are 3 types of Copying Objects
1.Class Assignment
2.Shallow copy
3.Deep copy
1.Class Assignment#
With the class assignment both the original and copy class will point to same memory location. Any update to a variable from either of the classes will have impact on the other class.
syntax
a=new();
b=a;
Memory Allocation of Class Assignment
In the above memory allocation we have say that p1 and p2 are sharing same memory and if we change one variable in one class(p1) it will be updated in other class(p2) also.
Code Snippet
class Mirafra;
string c;
int d;
function new();
c="team";
d=4;
endfunction:new
function void display();
$display("\t c=%0s,\t d=%0d",,c,d);
endfunction:display
endclass:Mirafra
module assignment;
Mirafra p1;
Mirafra p2;
initial begin:BEGIN_I
p1=new();
$display("contents of p1 before changes");
p1.display();
p2=p1;
$display("contents of p2 before changes");
p2.display();
p2.c="BJT";
p2.d=8;
$display("contents of p1 after changes");
p1.display();
$display("contents of p2 after changes");
p2.display();
end:BEGIN_I
endmodule:assignment
Output
In the below figure we can see that class assigment operation as we know class assignment has same memory location so first we can the copied objects so if we want change the values if we chnage one value in handle that changes reflect in other handle also
2.Shallow Copy#
When a class is shallow copied to another class, all the variables of the original class is copied to the copied class, with an exception of objects inside the class. In case the original class has a class object defined inside, that object would NOT be copied, only the handle for the object will be copied.This means the memory location of the object remain same. so if the object is updated from the copied class, this object value will be updated also for the original class.but if variable of copied class is update, it will NOT update the variable of the original class.
syntax
a=new();
b=new a;
Memory Allocation for Shallow Copy
In the above figure we can that memory allocation in p1 and p2 is same but variables change is updated only in the handle variables.
code snippet
class Mirafra;
string c;
int d;
function new();
c = "Teams";
d = 8;
endfunction:new
function void display();
$display("\t c=%0s,\t d=%0d",c,d);
endfunction:display
endclass:Mirafra
module shallow;
Mirafra p1;
Mirafra p2;
initial begin:BEGIN_I
p1 =new();
$display("contents of p1");
p1.display();
p2 =new p1;
$display("contents of p2");
p2.display();
p2.c="place";
$display("diplay contents of p1");
p1.display();
$display("diplay contents of p2");
p2.display();
end:BEGIN_I
endmodule:shallow
Output:-
In the below figure we can see the shallow copy as we know it has same memory location but share the memory by splitting and first valkues are copied if we want changes the values then only is updated as we see here a and b is updated but c is updated in particular handle.
3.Deep Copy#
SystemVerilog deep copy copies all the class members and its nested class members. That means it will copy all the members to a different memory location including the object inside the class. Any change in members of one of the class will have NO impact on another class member.
syntax
a=new();
b=new();
b.copy(a);
Memory Allocation of Deep Copy
In the above figure we can see p1 and p2 has different memories so if change or update any varibale only that class is updated because of different memory locations.
Code snippet
class branches;
string c;
int d;
function new();
c="Banglore";
d=1;
endfunction:new
function void disp();
$display("\t c=%0d,\t d=%0d",c,d);
endfunction:disp
function void deep(branches copy);//copy
this.c=copy.c;
this.d=copy.d;
endfunction:deep
endclass:branches
module deep;
branches p1;
branches p2;
initial begin:BEGIN_I
p1=new();
p2=new();
p2.deep(p1);//deep copy
$display("");
$display("contents of branch p1 before changes");
p1.disp();
$display("contents of branch p2 before changes");
p2.disp();
p1.c="Manipal";
p2.c="Hyderabad";
$display("contents of branches p1 after changes");
p1.disp();
$display("contents of branches p2 after changes");
p2.disp();
$display("");
end:BEGIN_I
endmodule:deep
Output:-
In the below figure we can se that it has different memory locations but we can copy the values using copymethod and if want change the values the value updation also occurs in the particular handle which we considered.
Virtual Methods#
SystemVerilog Methods declared with the keyword virtual are referred to as virtual methods.
Virtual Methods are two types
1.Virtual Functions
2.Virtual Tasks
Virtual Function#
A function declared with a virtual keyword before the function keyword is referred to as virtual Function, we use the virtual in base(parent)class function then only child class gets executed.
Code Snippet
class packet;
string a;
int b;
function new();
a="Team";
b=4;
endfunction:new
virtual function void display();
$display("a=%0d",a);
$display("b=%0d",b);
endfunction:display
endclass:packet
class pack extends packet;
string c;
int d;
function new();
c="BJT";
d=8;
endfunction:new
function void display();
// super.display();
$display("c = %0d",c);
$display("d = %0d",d);
endfunction:display
endclass:pack
class pack1 extends packet;
string e;
function new();
e="Manipal";
endfunction:new
function void display();
$display("e = %0d",e);
endfunction:display
endclass:pack1
packet pp0,pp1;
pack p2;
pack1 p3;
module virt_fun;
initial begin:BEGIN_I
p2=new();
p3=new();
pp0=p2;
pp1=new p3;
pp0.display();
pp1.display();
end:BEGIN_I
endmodule:virt_fun
Output:-
In the below figure we can see the contents of child class 1 and 2 as we declared parent class function as virtual function so it give the values of child classes.
Virtual Task#
Task declared with a virtual keyword before the task keyword is referred to as virtual task
code snippet
class packet;
string a;
int b;
virtual task display();
a="Team";
b=4;
$display("a=%0s",a);
$display("b=%0d",b);
endtask
endclass//class 1
//-----class 2-------
class pack extends packet;
string c;
int d;
task display();
c="BJT";
d=8;
$display("c=%0s",c);
$display("d=%0d",d);
endtask
endclass//class 2
packet p1;
pack p2;
module virtual_task;
initial begin:BEGIN_I
p2=new();
p1=p2;
$display("contents of pp0");
p1.display();
end:BEGIN_I
endmodule:virtual_task
Output
In the below figure we ca see that contents of child class as we declared the parent class methods as the virtual task it gives the child class contents.
Over-riding Class Members#
Base class or parent class properties and methods can be overridden in the child class or extended class by defining the class properties and methods with the same name as parent class in the child class will override the class members.
To override a method means that given a base class with a method, we can define a subclass which extends from that base class and then provide a new definition for the given method. By default, the subclass inherits the base class implementation of the method but should the programmer decide to change that definition by overriding it - simply listing a new version of that method, then the new version of the method will be used instead of the parent’s.
Code Snippet
//parentclass
class Mirafra;
string place;
int members;
int teams;
function new();
place="manipal";
members=13;
endfunction:new
function void display();
$display("place = %0d,\t members= %0d",place,members);
endfunction:display
endclass:Mirafra
//child-1
class Teams extends Mirafra;
string Teams;
int members;
function new();
Teams="mirafra-teams";
members=25;
endfunction:new
function void display();
$display("Teams=%0d,\t mem=%0d",Teams,members);
endfunction:display
endclass:Teams
//child-2
class bjt extends Mirafra;
string Team;
int members;
string place;
function new();
Team ="Team3";
members=4;
endfunction:new
function void display();
$display("Team=%0s,\t members=%0d,\t place=%0s",Team,members,place);
endfunction:display
endclass:bjt
module over_riding;
bjt c;
initial begin:BEGIN_I
c=new();
$display("contents before over-riding");
c.display();
c.place = "mirafra";
c.Team="BJT";//over-riding parent-class members
c.members = 8;
c.place="Manipal";
$display("contents after over-riding");
c.display();
end:BEGIN_I
endmodule:over_riding
Output:-
In the below figure we can the class over_riding members,here we are just accessing the parent class using the child class handle but parents and child should have same class peroperties here if we see we can place which in the parent class.
Static Properties and Methods#
Class members can be created with the keyword static. class members with the keyword static are called as static class members. the class can have static properties and static methods (functions and tasks). a single copy of static variables is shared across multiple instances.
Static Properties#
The static variable declared inside a class with static keyword shares a single memory location across all class instances.
syntaxstatic <data_type> <variable_name>
Code Snippet
class Mirafra;
byte teams;
//declare the static property
static byte BJT;
function new();
//incrementing the BJT
BJT++;
//Assigning static byte to byte
teams=BJT;
endfunction:new
function void disp();
$display("teams=%0d",teams);
endfunction:disp
endclass:Mirafra
module static_properties;
Mirafra m[4];//declared array of m here
initial begin:BEGIN_I
foreach(m[i]) begin:BEGIN_LOOP
m[i] = new();
$display("contents of teams");
m[i].disp();
end:BEGIN_LOOP
end:BEGIN_I
endmodule:static_properties
Output
In the below figure we see that when for loop is operation is done the value of contenyts of teams is updated because here we considered BJT as the static property and we assigned that BJT to team so team value is updated.
Static Methods#
Static methods are the same as static variables that also follow class access rules and scope.
Static functions and tasks can not be virtual They can access only static properties (static members) of a class. Accessing non-static members leads to compilation errors as it is illegal to use. But non-static functions or tasks can access static variables. Both static methods and static members in a class can be accessed without creating an object.
syntaxstatic function <method_name>
Code Snippet
class Mirafra;
static int team ;
function new();
//incrementing team
team ++;
endfunction:new
//declaring static method
static function void disp();
$display("\t team=%0d",team);
endfunction:disp
endclass:Mirafra
module static_method;
Mirafra m[3];//declaring array
initial begin:BEGIN_I
$display("");
foreach(m[i])begin:BEGIN_LOOP
m[i]=new;
end:BEGIN_LOOP
$display("\t contents of team");
m[2].disp();
$display("");
end:BEGIN_I
endmodule:static_method
Output In the below figure we see the static methods as we declared function as static function and in this static function only the static properties are accessible so as the for loop iteration is done the value gets updated each time so here we can see the teams is ‘3’.
Inheritance#
Inheritance is a mechanism which allows child class to inherit the properties of base-class. Objects of child class will have access to attributes and methods of parent class. If child class inherits parent class, then parent class is called super-class and child class is called subclass.
Inheritance is done by keyword ’extends’ which allows access to all class members of parent class.
From the above fig-2, we can clearly see that all the instantiation steps are reduced down to one single keyword ’extends’ which allows to have all the class members of parent to the child.
code snippet:-
class A;
int a = 5;
function void disp();
$display("1.Value of a = %0d",a);
endfunction:disp
endclass:A
class B extends A;
int a = 6;
function void display();
$display("2.Value of a = %0d",a);
endfunction:display
endclass:B
module inh_sam();
B b1;
initial begin
b1 = new;
b1.a = 10;
b1.disp();
b1.display();
end
endmodule:inh_sam
Output:-
In the code we can see that initially in the class A(parent) we have initialized the value of ‘a’ with 5 and in class B(child) we are intializing the value of 6 to ‘a’. In the module we are creating handle ‘b1’only for the child class B and we are intialising it with value 10. When we access the parent class method with the help of the child class handle it will display a = 5 and when we access the child class method with the help of the child class handle it will overwrite the value of a=6 with a=10 and displays the output. So we are able to access both the methods just by child class B handle.
Polymorphism#
Polymorphism allows to access the sub-class methods using super-class objects. Any subclass object can be assigned to super-class object. In polymorphism, same handle (or) methods take different forms. It is important to know that all the method names should be same for both parent and child class, also if we don’t use virtual for methods in parent class then it will only access parent class methods.
code snippet:-
class parent;
int a;
int b;
virtual function void display();
a = 1;
b = 2;
$display("This is parent class");
$display("a = %0d, b= %0d",a,b);
endfunction:display
endclass:parent
class child1 extends parent;
int c,d,e;
function void display();
a = 3;
b = 4;
e = a+b;
$display("This is child class");
$display("a = %0d, b = %0d,e = %0d",a,b,e);
endfunction:display
endclass:child1
class child2 extends parent;
int f;
function void display();
f= a*b;
$display("f = %0d",f);
endfunction:display
endclass:child2
module poly_ex();
parent p1[1:0];
child1 c;
child2 c2;
initial begin
c = new();
p1[0] = c;
p1[1] = new();
p1[0].display();
p1[1].display();
end
endmodule:poly_ex
Output:-
In this code we can see that the methods of both parent class and child classes are same. So the child class methods will overwrite parent class methods. So we are assigning the child handle ‘c’ is assigned to parent handle p[0]. So with the help of the p[0] handle we are able to access the child class method. Since it is display function it will print a=3,b=4,e=7. But when we are accessing the class method with the help of handle p[1] it will display the parent class method, that is a =1,b=2 because we did not assign child class handle c to parent class handle p[1]. So here the parent class handle is taking many forms to access child class methods which indeed called poly which is many forms in the polymorphism.
Abstract/Virtual class#
Abstract class is a virtual class which cannot be instantiated directly in the program(in other words an object of a virtual/abstract class cannot be created). If you try doing so it will throw compile time error. They will be used as a base class to inherit any no of classes. We generally use abstract class to define a prototype in advance, that means an abstract class provides a template for a set of derived classes. So you know you have a basic set of methods/properties that already exist, that makes it simpler for you to focus on the new intent for which you are creating this derived class.
code snippet:-
virtual class A;
int a = 5;
function void disp();
$display("1.Value of a = %0d",a);
endfunction:disp
endclass:A
class B extends A;
int a = 6;
function void display();
$display("2.Value of a = %0d",a);
endfunction:display
endclass:B
module abstract_ex();
B b1;
initial begin
b1 = new;
b1.a = 10;
b1.disp();
b1.display();
end
endmodule:abstract_ex
Output:-
In the code we can see that initially in the class A(parent) we have initialized the value of ‘a’ with 5 and in class B(child) we are intializing the value of 6 to ‘a’.
In the module we are creating handle ‘b1’only for the child class B and we are intialising it with value 10. When we access the parent class method with the help of the child class handle it will display a = 5 and when we access the child class method with the help of the child class handle it will overwrite the value of a=6 with a=10 and displays the output. So we are able to access both the methods just by child class B handle
Pure virtual method#
A virtual method inside an abstract class can be declared by keyword ‘pure’ and is called pure virtual method. The class will automatically consider it as abstract class if any pure virtual method is used. It should be only added in the base class. In the base class we are not allowed to add any function definition to the pure virtual function. It is important to know that all the derived classes of a base class with pure virtual methods should have implementation of all pure virtual methods individually.
code snippet:-
virtual class A;
int a,b,c;
pure virtual function void disp();
pure virtual task sum();
endclass:A
class B extends A;
virtual function void disp();
a =10;
$display("1.Value of a = %0d, b = %0d, c = %0d",a,b,c);
endfunction:disp
virtual task sum();
c = a+b;
$display("2.Value of a = %0d, b = %0d, c = %0d",a,b,c);
endtask:sum
endclass:B
module pure_vir_fun_ex();
B b1;
initial begin
b1 = new;
b1.disp();
b1.b = 35;
b1.sum;
end
endmodule:pure_vir_fun_ex
Output:- In the code we can see that initially in a virtual class we will be declaring two methods function void disp and task sum which we are supposed to be used in our code without defining it. When we inherit class A to B it is important that both the methods(function void disp and task sum) are supposed to be used in the child class B. In the similar fashion if there are more child classes each class is supposed to have both the methods declared individually or else it will throw an error. So in class B we are assiging value of a=10, but since we are not declaring the values of b=0,c=0. In task method we are adding both the values of a and b but we are passing the value of b =35, so we will get a = 10,b=35,c=45.
Encapsulation#
Encapsulation is the technique of hiding data within the class and making it available only through the methods. It seals the data and allows only access to trusted users(i.e., by the methods of the class).
Note:- It can be applicable for methods as well.
Local#
A member declared as ’local’ is accessible only to the methods of the same class and will not be able to access by child class.
code snippet:-
class parent;
bit [3:0] a,b;
local bit[5:0] c;
local int d = 5;
function int sum(bit[4:0]val1,val2);
c = val1 + val2;
return c;
endfunction:sum
function void display();
$display("sum = %0d",c);
$display("d = %0d",d);
endfunction:display
endclass:parent
module encap();
parent p;
int e;
initial begin
p = new();
e = p.sum(1010,101);
p.display();
end
endmodule:encap
Output:-
In the code we can see that the local variable c,d declared inside the class is being accessed inside the class. As it is allowed, no compilation error is observed.
Errors expected if we access local variable by child class#
code snippet:-
class parent;
bit [3:0] a,b;
local bit[5:0] c;
local int d = 5;
function int sum(bit[4:0]val1,val2);
c = val1 + val2;
return c;
endfunction:sum
function void display();
$display("sum = %0d",c);
$display("d = %0d",d);
endfunction:display
endclass:parent
class child extends parent;
function void disp();
display("d = %0d",d);
endfunction
endclass:child
module encap();
parent p;
child c1;
int e;
initial begin
p = new();
c1 = new();
e = p.sum(1010,0101);
p.display();
p.c = 5'b10;
p.display();
c1.disp();
end
endmodule:encap
Output:-
In the code we can see that the local variable c,d declared inside the class is trying to access from outside the class by using object handle of child class as well as parent handle p in module block. As the variable is declared as local, which leads to a compilation error.
Protected#
Sometimes there will be necessity to access the members of parent class by the child class. This can be done by the keyword ‘protected’. By using protected, all the child classes will get the access to the base class members which were data protected.
code snippet:-
class parent;
bit [3:0] a,b;
protected bit[5:0] c;
protected int d = 5;
function int sum(bit[4:0]val1,val2);
c = val1 + val2;
return c;
endfunction:sum
function void display();
$display("sum = %0d",c);
$display("1.d = %0d",d);
endfunction:display
endclass:parent
class child extends parent;
function void disp();
$display("2.d = %0d",d);
endfunction
endclass:child
module prot();
parent p;
child c1;
int e;
initial begin
p = new();
c1 = new();
e = p.sum(1010,0101);
p.display();
// p.d = 10; //Cannot access local/protected member "p.d"
c1.disp();
end
endmodule:prot
Output:-
In the code we can see that the protected variable c,d declared inside the class is being accessed inside the class. But here since it is protected inheritance is also allowed as when we try accessing in child class it will not throw an error. But we try accessing the values c,d in module block it will throw an error.
Public#
By default if we does not define any attributes with keywords ’local’ and ‘protected’, then by default it is ‘public’. It provides full access to all attributes and methods to child classes.
code snippet:-
class parent;
bit [3:0] a,b;
bit[5:0] c;
int d = 5;
function int sum(bit[4:0]val1,val2);
c = val1 + val2;
return c;
endfunction:sum
function void display();
$display("sum = %0d",c);
$display("1.d = %0d",d);
endfunction:display
endclass:parent
class child extends parent;
function void disp();
$display("2.d = %0d",d);
endfunction
endclass:child
module pub();
parent p;
child c1;
int e;
initial begin
p = new();
c1 = new();
e = p.sum(1010,0101);
p.display();
c1.d = 10;
c1.disp();
end
endmodule:pub
Output:- In the code we can see that the variable c,d declared inside the class which is by default public is being accessed inside the class.Here inheritance is also allowed as when we try accessing in child class it will not throw an error. When we try accessing the values c,d in module block it will not throw an error since it will have full access to all the attributes.