🛠️ Advanced OOP in SystemVerilog: Constructors, Handles, and Static Members#
This section explores advanced object-oriented programming (OOP) features in SystemVerilog, including how to define and instantiate classes, manage object handles, work with constructors, and utilize static methods and properties.
1️⃣ Class Definition and Instantiation#
In SystemVerilog, a class is defined using the class
keyword. A class can contain data members (properties) and methods (functions/tasks). To instantiate a class (i.e., create an object), use the new()
operator.
Example:
class Packet;
bit [7:0] data;
function void print();
$display("Data: %0h", data);
endfunction
endclass
Packet pkt;
initial begin
pkt = new(); // Instantiates the Packet class
pkt.data = 8'hAB;
pkt.print();
end
2️⃣ Class Handles and Objects#
In SystemVerilog, classes are accessed through handles. A handle is a variable that points to an object in memory.
- Class handle: A variable of the class type, e.g.,
Packet pkt;
- Object: The actual instance created by
new()
.
A handle can be:
- Assigned to another handle (both point to the same object).
- Compared against
null
to check if it is pointing to a valid object.
Example:
Packet pkt1, pkt2;
pkt1 = new();
pkt2 = pkt1; // Both pkt1 and pkt2 refer to the same object
3️⃣ Current Object Handle (this
)#
SystemVerilog provides a special handle called this
, which refers to the current object.
Example:
class Packet;
bit [7:0] data;
function void show();
$display("Data in this packet: %0h", this.data);
endfunction
endclass
this
is useful when passing the current object as an argument or differentiating between local and member variables.
4️⃣ Constructor Method#
A constructor is a special method named new()
that initializes an object when it is created. It can accept arguments to set initial values.
Example:
class Packet;
bit [7:0] data;
function new(bit [7:0] init_data);
data = init_data;
endfunction
endclass
Packet pkt = new(8'hFF); // Initializes 'data' to FF
If you don’t declare a constructor, SystemVerilog provides a default new()
with no arguments.
5️⃣ External Method Declaration#
In SystemVerilog, methods can be declared inside the class but defined externally (outside the class body). This helps organize code, especially in large testbenches.
Example:
class Packet;
bit [7:0] data;
extern function void print();
endclass
function void Packet::print();
$display("Data = %0h", data);
endfunction
Use the ClassName::methodName
syntax for external definitions.
6️⃣ super
Keyword#
The super
keyword allows a derived class to call methods from its base class, including its constructor.
Example:
class BasePacket;
function void display();
$display("Base display");
endfunction
endclass
class DataPacket extends BasePacket;
function void display();
super.display(); // Calls BasePacket's display()
$display("DataPacket display");
endfunction
endclass
7️⃣ Static Class Methods#
A static method belongs to the class itself rather than any specific object. It cannot access non-static (object-specific) variables.
Example:
class Utility;
static function void showHelp();
$display("This is a static help method.");
endfunction
endclass
initial begin
Utility::showHelp(); // Call static method
end
8️⃣ Static Class Properties#
Static properties belong to the class itself and are shared by all objects of that class.
Example:
class Counter;
static int count = 0;
function void increment();
count++;
endfunction
static function void showCount();
$display("Count = %0d", count);
endfunction
endclass
initial begin
Counter c1 = new();
Counter c2 = new();
c1.increment();
c2.increment();
Counter::showCount(); // Outputs 2
end
📖 Conclusion#
These advanced OOP features allow you to write more modular, maintainable, and scalable testbenches in SystemVerilog. Mastering them will improve your ability to model complex verification environments.
module tb_advanced_oop_demo;
// Base class with data and constructor
class Packet;
bit [7:0] data;
// Constructor with argument
function new(bit [7:0] init_data);
data = init_data;
endfunction
// Print method declared inside, defined outside
extern function void print();
endclass
// Print method defined outside the class
function void Packet::print();
$display("[Packet] Data = %0h", data);
endfunction
// Derived class extending Packet
class ExtendedPacket extends Packet;
bit [7:0] id;
function new(bit [7:0] init_data, bit [7:0] init_id);
super.new(init_data);
id = init_id;
endfunction
function void print();
super.print();
$display("[ExtendedPacket] ID = %0h", id);
endfunction
endclass
// Class with static property and method
class Counter;
static int count = 0;
function void increment();
count++;
endfunction
static function void showCount();
$display("Count = %0d", count);
endfunction
endclass
initial begin
Packet p;
ExtendedPacket ep;
Counter c1;
Counter c2;
// Object creation and assignments
p = new(8'hAA);
p.print();
ep = new(8'hBB, 8'h01);
ep.print();
// 'this' example
$display("Accessing 'this.data' in Packet: %0h", p.data);
// Static counter demonstration
c1 = new();
c2 = new();
c1.increment();
c2.increment();
Counter::showCount();
#10 $finish;
end
endmodule