2. OOP in SystemVerilog - Abstract Classes
Abstract classes (also called virtual classes) are a powerful OOP feature in SystemVerilog that define a template for derived classes. They're extensively used in UVM and are a common interview topic.
What is an Abstract Class?
An abstract class is a class that:
- Cannot be instantiated directly
- Serves as a blueprint for derived classes
- May contain pure virtual methods that must be implemented by child classes
Keyword: Use virtual class to declare an abstract class in SystemVerilog.
Syntax
// Abstract class declaration
virtual class ClassName;
// Properties
// Methods (virtual, pure virtual, or regular)
endclass
// Concrete class extending abstract class
class DerivedClass extends ClassName;
// Must implement all pure virtual methods
endclass
Why Use Abstract Classes?
| Purpose | Benefit |
|---|---|
| Define common interface | Ensures all derived classes have required methods |
| Enforce implementation | Pure virtual methods must be overridden |
| Prevent direct instantiation | Forces use of concrete implementations |
| Code reusability | Common functionality in base class |
| Polymorphism | Handle objects through base class references |
Types of Methods in Abstract Classes
flowchart TD
A["Abstract Class Methods"] --> B["Regular Methods"]
A --> C["Virtual Methods"]
A --> D["Pure Virtual Methods"]
B --> B1["Has implementation\nCan be inherited as-is"]
C --> C1["Has implementation\nCan be overridden"]
D --> D1["No implementation\nMUST be overridden"]
style A fill:#dbeafe,stroke:#3b82f6
style D fill:#fee2e2,stroke:#ef4444
style D1 fill:#fee2e2,stroke:#ef4444
Comparison Table
| Method Type | Syntax | Implementation | Override Required? |
|---|---|---|---|
| Regular | function void foo(); | Required | No |
| Virtual | virtual function void foo(); | Required | No (optional) |
| Pure Virtual | pure virtual function void foo(); | Not allowed | Yes (mandatory) |
Complete Example
// Abstract base class - cannot be instantiated
virtual class Transaction;
// Properties
rand bit [31:0] addr;
rand bit [31:0] data;
// Regular method - inherited as-is
function void print_base();
$display("Base: addr=0x%0h, data=0x%0h", addr, data);
endfunction
// Virtual method - can be overridden
virtual function void print();
$display("Transaction: addr=0x%0h, data=0x%0h", addr, data);
endfunction
// Pure virtual method - MUST be implemented by child
pure virtual function bit is_valid();
// Pure virtual task
pure virtual task execute();
endclass
// Concrete class - implements pure virtual methods
class WriteTransaction extends Transaction;
rand bit [3:0] byte_en;
// Override virtual method
virtual function void print();
$display("WRITE: addr=0x%0h, data=0x%0h, be=0x%0h",
addr, data, byte_en);
endfunction
// Implement pure virtual function (mandatory)
virtual function bit is_valid();
return (addr[1:0] == 2'b00); // Check alignment
endfunction
// Implement pure virtual task (mandatory)
virtual task execute();
$display("Executing WRITE to 0x%0h", addr);
#10;
endtask
endclass
// Another concrete class
class ReadTransaction extends Transaction;
rand int burst_len;
virtual function void print();
$display("READ: addr=0x%0h, burst=%0d", addr, burst_len);
endfunction
virtual function bit is_valid();
return (burst_len > 0 && burst_len <= 16);
endfunction
virtual task execute();
$display("Executing READ from 0x%0h", addr);
#5;
endtask
endclass
Testbench Example
module tb;
initial begin
Transaction t; // Base class handle (OK)
WriteTransaction wr;
ReadTransaction rd;
// t = new(); // ERROR! Cannot instantiate abstract class
// Create concrete objects
wr = new();
rd = new();
// Randomize
assert(wr.randomize());
assert(rd.randomize());
// Polymorphism - base handle pointing to derived object
t = wr;
t.print(); // Calls WriteTransaction::print()
t.execute(); // Calls WriteTransaction::execute()
t = rd;
t.print(); // Calls ReadTransaction::print()
// Check validity
if (wr.is_valid())
$display("Write transaction is valid");
end
endmodule
Output
WRITE: addr=0x12345678, data=0xdeadbeef, be=0xf Executing WRITE to 0x12345678 READ: addr=0x87654320, burst=8 Write transaction is valid
Abstract Classes in UVM
UVM extensively uses abstract classes. Key examples:
| UVM Class | Type | Purpose |
|---|---|---|
uvm_object | Abstract | Base for all UVM data objects |
uvm_component | Abstract | Base for all UVM structural components |
uvm_sequence_item | Abstract | Base for transaction items |
uvm_sequence | Abstract | Base for sequences |
uvm_driver | Abstract | Base for drivers |
// UVM example - extending abstract class
class my_transaction extends uvm_sequence_item;
`uvm_object_utils(my_transaction)
rand bit [31:0] addr;
rand bit [31:0] data;
function new(string name = "my_transaction");
super.new(name);
endfunction
// Override pure virtual methods from uvm_object
virtual function void do_copy(uvm_object rhs);
my_transaction t;
super.do_copy(rhs);
$cast(t, rhs);
this.addr = t.addr;
this.data = t.data;
endfunction
virtual function string convert2string();
return $sformatf("addr=0x%0h, data=0x%0h", addr, data);
endfunction
endclass
Common Mistakes
| Mistake | Error | Fix |
|---|---|---|
| Instantiating abstract class | Cannot instantiate virtual class | Instantiate derived class instead |
| Not implementing pure virtual | Class is abstract | Implement all pure virtual methods |
| Body in pure virtual | Syntax error | Pure virtual methods have no body |
Missing virtual keyword | Method not overridden | Use virtual for polymorphism |
// WRONG - pure virtual cannot have body
pure virtual function void foo();
$display("test"); // ERROR!
endfunction
// CORRECT - pure virtual has no body
pure virtual function void foo();
Abstract vs Interface Class
SystemVerilog also has interface class (similar to Java interfaces):
| Feature | Abstract Class | Interface Class |
|---|---|---|
| Keyword | virtual class | interface class |
| Properties | Allowed | Not allowed |
| Method implementation | Allowed | Not allowed (pure virtual only) |
| Inheritance | Single (extends) | Multiple (implements) |
| Use case | Partial implementation | Define contracts/APIs |
Interview Questions
Q1: Can you create an object of an abstract class?
Answer: No. Abstract classes cannot be instantiated directly. You can only create objects of concrete (non-abstract) derived classes.
Q2: What's the difference between virtual and pure virtual methods?
Answer: Virtual methods have an implementation and can optionally be overridden. Pure virtual methods have no implementation and must be overridden in derived classes.
Q3: Can an abstract class have non-virtual methods?
Answer: Yes. Abstract classes can have regular methods, virtual methods, and pure virtual methods.
Q4: Give a UVM example of an abstract class.
Answer: uvm_object, uvm_component, uvm_sequence_item are all abstract classes that define the framework's core functionality.
Key Takeaways
virtual classdeclares an abstract class- Abstract classes cannot be instantiated
pure virtualmethods must be implemented by derived classes- Enables polymorphism through base class handles
- UVM base classes are mostly abstract classes
- Use abstract classes to define templates and enforce contracts
Comments (0)
Leave a Comment