15.Classes and oops - vineethkumarv/SystemVerilog_Course GitHub Wiki

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

Class Instance/ Class handle:-

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.

handle drawio

                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

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:-

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.

object drawio

               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.

class drawio

              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

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

this drawio

                  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.

without_this drawio

          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

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

super drawio

              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

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

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.

extern drawio

             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

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

1.Global constants
2.Instance constants

In both we use the 'const' keyword to declare the constant values.

constant-class-image

             Fig-  type of constant class properties  

1.Global Constants

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.

Untitled Diagram drawio (9)

         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

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:
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

Untitled Diagram drawio (11)

            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

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 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

parameter-value

              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

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 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

parameter-type

          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

Copying Objects

There are 3 types of Copying Objects

1.Class Assignment
2.Shallow copy
3.Deep copy

Untitled Diagram drawio (16)

          Fig-       type of copy method

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

Untitled Diagram drawio (23)

           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

class-assignment

               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

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

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

Untitled Diagram drawio (18)

          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

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

Deepcopy

            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

Untitled Diagram drawio (17)

             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

Virtual Methods

SystemVerilog Methods declared with the keyword virtual are referred to as virtual methods.

virtual

           Fig-    type of virtual class member  

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

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

virtual-function

         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

Virtual Task

Task declared with a virtual keyword before the task keyword is referred to as virtual task

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

 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

Untitled Diagram drawio (24)

                    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

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.

Untitled Diagram drawio (25)

                        Fig-  static class member  

Static Properties

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

static-properties

               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

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

static-method

                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

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-1

      Fig-1 Inheritance memory diagram

Inheritance is done by keyword 'extends' which allows access to all class members of parent class.

Inheritance-2new-Page-2 (1)

      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.

inh_output_new-Page-3

      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

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.

poly-output new-Page-2

      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/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

abstract-output new

      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

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.

pvf_new

      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

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).

Encap

      Fig-   Type of encapsulation

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

  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.

local_errors_new-Page-2

      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

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.

local_errors_new drawio

      Fig- showing 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;
    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.

protected_new

      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

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.

pub_new

      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

⚠️ **GitHub.com Fallback** ⚠️