In SystemVerilog, an abstract class is a class declared as virtual
that cannot be directly instantiated. Instead, it can only be used as a base class for other subclasses. This ensures that developers extend the base class to meet specific needs, enforcing structure and reusability. An abstract class can be helpful in test cases, as it requires subclasses to implement the base class’s functionality.
What is a SystemVerilog Abstract Class?
A SystemVerilog abstract class is defined using the virtual
keyword. It cannot be instantiated directly but can be extended by other classes that can be instantiated. Here’s how you define a basic virtual class:
virtual class <class_name>;
// Class definition goes here
endclass
Although it’s not mandatory, base classes are often declared as virtual
. This encourages developers to always create subclasses that are tailored for their requirements.
Example: Base Class Without Virtual Keyword
Let’s first look at a regular class definition without the virtual
keyword:
class BaseClass;
int data;
function new();
data = 32'hc0de_c0de;
endfunction
endclass
module tb;
BaseClass base;
initial begin
base = new();
$display ("data=0x%0h", base.data);
end
endmodule
Simulation Log:
ncsim> run
data=0xc0dec0de
ncsim: *W,RNQUIE: Simulation is complete.
Example: Base Class Declared as Virtual (Abstract Class)
Now, let’s declare the BaseClass
as virtual
to make it an abstract class:
virtual class BaseClass;
int data;
function new();
data = 32'hc0de_c0de;
endfunction
endclass
module tb;
BaseClass base;
initial begin
base = new();
$display ("data=0x%0h", base.data);
end
endmodule
In this case, we get a compilation error since abstract classes cannot be instantiated:
Simulation Log:
base = new();
|
ncvlog: *E,CNIABC (testbench.sv,12|5): An abstract (virtual) class cannot be instantiated.
Extending an Abstract Class
Even though you cannot instantiate an abstract class directly, you can extend it. The child class can then be instantiated. Here’s how you can extend the BaseClass
:
virtual class BaseClass;
int data;
function new();
data = 32'hc0de_c0de;
endfunction
endclass
class ChildClass extends BaseClass;
function new();
data = 32'hfade_fade;
endfunction
endclass
module tb;
ChildClass child;
initial begin
child = new();
$display ("data=0x%0h", child.data);
end
endmodule
In this example, the child class ChildClass
extends the abstract class BaseClass
and can be instantiated.
Simulation Log:
ncsim> run
data=0xfadefade
ncsim: *W,RNQUIE: Simulation is complete.
Pure Virtual Methods in Abstract Classes
In SystemVerilog, you can also declare pure virtual methods in an abstract class. These methods only need a prototype in the base class, and their implementation is left for subclasses. A pure virtual method is declared using the pure
keyword.
virtual class BaseClass;
int data;
pure virtual function int getData();
endclass
class ChildClass extends BaseClass;
virtual function int getData();
data = 32'hcafe_cafe;
return data;
endfunction
endclass
module tb;
ChildClass child;
initial begin
child = new();
$display ("data = 0x%0h", child.getData());
end
endmodule
In this example, getData()
is a pure virtual method in BaseClass
, and it is implemented in ChildClass
. The return type and arguments for the method should match in both the abstract class and the subclass.
Simulation Log:
ncsim> run
data = 0xcafecafe
ncsim: *W,RNQUIE: Simulation is complete.
Key Differences Between Abstract and Regular Classes
Here’s a quick comparison between regular and abstract (virtual) classes in SystemVerilog:
Feature | Regular Class | Abstract Class (Virtual) |
---|---|---|
Instantiation | Can be instantiated directly | Cannot be instantiated directly |
Use in Subclasses | Can be extended by subclasses | Must be extended by subclasses |
Purpose | For general use | To be extended for specific needs |
Abstract Methods | Cannot have pure virtual methods | Can have pure virtual methods |
Conclusion
SystemVerilog abstract classes (declared as virtual
) help in enforcing good design practices by ensuring that test case developers extend base classes instead of using them directly. They also allow defining methods that must be implemented in subclasses, promoting code reusability and flexibility. Understanding how to use these classes, including pure virtual methods, is essential for writing efficient and structured SystemVerilog code.