7

Does SystemVerilog support downcasting (casting a base object to a derived object)? If so, how?

The following downcast example does not work:

class base;
  int a = 5;
endclass

class extend extends base;
  int b = 1;
endclass

module test;

  initial begin
    base m_base;
    extend m_extend;

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

Modify and rerun the example on EDA Playground: http://www.edaplayground.com/s/4/581

Victor Lyuboslavsky
  • 9,882
  • 25
  • 87
  • 134

3 Answers3

11

Yes, you can downcast. Your example is the correct syntax, and it actually does compile. However you are getting a runtime error because the cast fails.

The cast in you example is failing because you can only successfully downcast if the handle to the base object is actual referencing an object of the derived type. You can call $cast as a function and it will return a boolean indicating whether the cast was successful or not.

Here is an example:

class animal;
  function void eat();
  endfunction
endclass

class dog extends animal;
  function void bark();
    $display("woof");
  endfunction
endclass

class cat extends animal;
  function void meow();
    $display("meow");
  endfunction
endclass

module test;

  initial begin
    dog a_dog = new();
    cat a_cat = new();

    animal animals[$];
    animals.push_back(a_dog);
    animals.push_back(a_cat);

    foreach (animals[i]) begin
      dog another_dog;
      animals[i].eat();
      if ($cast(another_dog, animals[i])) begin
        $display("Found a dog!");
        another_dog.bark();
      end
    end

  end
endmodule

Outputs:

# Found a dog!
# woof

See http://www.edaplayground.com/s/474/586

dwikle
  • 6,820
  • 1
  • 28
  • 38
4

IEEE Std 1800-2012 § 8.16 "Casting" states:

It is always legal to assign an expression of subclass type to a variable of a class type higher in the inheritance tree (a superclass or ancestor of the expression type). It shall be illegal to directly assign a variable of a superclass type to a variable of one of its subclass types. However, $cast may be used to assign a superclass handle to a variable of a subclass type provided the superclass handle refers to an object that is assignment compatible with the subclass variable.

The following cast failes because a superclass object not be read as an childclass.

m_base = new();
$cast(m_extend, m_base); // destination type != source object type

To cast correctly the object of the source handle must be compatible with the destination typetypes must be comparable:

m_extend = new();
m_base = m_extend;
$cast(m_extend, m_base); // destination type == source object type

Downcasting can work through levels of inheritance. The following example demonstrates a base class handle pointing a grandchild object being casted to the extend class (the grandchild object's parent class):

class ext_more extends extend;
  int c;
endclass
initial begin
  base m_base;
  extend m_extend;
  ext_more m_ext_more;

  m_ext_more = new();
  m_base = m_ext_more;
  $cast(m_extend, m_base); // legal, casting a subclass object to a parent handle
  $display(m_extend.a);
end

Here are some working example: http://www.edaplayground.com/s/6/587

Greg
  • 18,111
  • 5
  • 46
  • 68
0

In this solution, you are nowhere downcasted, you just use the $cast to check if classes are compatible or not. If yes, print that particular class (DOG in your case) is found.

In you $cast function first parameter (destination) you are taking another_dog as a child class and in the second parameter (source) you are picking from queues that is again queues of child classes

ZygD
  • 22,092
  • 39
  • 79
  • 102