15.Classes and oops - vineethkumarv/SystemVerilog_Course GitHub Wiki
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.
Properties are nothing but variables and methods are nothing but Functions/Tasks. 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
Code snippet:-
class home;
bit light;
int fan ;
string switch;
task open_electricity();
switch = "ON"
$display("switch is %s so electricity is open",switch);
endtask
endclass
From above code snippet class home contains light, fan, switch as properties of the class and open_electricity is a method of the class.
A handle is an indirect reference to a class object, like a pointer to an address in memory.
syntax:-
home h1;
In the above syntax home is a class and h1 is the variable 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;
bit light;
int fan ;
string switch;
task open_electricity();
switch = "ON";
$display("switch is %s so electricity is open",switch);
endtask
endclass
module tb;
home h1;
initial begin
if (h1==null)
$display("object is empty");
else
$display("object is not empty");
end
endmodule
output:-
In above code we create a handle h1 for class home and check it is null or not. On the below fig-1 we can see that it display object is empty. so, we can say that object was not created.
Fig- output of class handle
Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/class_handle/handle.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/class_handle/handle.log
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();
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:-
h1 = 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 creat 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;
bit light;
int fan ;
string switch;
task open_electricity();
switch = "ON";
$display("switch is %s so electricity is open",switch);
endtask
endclass
module tb;
home h1;
initial begin
h1=new();
if (h1==null)
$display("object is empty");
else
$display("object is not empty");
end
endmodule
output:-
On below fig-2 we can see that after create an object the memory to a class handle was created so it display object is not empty.
Fig- output of class object
Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/class_object/object.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/class_object/object.log
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:-
home_1.light = 1;
// access the class propertie
home_1.open_electricity
// access the class method
code snippet:-
class home;
bit light;
int fan;
string switch;
task open_electricity();
switch = "ON";
$display("switch is %0s so electricity is open",switch);
endtask
endclass
module check_electricity;
home h1;
initial begin
h1=new();
h1.light=1;
h1.fan=1;
h1.open_electricity;
$display("light is %0d(ON) and fan is also %0d(ON)",h1.light,h1.fan);
end
endmodule
On 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.display
output:-
In below fig-3 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.
Fig- output of class
Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/class/class.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/class/class.log
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 handle of the current class object. It shall be used only in non-static class methods.
syntax:-
this.<base_class_member>;
// It has to be used in derived class
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
endclass
module check_electricity;
base_class b1;
initial begin
b1=new();
b1.open_electricity;
$display("Outside class :- switch is %0s that's why fan is %s",b1.switch,b1.fan);
end
endmodule
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.
Fig- output of this keyword
Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/this_keyword/this.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/this_keyword/this.log
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
endclass
module check_electricity;
base_class b1;
initial begin
b1=new();
b1.open_electricity;
$display("Outside class :- switch is %0s that's why fan is %s",b1.switch,b1.fan);
end
endmodule
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.
Fig- output of without this keyword
Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/without_this_keyword/without_this.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/without_this_keyword/without_this.log
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.<base_class_member>; // It has to be used in derived class
code snippet:-
class base_class;
string fan,switch;
function void display();
switch="ON";
$write("switch is %s " ,switch);
endfunction
endclass
class sub_class extends base_class;
string fan="ON";
function void display();
super.display;
$write(" that's why fan is %s \n" ,fan);
endfunction
endclass
sub_class s1;
module super_ex;
initial begin
s1 =new();
s1.display;
end
endmodule
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 .
Fig- output of super keyword
Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/super_keyword/super.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/super_keyword/super.log
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
function void home::display();
string switch="OFF";
$display("The switch is %0s that's why fan is %0s",switch,fan);
endfunction
module extern_example;
home h;
initial begin
h=new();
h.display;
end
endmodule
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.
Fig- output of extern keyword
Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/extern_keyword/extern.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/extern_keyword/extern.log
To make class properties read-only, a const specifier is used. Since class objects are dynamic in nature, SystemVerilog provides two types of constants
1.Global constants
2.Instance constants
In both we use the 'const' keyword to declare the constant values.
Fig- type of constant class properties
During variable declaration, an initial value is assigned, such class properties known as global constants. The value of a variable can not be changed after the declaration of the variable
syntax:
class example;
int a;
const int b=2;
endclass
Code Snippet
class data;
string a;
const int b=1;//global constant
function new();
a="team";
endfunction
function void display();
$display("a=%0d,b=%0d",a,b);
endfunction
endclass
initial begin
p1=new();
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.
//-------------------------------------------------------
p2= new p1;//shallow copy
p2.display();
p2.ar.a="BJT";
//p2.ar.b=8;
p2.d=5;
p2.c="TEAM";
p1.display();
p2.display();
end
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 wan't to change the value of 'b' it throws errors.It won't take the values after it declares as constant.
Fig- output of global constant
Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/constant_variables/global_class/global_class.sv
Github logfile link https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/constant_variables/global_class/global_class.log
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:
class example;
int a;
const int b;
function new();
b=9;
endfunction
endclass
Code Snippet
class data;
const int a;
string b;
function new();
a=5;
b="bhavana";
endfunction
function void display();
$display("a=%0d,b=%0d",a,b);
endfunction
endclass
initial begin
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.dt.b="team";
t1.display();
t2= t1;//class_assignment
t2.d=7;
t2.display();
t2.c=8;
t2.d=0;
t2.dt.b="BJT";
t1.display();
t2.display();
end
Output
Fig- output of Instance Constants
Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/constant_variables/instance_class/instance_class.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/constant_variables/instance_class/instance_class.log
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.
syntax
class Vector #(parameter WIDTH=1);
bit [WIDTH-1:0] data;
endclass
Code Snippet
class mirafra #(parameter int branch=32,employes=32);
bit [branch-1:0]b1;
bit [employes-1:0]b2;
function new();
b1=13;
b2=25;
endfunction
endclass
module value;
manipal p1;
manipal p2;
initial begin
p1=new();
$display("contents of p1 before value changes");
p1.disp();
p2=p1;//classs-assignment
$display("contents of p2 before value changes");
p2.disp();
p1.m.b2=4;
p2.x="BJT";
p2.y=8;
$display("contents of p1 after value changes");
p1.disp();
$display("contents of p2 after value changes");
p2.disp();
end
endmodule
Output
Fig- output of parameterized by value
Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/parameterized_classes/parameter_value/parameter_value.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/parameterized_classes/parameter_value/parameter_value.log
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 int a=128,type team=string);//parameter declaration
bit [a-1:0]d;
team c;
function new();
d=8;
c="Mirafra";
endfunction
endclass
module test;
pack t1,t2;
initial begin
t2=new();
$display("contents of t2 before value changes");
t2.display();
t2.dt.d=3;
t2.dt.c="Teams";
t1=new t2;//shallow copy
$display("contents of t1 before value changes");
t1.display();
t1.y=8;
t2.x="BJT";
$display("contents of t1 after value changes");
t1.display();
$display("contents of t2 after value changes");
t2.display();
end
endmodule
Output
Fig- output of parameterized by datatype
Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/parameterized_classes/parameter_datatype/parameter_datatype.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/parameterized_classes/parameter_datatype/parameter_datatype.log
There are 3 types of Copying Objects
1.Class Assignment
2.Shallow copy
3.Deep copy
Fig- type of copy method
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
Fig- memory allocation for 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
module assignment;
Mirafra p1;
Mirafra p2;
initial begin
p1=new();
$display("contents of p1 before changes");
p1.display();
p2=p1;
$display("contents of p2 before changes");
p2.display();
p2.c="BJT";
p2.pk.a="Team3";
p2.pk.b=4;
p2.d=8;
$display("contents of p1 after changes");
p1.display();
$display("contents of p2 after changes");
p2.display();
end
endmodule
Output
Fig- output of class assignment
Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/copying_methods/class_assignment/class_assignment.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/copying_methods/class_assignment/class_assignment.log
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
Fig- 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
module shallow;
Mirafra p1;
Mirafra p2;
initial begin
p1 =new();
$display("contents of p1");
p1.display();
p2 =new p1;
$display("contents of p2");
p2.display();
p2.c="BJT";
p2.ar.a="Team3";
p2.ar.b=4;
$display("diplay contents of p1");
p1.display();
$display("diplay contents of p2");
p2.display();
end
endmodule
Output
Fig- output of shallow copy
Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/copying_methods/shallow_copy/shallow_copy.sv
Github logfile link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/copying_methods/shallow_copy/shallow_copy.log
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
Fig- memory allocation for 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
module deep;
branches p1;
branches p2;
initial begin
p1=new();
p2=new();
p2.deep(p1);//deep copy
$display("contents of branch p1 before changes");
p1.disp();
$display("contents of branch p2 before changes");
p2.disp();
//changing the values of p1 and p2
p1.pk.a="BJT";
p2.pk.a="Mirafra-Teams";
p1.c="Manipal";
p2.d=9;
p2.c="Hyderabad";
p1.d=8;
$display("contents of branches p1 after changes");
p1.disp();
$display("contents of branches p2 after changes");
p2.disp();
end
endmodule
Output
Fig- output of deep copy
Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/copying_methods/deep_copy/deep_copy.sv
Github logfile link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/copying_methods/deep_copy/deep_copy.log
SystemVerilog Methods declared with the keyword virtual are referred to as virtual methods.
Fig- type of virtual class member
Virtual Methods are two types
1.Virtual Functions
2.Virtual Tasks
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
virtual function void display();
$display("a=%0d",a);
$display("b=%0d",b);
endfunction
endclass
module example;
initial begin
p2=new();
p3=new();
pp0=p2;
pp1=new p3;
//p1.display();
pp0.display();
pp1.display();
//p3.e=7;
//pp1.display();
end
endmodule
Output
Fig- output of virtual function
Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/virtual_methods/virtual_function.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/virtual_methods/virtual_function.log
Task declared with a virtual keyword before the task keyword is referred to as virtual task
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
module over_riding;
BJT c;
initial begin
c=new();
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
endmodule
Output
Fig- output of overriding class member
Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/class_over_riding/over_riding_class.sv
Github logfile link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/class_over_riding/over_riding_class.log
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.
Fig- static class member
The static variable declared inside a class with static keyword shares a single memory location across all class instances.
syntax
static <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
function void disp();
$display("teams=%0d",teams);
endfunction
endclass
module static_properties;
Mirafra m[4];//declared array of m here
initial begin
foreach(m[i]) begin
m[i] = new();
$display("contents of teams");
m[i].disp();
end
end
endmodule
Output
Fig- output of static properties
Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/static/static_properties/static_properties.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/static/static_properties/static_properties.log
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.
syntax
static function <method_name>
Code Snippet
class Mirafra;
static int team ;
function new();
//incrementing team
team ++;
endfunction
//declaring static method
static function void disp();
$display("team=%0d",team);
endfunction
endclass
module static_method;
Mirafra m[3];//declaring array
initial begin
foreach(m[i])begin
m[i]=new;
end
$display("contents of team");
m[2].disp();
end
endmodule
Output
Fig- output of static method
Github Lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/static/static_methods/static_method.sv
Github Logfile Link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/static/static_methods/static_method.log
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.
Fig-1 Inheritance memory diagram
Inheritance is done by keyword 'extends' which allows access to all class members of parent class.
Fig-2 Functionality of extends keyword
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.
Fig- output of inheritance
Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/inheritance/inh.sv
Github logfile link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/inheritance/inh_op.log
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.
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.
Fig- output of polymorphism
Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/polymorphism/poly.sv
Github logfile linkhttps://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/polymorphism/poly_op.log
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
Fig- output of abstract
Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/abstraction/abstract_class/abstract.sv
Github logfie link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/abstraction/abstract_class/abstract_op.log
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.
Fig- output of pure virtual class
Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/abstraction/pure_virtual_function/pvf.sv
Github logfile link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/abstraction/pure_virtual_function/pvf_op.log
Encapsulation is the technique of hiding data the 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).
Fig- Type of encapsulation
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
class child extends parent;
function void disp();
endfunction
endclass:child
module encap();
parent p;
child c1;
int e;
initial begin
p = new();
c1 = new();
e = p.sum(1010,0101);
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.
Fig- output of local encapsulation
Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/encapsulation/local/local.sv
Github logfile link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/encapsulation/local/encap_op.log
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.
Fig- showing error
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;
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.
Fig- output of protected encapsulation
Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/encapsulation/protected/prot.sv
Github logfile link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/encapsulation/protected/prot_op.log
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.
Fig- output of public encapsulation
Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/encapsulation/public/pub.sv
Github logfile link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/classes/encapsulation/public/pub_op.log