Down Cast and Virtual Concept

In SystemVerilog, Downcasting and Virtual Concepts are important concepts used in object-oriented programming (OOP) within the hardware verification environment. These features help manage and manipulate object types and are particularly useful in writing flexible and reusable verification environments.

1. Downcasting in SystemVerilog

Downcasting is a type of casting where a reference to a superclass object is converted to a reference of a subclass type. It allows you to treat an object of a more general (base) type as a more specific (derived) type.

In other words, downcasting is used when you know the actual type of an object and want to treat it as an object of a more specific class.

2. Virtual Concepts in SystemVerilog

Virtual Concepts are a powerful feature introduced in SystemVerilog to help define abstract types or types that can be used as “placeholders” in assertions or methods where the specific type is not known yet. They are essentially a way to declare a set of constraints without specifying an exact type.

A virtual concept allows you to define a set of attributes or constraints that can be instantiated later as concrete types. This is especially useful in complex verification environments where types or classes might not be fully known until later in the simulation.

class base;
  int a = 5;
endclass

class extend extends base;
  int b = 1;
endclass

module top;
  initial begin
    base     m_base;
    extend  m_extend;

    m_extend = new();
    m_base    = new();
    $cast(m_extend, m_base);
    $display(m_extend.a);
  end
endmodule

//Error: (vsim-3971) $cast to type ‘class work.top1_sv_unit::extend’ from ‘class work.top1_sv_unit::base’ failed in file top.sv

Meaning of a successfully casting from super-class(parent class) to sub-class(child class) is that the super-class is actually a sub-class.
class BasePacket;
  int A = 1;
  int C = 2;

  function void printA;
    $display(“BasePacket::A is %d”, A);
  endfunction : printA

  virtual function void printC;
    $display(“BasePacket::C is %d”, C);
  endfunction : printC
endclass : BasePacket

class My_Packet extends BasePacket;
  int A = 3;
  int C = 4;

  function void printA;
    $display(“My_Packet::A is %d”, A);
  endfunction: printA

  virtual function void printC;
    $display(“My_Packet::C is %d”, C);
  endfunction : printC
endclass : My_Packet

module top;
  initial begin
My_Packet EXT = new;
BasePacket BASE;

BASE = EXT;
BASE.printA;
BASE.printC;
$cast(EXT, BASE);
EXT.printA;
EXT.printC;
end
endmodule : top

//Output:
// BasePacket::A is           1
// My_Packet::C is           4
// My_Packet::A is           3
// My_Packet::C is           4

Here super-class in this example (BASE) is actually the sub-class (EXT), so the $cast is passed.

Here for first call (using BASE handle) of printA and printC, super-class (BASE) is acutally sub-class (EXT) and function printC is declared as virtual in super-class (BASE), so it will execute printC function of sub-class (EXT).

But, function printA is not declared as virtual in super-class (BASE), so it will execute printA function of super-class (BASE), in-spite of it is actually having memory of EXT class, because handle is of super-class.

One usual scenario to use the $cast is to pass some sub-class data into other class, and the developer of the receptor class even don’t know if the incoming class is what kind of sub-class, so usually he will in the receptor class use a super(parent)-class to get the incoming data and then use $cast to check/transfer the data into certain sub-class.

Leave a Comment

Your email address will not be published. Required fields are marked *

error: Content is protected !!
Scroll to Top