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?

PurposeBenefit
Define common interfaceEnsures all derived classes have required methods
Enforce implementationPure virtual methods must be overridden
Prevent direct instantiationForces use of concrete implementations
Code reusabilityCommon functionality in base class
PolymorphismHandle 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 TypeSyntaxImplementationOverride Required?
Regularfunction void foo();RequiredNo
Virtualvirtual function void foo();RequiredNo (optional)
Pure Virtualpure virtual function void foo();Not allowedYes (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 ClassTypePurpose
uvm_objectAbstractBase for all UVM data objects
uvm_componentAbstractBase for all UVM structural components
uvm_sequence_itemAbstractBase for transaction items
uvm_sequenceAbstractBase for sequences
uvm_driverAbstractBase 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

MistakeErrorFix
Instantiating abstract classCannot instantiate virtual classInstantiate derived class instead
Not implementing pure virtualClass is abstractImplement all pure virtual methods
Body in pure virtualSyntax errorPure virtual methods have no body
Missing virtual keywordMethod not overriddenUse 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):

FeatureAbstract ClassInterface Class
Keywordvirtual classinterface class
PropertiesAllowedNot allowed
Method implementationAllowedNot allowed (pure virtual only)
InheritanceSingle (extends)Multiple (implements)
Use casePartial implementationDefine 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 class declares an abstract class
  • Abstract classes cannot be instantiated
  • pure virtual methods 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
Author
Mayur Kubavat
VLSI Design and Verification Engineer sharing knowledge about SystemVerilog, UVM, and hardware verification methodologies.

Comments (0)

Leave a Comment