Inheritance is a concept in OOP that allows us to extend a class to create another class and have access to all the properties and methods of the original parent class from the handle of a new class object. The idea behind this scheme is to allow developers add in new properties and methods into the new class while still maintaining access to the original class members. This allows us to make modifications without touching the base class at all.
ExtPacket is extended and hence is a child class of Packet. Being a child class, it inherits properties and methods from its parent. If there exists a function with the same name in both the parent and child class, then its invocation will depend on the type of the object handle used to call that function. In the example below, both Packet and ExtPacket have a function called
display(). When this function is called by a child class handle, the child class
display() function will be executed. If this function is called by a parent class handle, then the parent class
display() function will be executed.
In a previous post, key topics on class handles and objects were discussed which is essential to understand how shallow copy and deep copy works.
Click here to refresh concepts in class handles and objects !
this keyword is used to refer to class properties, parameters and methods of the current instance. It can only be used within non-static methods, constraints and covergroups.
this is basically a pre-defined object handle that refers to the object that was used to invoke the method in which
this is used.
A very common way of using
this is within the initialization block.
class Packet; bit [31:0] addr; function new (bit [31:0] addr); // addr = addr; // Which addr should get assigned ? this.addr = addr; // addr variable in Packet class should be // assigned with local variable addr in new() endfunction endclass
Unless there is ambiguity in assignment, use of
this keyword is not generally needed for specifying access to class members in methods.
Each class instance would normally have a copy of each of its internal variables.
class Packet; bit [15:0] addr; bit [7:0] data; function new (bit [15:0] ad, bit [7:0] d); addr = ad; data = d; $display ("addr=0x%0h data=0x%0h", addr, data); endfunction endclass module tb; initial begin Packet p1, p2, p3; p1 = new (16'hdead, 8'h12); p2 = new (16'hface, 8'hab); p3 = new (16'hcafe, 8'hfc); end endmodule
Each of the class objects p1, p2, p3 will have addr and data variables within it.Simulation Log
ncsim> run addr=0xdead data=0x12 addr=0xface data=0xab addr=0xcafe data=0xfc ncsim: *W,RNQUIE: Simulation is complete.
A constructor is simply a method to create a new object of a particular class data-type.
C/C++ requires complex memory allocation techniques and improper de-allocation could lead to memory leaks and other behavioral issues. SystemVerilog, although not a programming language, is capable of simple construction of objects and automatic garbage collection.
When class constructor is explicity defined
// Define a class called "Packet" with a 32-bit variable to store address // Initialize "addr" to 32'hfade_cafe in the new function, also called constructor class Packet; bit [31:0] addr; function new (); addr = 32'hfade_cafe; endfunction endclass module tb; // Create a class handle called "pkt" and instantiate the class object initial begin // The class's constructor new() fn is called when the object is instantiated Packet pkt = new; // Display the class variable - Because constructor was called during // instantiation, this variable is expected to have 32'hfade_cafe; $display ("addr=0x%0h", pkt.addr); end endmodule
In the example above, variable declaration creates an object of class Packet and will automatically call the
new() function within the class. The
new() function is called a class constructor and is a way to initialize the class variables with some value. Note that it does not have a return type and is non-blocking.
ncsim> run addr=0xfadecafe ncsim: *W,RNQUIE: Simulation is complete.