Monday 1 June 2015

Virtual method in SystemVerilog

A method of a class may be identified with the keyword virtual.
Virtual methods are a basic polymorphic construct.
One way to view this is that there is only one implementation of a virtual method per class hierarchy, and it is always the one in the latest derived class.
Virtual methods provide prototypes for the methods that later override them.
Virtual method overrides in subclasses shall have matching argument types, identical argument names, identical qualifiers, and identical directions to the prototype.
The virtual qualifier is optional in the derived class method declarations. The return type of a virtual function shall be either:
matching type or a derived class type
of the return type of the virtual function in the superclass. It is not necessary to have matching default expressions, but the presence of a default shall match.

A virtual method may override a non-virtual method, but once a method has been identified as virtual, it shall remain virtual in any subclass that overrides it. In that case, the virtual keyword may be used in later declarations, but is not required.


class Base;
  int unsigned A = 1;
  int unsigned B = 2;

  function void printA();
    $display("Base: A=%0d", A);
  endfunction : printA

  virtual function void printB();
    $display("Base: B=%0d", B);
  endfunction : printB
endclass : Base

class Child extends Base;
  int unsigned A = 3;
  int unsigned B = 4;

  function void printA();
    $display("Child: A=%0d", A);
  endfunction : printA

  function void printB();
    $display("Child: B=%0d", B);
  endfunction : printB
endclass : Child

// Child2 is inherited (extends) from Child.
// printB is not defined as virtual in Child.
// Though Child2 override printB of Child because printB is defined as virtual in Base.

class Child2 extends Child;
  int unsigned A = 5;
  int unsigned B = 6;

  function void printA();
    $display("Child2: A=%0d", A);
  endfunction : printA

  function void printB();
    $display("Child2: B=%0d", B);
  endfunction : printB
endclass : Child2

module top();
  Base  B1;
  Child C1;
  Child2 C2;

  initial begin
    B1 = new();
    C1 = new();
    C2 = new();
   
    B1.printA;  // displays 'Base::A is 1'
    B1.printB;
  // displays 'Base::B is 2'
    C1.printA;  // displays 'Child::A is 3'
    C1.printB;  // displays 'Child::B is 4'
    C2.printA;  // displays 'Child2::A is 5'
    C2.printB;  // displays 'Child2::B is 6'

    B1 = C1;    // B1 has handle of Child
    B1.printA;  //
displays 'Base::A is 1'
    B1.printB;  // displays 'Child::B is 4' - latest derived method
    C1.printA;  // displays 'Child1::A is 3'
    C1.printB;  // displays 'Child1::B is 4'

    C1 = C2;     // C1 has handle of Child2
    C1.printA;  // displays 'Child1::A is 3'
    C1.printB;  // displays 'Child2::B is 6' - latest derived method
    C2.printA;  // displays 'Child2::A is 5'
    C2.printB;  // displays 'Child2::B is 6'

    B1 = C2;     // C1 has handle of Child2
    B1.printA;  // displays 'Base::A is 1'
    B1.printB;  // displays 'Child2::B is 6' - latest derived method
    C2.printA;  // displays 'Child2::A is 5'
    C2.printB;  // displays 'Child2::B is 6'
  end
endmodule : top


//Output:
// Base: A=1
// Base: B=2
// Child: A=3
// Child: B=4
// Child2: A=5
// Child2: B=6

// Base: A=1
// Child: B=4
// Child: A=3
// Child: B=4

// Child: A=3
// Child2: B=6
// Child2: A=5
// Child2: B=6

// Base: A=1
// Child2: B=6
// Child2: A=5
// Child2: B=6

No comments:

Post a Comment