MoniCa
MoniCa

Reputation: 71

How to get property of class handle after override in UVM?

I'm trying to understand UVM Override. I was made a simple Override example as the below

    module test_module ();
`include "uvm_macros.svh"
  import uvm_pkg::*;
 
  class agent_a extends uvm_agent;
    `uvm_component_utils(agent_a)
 
    function new(string name = "agent_a", uvm_component parent = null);
      super.new(name, parent);
    endfunction : new
  endclass : agent_a
 
  class agent_b extends agent_a;
    `uvm_component_utils(agent_b)
 
    string field = "agent_b.field";
 
    function new(string name = "agent_b", uvm_component parent = null);
      super.new(name, parent);
    endfunction : new
  endclass : agent_b
  
    class agent_c extends uvm_env;
      `uvm_component_utils(agent_c)
 
    string field = "agent_c.field";
 
      function new(string name = "agent_c", uvm_component parent = null);
      super.new(name, parent);
    endfunction : new
  endclass : agent_c
  
 
  agent_a agent_a_h;
 
  initial begin
    
    agent_a::type_id::set_type_override(agent_c::get_type());
    factory.print();

    agent_a_h = agent_a::type_id::create("agent_a_h", null);

    $display("field = ", agent_a_h.field);
    
  end
endmodule : test_module

When I ran the above simulation. I encounter below Error message.

    $display("field = ", agent_a_h.field);
                                       |
xmvlog: *E,NOTCLM (testbench.sv,46|39): field is not a class item.

If I understand as well about override, I can use agent_c class instead agent_a after override.

then agent_a agent_a_h; becomes agent_c agent_a_h;

then it could be displayed agent_a_h.field without error .

but why does it say as "field" is not a class item?

#update question for override from derived class

module test_module ();
`include "uvm_macros.svh"
  import uvm_pkg::*;
 
  class agent_a extends uvm_agent;
    `uvm_component_utils(agent_a)
 
    function new(string name = "agent_a", uvm_component parent = null);
      super.new(name, parent);
    endfunction : new
    
    virtual function display();
      $display("agent_a.display1");
    endfunction
    
  endclass : agent_a
 
  class agent_b extends agent_a;
    `uvm_component_utils(agent_b)
 
    string field = "agent_b.field";
 
    function new(string name = "agent_b", uvm_component parent = null);
      super.new(name, parent);
    endfunction : new
    
        
    virtual function display();
      $display("agent_b.display2");
    endfunction
    
    
  endclass : agent_b
  
    class agent_c extends uvm_agent;
      `uvm_component_utils(agent_c)
 
    string field = "agent_c.field";
 
      function new(string name = "agent_c", uvm_component parent = null);
      super.new(name, parent);
    endfunction : new
      
              
    virtual function display();
      $display("agent_c.display3");
    endfunction
    
  endclass : agent_c
  
 
  agent_a agent_a_h;


 
  initial begin

    agent_a::type_id::set_type_override(agent_c::get_type());
    factory.print();

    agent_a_h = agent_a::type_id::create("agent_a_h", null);

   // $display("field = ", agent_a_h.field);
    
    agent_a_h.display();
    
  end
endmodule : test_module

I update code as the above, for figure out What if there are 2 class extended uvm_agent, ##################################################################

What If I want drv2 class to add into old testbench( drv class),
Does it impossible to override between drv2 class and drv? Should I have to add drv2 class below to C orc D in drv class hierachy? enter image description here

Upvotes: 2

Views: 965

Answers (1)

Serge
Serge

Reputation: 12384

agent_a_h is of type agent_a, and as a result, it contains no such field.

First of all, you cannot override agetn_a with agent_c. Those classes are unrelated and there is no way to use factory override to do so. You will get run-time errors here.

In object-oriented programming in order to do something with a derived class objects through a base class pointer, you should use a virtual function.

I demonstrated these 2 points in modified code below.

  1. created a virtual function getField()
  2. used agent_b to override
`include "uvm_macros.svh"

module test_module ();
   import uvm_pkg::*;
   
class agent_a extends uvm_agent;
   `uvm_component_utils(agent_a)
   
   function new(string name = "agent_a", uvm_component parent = null);
      super.new(name, parent);
   endfunction : new
   
   virtual function string getField(); //<<<<<<
      return "";
   endfunction
   
endclass : agent_a
   
class agent_b extends agent_a;
   `uvm_component_utils(agent_b)
   
   string  field = "agent_b.field";
   
   function new(string name = "agent_b", uvm_component parent = null);
      super.new(name, parent);
   endfunction : new
   
   virtual function string getField(); // <<<<<<<
      return field;
   endfunction
endclass : agent_b
      
   agent_a agent_a_h;
   
   initial begin
      agent_a::type_id::set_type_override(agent_b::get_type()); // <<<<<<
      agent_a_h = agent_a::type_id::create("agent_a_h", null);

      $display("field = ", agent_a_h.getField());
   end
endmodule : test_module

Answering your update: there is no way to override base class drv with an non-related class drv2. The classes for override must have parent/child type relation ship in order for that.

But in your case, they have a common uvm_agent class parent. If you use it as a base class, than you can override it either with drv or drv2.

That means that you have to plan accordingly.

======================= Here is some extra explanation for your comment question. Currently you have the following type inheritance:

uvm_agent --> agent_a
          |   |--> agent_b
          |--> agent_c

You use agent_a as a base pointer: agent_a agent_a_h; This allows you to override agent_a with agent_b when you create agent_a_h. Basically the factory create an object of type agent_b and assigns it to the handle of its super class type (agent_a).

This cannot be done with agent_c because agent_a is not its base class.

To fix this problem you should notice that uvm_agent is eventually a base class for all of those classes. Therefore, it could be used as such in overrides:

   uvm_agent handle;
   ...
   uvm_agent::type_id::set_type_override(agent_X::get_type());
   handle = uvm_env::type_id::create("agent_X_handle", null);

without uvm it could be expressed as the following.

   uvm_agent handle;
   agent_X agent_X_h = new;
   handle = agent_X_H;

Now, the problem is that the uvm_agent class is a third-party library class and does not have any of the members which you care about, e.g. 'display'

The solution I suggested is following this scheme:

uvm_agent --> my_agent  --> agent_a
                        |   |--> agent_b
                        |--> agent_c

where my_agent is a virtual class containing the functions you need:

class my_agent extends uvm_agent;
     virtual function void display();
     endfunction
     ...
endclass
class agent_a extends my_agent; ...
class agent_b extends agent_a; ...
class agent_c extends my_agent; ...

In this case you can have my_agent as a base handle and do your overrides to any of the class types in the tree:

overrides:

   my_agent handle;
   ...
   my_agent::type_id::set_type_override(agent_X::get_type());
   handle = my_agent::type_id::create("agent_X_handle", null);

Upvotes: 2

Related Questions