The virtual keyword in SystemVerilog is used to declare methods and interfaces that support polymorphism. It allows a derived class to override methods from a base class, enabling dynamic binding at runtime. Without the virtual keyword, method binding is static, determined at compile time.
Where is the virtual Keyword Used?
The virtual keyword is primarily used in two contexts:
- Virtual Methods: To declare methods in a base class that can be overridden by derived classes.
- Virtual Interfaces: To define interface variables that can be dynamically connected.
Let’s explore these applications in detail.
1. Virtual Methods
A method marked with virtual allows derived classes to override its behavior, enabling runtime polymorphism. This is particularly useful in verification environments, where you might want different behaviors depending on the object type being used.
Example: Virtual Methods
class BaseClass;
virtual function void display();
$display("This is BaseClass.");
endfunction
endclass
class DerivedClass extends BaseClass;
function void display();
$display("This is DerivedClass.");
endfunction
endclass
module test;
initial begin
BaseClass base;
DerivedClass derived = new();
// Polymorphism
base = derived; // Assign derived object to base class reference
base.display(); // Calls DerivedClass::display due to virtual
end
endmodule
Output:
This is DerivedClass.
Explanation:
- The display() method in BaseClass is declared as
virtual. - When the base reference points to a DerivedClass object, the overridden display() method in DerivedClass is invoked, demonstrating polymorphism.
In the above code, if we remove the virtual keyword then the output will be:
This is BaseClass.
2. Virtual Interfaces
Virtual interfaces are used to connect modules or environments dynamically. They enable passing interface handles to different modules, avoiding hard-coded connections and improving flexibility.
Example: Virtual Interfaces
interface my_interface;
logic signal;
endinterface
class Driver;
virtual my_interface vif; // Virtual interface declaration
function new(virtual my_interface vif);
this.vif = vif;
endfunction
task drive();
vif.signal = 1'b1; // Drive the interface signal
$display("Signal driven: %b", vif.signal);
endtask
endclass
module test;
my_interface intf(); // Instantiate the interface
Driver drv;
initial begin
drv = new(intf); // Pass the interface to the driver
drv.drive();
end
endmodule
Output:
Signal driven: 1
Explanation:
- The my_interface is declared as a virtual interface in the
Driverclass. - The intf instance is dynamically passed to the
Driverduring its construction, allowing the driver to manipulate the interface signals.
Common Use Cases
- UVM (Universal Verification Methodology): The virtual keyword is integral in UVM, where virtual methods are used for factory overrides and callbacks, and virtual interfaces connect testbenches to DUTs.
- Reusable Test Environments: Virtual interfaces allow creation of generic drivers and monitors that can work with different designs by connecting dynamically at runtime.
Key Points to Remember
- Declare a method as virtual in the base class to allow it to be overridden in derived classes.
- Use virtual interfaces to enable dynamic binding of interface connections.
- Without the virtual keyword, methods and interfaces are statically bound, limiting flexibility.