Abstract Class and Pure Virtual methods

What Is an Abstract Class?

An abstract class is a class that serves as a base class and cannot be instantiated directly. It acts as a template for other classes, defining methods and properties that derived (child) classes must implement or extend. Abstract classes are often used to enforce a standard structure in testbenches or verification components.

Characteristics of Abstract Classes:

  1. Cannot be instantiated: You cannot create an object of an abstract class.
  2. Contains pure virtual methods: These methods must be implemented by derived classes.
  3. May include concrete methods: Abstract classes can have fully implemented methods that child classes can use or override.
  4. Serves as a blueprint: Abstract classes define the structure and behavior expected in derived classes.

Declaring an Abstract Class:

To make a class abstract in System Verilog, you use the keyword virtual before the class declaration.

virtual class AbstractClassName;
    // Class body
endclass

Pure Virtual Methods in Abstract Classes

A pure virtual method is a method declared in an abstract class that does not have a body. It is marked using the pure keyword. Pure virtual methods must be implemented by any class that inherits the abstract class and it must use the same arguments and return type if applicable.

Syntax:

pure virtual function return_type method_name(arguments);

Abstract Class Examples:

Example1: Abstract Class With Virtual Functions

// Abstract class for arithmetic operations
virtual class Arithmetic;
  // Virtual method with a default implementation
  virtual function int compute(int a, int b);
    // Default implementation returns 0 (can be overridden)
    return 0;
  endfunction
endclass

// Derived class for addition
class Addition extends Arithmetic;
  // Override the compute method
  function int compute(int a, int b);
    return a + b;
  endfunction
endclass

// Derived class for subtraction
class Subtraction extends Arithmetic;
  // Override the compute method
  function int compute(int a, int b);
    return a - b;
  endfunction
endclass


// Testbench
module tb;
 
  int result;

  initial begin
    Addition Add = new();
    Subtraction Sub = new();
    
    // Perform addition
    result = Add.compute(10, 5);
    $display("Addition Result: %0d", result);

    // Perform subtraction
    result = Sub.compute(10, 5);
    $display("Subtraction Result: %0d", result);

  end
endmodule

Key Points:

  1. Abstract Class:
    • Defined using the abstract keyword.
    • Includes a virtual method compute with a default implementation that can be overridden by derived classes.
    • This approach does not use pure functions, so the abstract class itself can technically provide a working (but generic) implementation.
  2. Virtual Function:
    • Derived classes override the compute method to provide specific behavior for addition, and subtraction.

Output:

Addition Result: 15
Subtraction Result: 5

Example 2: Abstract Class with pure virtual methods

Let’s consider a simple example of an abstract class that defines a verification component’s interface.

// Abstract class for verification component
virtual class VerificationComponent;
    // Pure virtual methods
    pure virtual function void configure();
    pure virtual task run();
    
    // Concrete method
    function void print_info();
        $display("Verification Component: Abstract base class");
    endfunction
endclass

// Derived class: Driver
class Driver extends VerificationComponent;
    function void configure();
        $display("Driver: Configuring interface");
    endfunction

    task run();
        $display("Driver: Sending data");
    endtask
endclass

module tb;
    initial begin
        // Polymorphic behavior
        VerificationComponent vc;

        // Instantiate a Driver
      Driver drive = new();
      vc = drive;
      vc.configure();
      vc.run();
      vc.print_info();

    end
endmodule

Explanation:

  1. Abstract Class (VerificationComponent):
    • Contains two pure virtual methods: configure() and run().
    • Includes a concrete method, print_info(), which can be reused or overridden in derived classes.
  2. Derived Classes (Driver ):
    • Implement the pure virtual methods from the base class.
    • Define specific behaviors for configure() and run().
  3. Polymorphism:
    • The base class reference (vc) can hold objects of different derived classes (Here Driver).
    • Allows seamless interaction with derived classes while maintaining code flexibility.

Output:

Driver: Configuring interface
Driver: Sending data
Verification Component: Abstract base class

Benefits of Abstract Classes and Pure Virtual Methods

  1. Code Reusability: Define common methods and properties in the base class and reuse them across derived classes.
  2. Flexibility: Enforce specific behaviors in derived classes through pure virtual methods.
  3. Polymorphism: Enable the use of base class references to interact with derived classes, providing flexibility in testbench design.
  4. Modularity: Divide functionality across classes, improving the organization and maintainability of code.