Comparing dynamic types of uvm_objects

I want to make a function that can determine if a given object is an instance of a given type, where both the type and the object are dynamic. I am hoping that uvm_object_wrapper can help me (if only as a proxy to create a type to be able to use virtual functions).

For example, if uvm_object defined something like
// Note: this could be an object util macro
virtual function bit is_an_instance_of_my_type(uvm_object o);
MY_TYPENAME t;
return $cast(t, o);
endfunction

Then I could do something like
function am_i_an_instance_of(uvm_object_wraper sometype);
uvm_object other_obj = some_type.create(“other_pbj”);
return other_obj.is_an_instance_of_my_type(this);
endfunction

As far as I know, this specific functionality is not present, but I am wondering if there is anything similar. Unfortunately, I would like my solution to generalize to third-party uvm_object subtypes, so I can’t just extend the macros myself or generate such a function.

I recently learned about uvm_callbacks, which seems to handle using subtypes as the type parameter, and somehow searches through the supertypes/subtypes as needed for a matching callback when requested to get or delete callbacks for example. The code for that has been hard for me to parse or figure out if I could apply it here.

For now, I have worked around this by creating a helper class with a type parameter and using $cast() there, but I am hoping I can work this into the base class I’m using.

You do not need to create a separate function for this. The uvm_object base class provides the virtual method get_object_type() as well as the static method get_type() (inserted by the uvm_object/component_utils macro). They return the singleton uvm_object_wrapper handles which can be compared directly.

my_object1.get_object_type() == my_object2.get_object_type()

or

my_object1.get_object_type() == some_type::get_type()

This lets me determine if two objects exactly equal, but that isn’t quite what I want. I want to know if the object is an instance of a given type, which would include an instance of any subclasses of the given type.

So, I’d want to be able to do something like below (if I was in a language where such operator overloads worked and this was implemented).

// "less than or equal to" for types being a way to ask if the left side is a subtype of the right side (or the same type).
my_object1.get_object_type() <= some_type::get_type()

In java, this would be like “instanceof”, except that I’m hoping to use dynamic type representations (uvm_object_wrapper) rather than explicit type names or type parameters.

OK, I guess there is nothing similar to Java’s instanceof operator. Without knowing the actual problem you want to solve, this is an XY problem.

One possible approach might be to build a lookup table using an associative array for the class types you need to query.

  typedef struct {
    uvm_wrapper_object object;
    uvm_wrapper_object typeof;
  } iof;
  bit lut[iof] = '{default:0}; //Look Up Table
...
lut[iof'{some_type::get_type(),some_type::get_type()}] = 1;
lut[iof'{some_extended_type::get_type(),some_type::get_type()}] = 1;

Then you would ask

if( lut[iof'{my_object1.get_object_type(),some_type::get_type()}] ) ...

OK. To break the XY problem at least, what I really want (and have a slightly clunky solution for already) is to be able to find the source of a translated sequence item.

For example: I might have an Avalon or AXI-S frame which has been extracted from the bus, and has bus-level details (including user bits, KEEP bits, etc), I might translate that to an array of data bytes (resolving things like the KEEP signal and dropping user data) for further analysis. I might then translate that item to an abstract protocol-specific representation for the higher level protocol.

Sometimes, a predictor mostly wants the higher level protocol information, but in certain cases, needs to check something about a lower level (e.g. user bits). I would like to have a function where any translated sequence item (a base class) can be asked to walk it’s source chain (the things it was translated from) and return the first item that is of a particular type.

That type might not be an exact match (e.g. a type for AXI-S packets, but the verification library used for that has multiple subtypes, or possibly even uses an interface class, so the dynamic type is not fully predictable, but can have an upper bound set).

class third_party_bus_item_base_class extends uvm_sequence_item;
   ...
endclass

class translated_seq_item extends uvm_sequence_item;
   `uvm_object_utils(translated_seq_item)

   // gets set in any translation operations to refer to the item this item was derived from
   uvm_sequence_item translated_from;
   ...
endclass

class protocol_item extends translated_seq_item;
   ...
endclass

class my_frame_listener extends uvm_subscriber#(protocol_item);
   ...
   function void write(protocol_item t);
      // this is what I'd like to do
      third_party_bus_item_base_class source_item = t.get_source_ by_type(third_party_bus_item_base_class ::get_type());
      if (source_item) begin
         `uvm_info("translation", "the item was translated from a <third-party bus type> item", UVM_MEDIUM)
      end
   endfunction
endclass

What I do now is have a helper class that takes a type parameter with a single static function:

class translated_item_helper#(type LOOKUP_TYPE);
   static function LOOKUP_TYPE get_source(translated_seq_item item);
      LOOKUP_TYPE result;
      translated_seq_item intermediate = item;
      while (intermediate) begin
         // current item is desired result, return it
         if ($cast(result, intermediate)) return intermediate;
         // current item is a translated item, so we can keep looking
         else if ($cast(intermediate, intermediate.translated_from)) continue;
         // current item is neither the result, nor has a known translation source to check. Give up
         else return null;
      end
   endfunction
endclass

This is functional, but I wanted to ask if there is a way to avoid the helper class that I might like more.