类和面向对象

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.

Untitled Diagram drawio (37)

                Fig-1: All variations of a class.  

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.

Cheat sheet for classes:#

classes and oopsDescription
1.ClassA class is a user-defined data type that includes data (class properties), functions and tasks that operate on data
2.Class handleAn object handle is nothing but a pointer for an object.
3.Class constructorA constructor simply a method to create a new object of particular class datatype
4.Class objectClass properties and methods can be accessed only after creating the object
5.This keywordthe thiskeyword used to refer properties or methods of current instance
6.Super keywordthe super keyword is used from within the child-class to refer to properties and methods of parent-class
7.Extern keywordAn extern keyword is used for methods which provides a facility for class methods to define them outside of the class body
8.Constant class propertiesTo make class properties read-only, a const specifier is used
9.Copying objectsCopying the objects according to the memory locations
10.Parameterized classesparameters are like constants that are local
11.Virtual methodsVirtual method functionality is set at run‐time, which allows extended class handles to be assigned to base class handles
12.Static properties and methodsclass members with the keyword static are called as static class members
13.Over riding class membersDefining the class properties and methods with the same name as parent class in the child class will override the class members.
14.InheritanceInheritance is an OOP concept that allows the user to create classes that are built upon existing classes
15.PolymorphismThe ability for the same code to behave differently depending on the kind of Object with which it is dealing
16.EncapsulationThe technique of hiding the data within the class and making it available only through the methods
17.Abstractionclass declared with the keyword virtual is referred to as an abstract 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.

class_handle

Fig-2: output of class handle

Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/class_handle/handle.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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:-

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.

class_object

      Fig-3: output of class object  

Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/class_object/object.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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:-

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

assessing

      Fig-4: output of class  

Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/class/class.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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 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.

this_keyword

      Fig-5: output of this keyword 

Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/this_keyword/this.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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: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.

without_this

      Fig-6: output of without this keyword  

Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/without_this_keyword/without_this.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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.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 .

super

      Fig-7: output of super keyword

Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/super_keyword/super.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/super_keyword/super.log

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.

extern

      Fig-8: output of extern keyword

Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/extern_keyword/extern.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/extern_keyword/extern.log

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.

chain_construct

               Fig-9: output for chaining constructs.  

Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/tree/production/classes/chaining_constructs
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/chaining_constructs/basic_constructs_1/chain_constructs.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. They are

1.Global constants
2.Instance constants

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

constant-class-image

             Fig-10: Types 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 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.

global

         Fig-11: output of global constant  

Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/constant_variables/global_class/global_class.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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:-
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.

instance

            Fig-12: output of Instance Constants  

Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/constant_variables/instance_class/instance_class.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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 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.

parameter

              Fig- 12 output of parameterized by value  

Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/parameterized_classes/parameter_value/parameter_value.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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 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.

parameter-datatype

          Fig-13 output of parameterized by datatype  

Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/parameterized_classes/parameter_datatype/parameter_datatype.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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-14 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-15  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

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

class-assignment (2)

               Fig-16 output of class assignment  

Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/copying_methods/class_assignment/class_assignment.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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-17 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.

shallow

          Fig-18 output of shallow copy   

Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/copying_methods/shallow_copy/shallow_copy.sv
Github logfile link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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

Untitled Diagram drawio (38)

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

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.

deepcopy (2)

             Fig- 20  output of deep copy  

Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/copying_methods/deep_copy/deep_copy.sv
Github logfile link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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-21 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: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.

Untitled Diagram drawio (34)

         Fig-22 output of virtual function  

Github lab link: classes/virtual_methods/virtual_function Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/virtual_methods/virtual_function.log

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.

Untitled Diagram drawio (35)

Github lab link :https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/virtual_methods/virtual_task/virtual_task.sv

Github logfile link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/virtual_methods/virtual_task/virtual_task.log

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.

over riding

                    Fig-23 output of overriding class member  

Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/class_over_riding/over_riding_class.sv
Github logfile link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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-24  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: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.

properties

               Fig-25 output of static properties  

Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/static/static_properties/static_properties.sv
Github logfile link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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: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’.

static methods

                          Fig-26 output of static method  

Github Lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/static/static_methods/static_method.sv
Github Logfile Link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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-27 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-28 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-29 output of inheritance  

Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/inheritance/inh.sv
Github logfile link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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. 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.

poly-output new-Page-2

      Fig-30  output of polymorphism  

Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/polymorphism/poly.sv
Github logfile linkhttps://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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-31 output of abstract  

Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/abstraction/abstract_class/abstract.sv
Github logfie link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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-32  output of pure virtual class  

Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/abstraction/pure_virtual_function/pvf.sv
Github logfile link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/abstraction/pure_virtual_function/pvf_op.log

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.

Encap

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


  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.

local_errors_new-Page-2

      Fig-34 output of local encapsulation  

Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/encapsulation/local/local.sv
Github logfile link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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-35 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;     //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.

protected_new

      Fig-36  output of protected encapsulation  

Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/encapsulation/protected/prot.sv
Github logfile link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/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-37 output of public encapsulation  

Github lab link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/encapsulation/public/pub.sv
Github logfile link:https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/production/classes/encapsulation/public/pub_op.log