Not be able to access type override object properties?

I’m trying to use set_type_override_by_type to override base sequence item class into an extend sequence item class which I created for more constraints on the base class properties. However, I’m encountering a compilation err that prevents me to access the new properties that I created inside the extended class. Here is a code example:

class seq_item_base extends uvm_sequence_item;
  rand int addr;

  constraint valid_addr { addr >= 0; addr <= 256 };

  `uvm_object_utils_begin(seq_item_base)
     // register all properties
  `uvm_object_utils_end

   //constructor
   ...
   // methods
   ...
endclass

typedef enum { LOW, HIGH } addr_knob;
class extended_seq_item extends uvm_sequence_item;
  rand addr_knob knob;

  constraint addr_by_knob { (knob == LOW) -> addr inside { [0:128] };
                            (knob == HIGH) -> addr inside { [129:256] }; }

  `uvm_object_utils_begin(extebded_seq_item)
      // register all new properties
  `uvm_object_utils_end

   //constructor
   ...

endclass

In build phase of my test, I override base_seq_item with extended_seq_item:

class test extends uvm_test;
  ...
  function void build_phase( uvm_phase phase );
    ...
    set_type_override_by_type( base_seq_item::get_type(), extended_seq_item::get_type() );
    ...
    // create test evn
    ...
  endfunction
endclass

Inside my sequence, I want to randomize property addr using knob:

class test_sequence extend uvm_sequence#(base_seq_item);
  // factory registration
  ...
  // constructor
  ...
  task body;
    base_seq_item req;
    uvm_table_printer printer_h;
    begin
      req = base_seq_item::bype_id::create("req");
      `uvm_info( "", $sformatf( "Printing req sequence item:\b%s", req.sprint(printer_h) ), UVM_LOW )
      start_item(req);
      void'( req.randomize() with { req.knob == LOW } );
      finish_item(req);
      ... 
    end
  endtask
endclass

the compiler complains that knob is not a class item of base_seq_item, which makes sense to me. However, if this is what I want to do, meaning building more constraints using a new property in an extended class, how can I work around this?

Any suggestion is appreciated!!!

You can further extend the extended_seq_item class adding or overriding more constraints. Then you can replace the factory override with that extended class. (or some other mechanism that overrides the override).

You can also extend your test_sequence class replacing the body method to have a new randomize with constraint.

I prefer the first suggestion and not use the with clause. It is in better keeping with object-oriented programming practices.

In reply to dave_59:

Thanks for your suggestion, Dave! I’m going to try it out!

In reply to Minzhen:

Hi Dave,

I ran below code to access the override class properties but i am unable to achieve this.Could you please help me how to access properties of override class…

class driver extends uvm_driver;
`uvm_component_utils(driver)
//new
endclass

class driver_extended extends driver;
`uvm_component_utils(driver_extended)

 string str_val ="RAM";

//new
endcalss

class agent extends uvm_component;
`uvm_component_utils(agent)
driver drv;
//new
function build();
 drv = driver::type_id::create("drv",this);
endfunction

endclass

class test_factory extends uvm_test;
 agent ag1;
 function new(string name="test",uvm_component parent=null);
  factory.set_type_override_by_type(driver::get_type(),driver_extended::get_type(),"*"); // overriding component
  ag1 = agent::type_id::create("ag1",this);
 endfuction

 task run();
  `uvm_info("VALUE",$psprintf("%s",ag1.drv.str_val),UVM_LOW)
  #100;
  global_stop_request();
 endtask
endclass

For above code,compiler complains as below
str_val is not a class item.

In reply to brambabu:

If you want to access str_val, then you have to have to use a class variable that knows it exists. Also, move your code from OVM to UVM.

task run_phase(uvm_phase phase);
  driver_extended drv_ext;   
  phase.raise_objection(this);
  if(!$cast(drv_ext, ag1.drv)) `uvm_error("OOPS","driver override did not work") 
  `uvm_info("VALUE",$psprintf("%s",drv_ext.str_val),UVM_LOW)
  #100;
  phase.drop_objection(this);
 endtask

In reply to dave_59:

Thanks a lot Dave…Its working now.

In reply to dave_59:

In reply to brambabu:
If you want to access str_val, then you have to have to use a class variable that knows it exists. Also, move your code from OVM to UVM.

task run_phase(uvm_phase phase);
driver_extended drv_ext;   
phase.raise_objection(this);
if(!$cast(drv_ext, ag1.drv)) `uvm_error("OOPS","driver override did not work") 
`uvm_info("VALUE",$psprintf("%s",drv_ext.str_val),UVM_LOW)
#100;
phase.drop_objection(this);
endtask

Hi Dave,
If the handle to the extended class (drv_ext) is declared, and the same is used to access the variable str_val, where is the override feature coming into picture here? What is the requirement to override, if the declared handle of the extended class is used to access the properties of the extended class, in this scenario?

In reply to n.s.suhas:

The test_factory class knows that it has overridden the driver in the agent, but the agent is unaware of the override. The point of OOP is that we can use inheritance in a way that makes code re-usable. If the only thing we override in a class is virtual methods and constraints, their’s no need to access the object with the extended class variable.

In reply to dave_59:
Hi Dave,

I didn’t get ur below statement. Could u please elaborate more on it?

In reply to n.s.suhas:
If the only thing we override in a class is virtual methods and constraints, their’s no need to access the object with the extended class variable.

Thanks,
H.Modh

In reply to bdreku:

I think you need to study more how Object Oriented Programming works. Search for topics on inheritance and polymorphism.

In reply to bdreku:

Let me try explain this:

class agent extends uvm_component;
`uvm_component_utils(agent)
**driver drv;**
//new
function build();
 drv = driver::type_id::create("drv",this);
endfunction
 
endclass
 
class test_factory extends uvm_test;
 agent ag1;
 function new(string name="test",uvm_component parent=null);
  **factory.set_type_override_by_type(driver::get_type(),driver_extended::get_type(),"*"); // overriding component**
  ag1 = agent::type_id::create("ag1",this);
 endfuction
 
endclass

look in test_factory you override driver with driver_extended, using factory. That is good, now everywhere instead of driver object the driver_extended will be used. Everywhere, but agent class.
Look on agent class (bold line). Here you explicitly define drv as “driver” type object. And no factory method can override it, because you explicit define it (without using factory). So for agent class the drv instance is “driver” object type. This is how agent class understands it.
Even though after factory override the drv type is driver_extended, but still for agent class drv is driver type object.
To workaround this we need to user Dave suggested method.

Hi Dave,
How to assign the drv_ext.str_val with a new val from the test_factory which extends the uvm_test? Below seems not working. It only assigns the new_val to the drv_ext not ag1.drv object?

if(!$cast(drv_ext, ag1.drv)) `uvm_error("OOPS","driver override did not work") 
 drv_ext.str_val = "new_val";
  `uvm_info("VALUE",$psprintf("%s",drv_ext.str_val),UVM_LOW)

The point here was str_val only exists in the extended driver. You need an extended driver class variable to reference it even though the handle in the ag1.drv variable has a handle to it.