在 UVM 中覆盖后如何获得 属性 的 class 句柄?

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

我正在尝试了解 UVM 覆盖。 我做了一个简单的覆盖示例,如下所示

    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

当我运行上面模拟的时候。我遇到以下错误消息。

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

如果我也了解覆盖,我可以使用 agent_c class 代替 agent_a 覆盖后。

然后agent_aagent_a_h;变成 agent_c agent_a_h;

然后就可以正常显示agent_a_h.field了。

但为什么说“字段”不是 class 项目?

#update 从派生 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

我更新了上面的代码,为了弄清楚如果有 2 class extended uvm_agent 会怎么样, ################################################## ################

如果我想将 drv2 class 添加到旧测试台(drv class),
drv2 class 和 drv 之间是否无法覆盖? 我是否必须将下面的 drv2 class 添加到 drv class 层次结构中的 C orc D?

agent_a_hagent_a 类型,因此它不包含这样的字段。

首先,你不能用agent_c覆盖agetn_a。那些 classes 是不相关的,没有办法使用工厂覆盖来做到这一点。您将在此处收到 run-time 个错误。

在 object-oriented 编程中,为了通过基 class 指针对派生的 class object 执行某些操作,您应该使用虚函数。

我在下面的修改代码中演示了这两点。

  1. 创建了一个虚函数getField()
  2. 使用agent_b覆盖
`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

回答你的更新:无法用non-related覆盖base class drv class drv2。覆盖的 classes 必须具有 parent/child 类型关系才能实现。

但是在你的情况下,他们有一个共同点uvm_agentclassparent。如果您使用 it 作为基础 class,那么您可以使用 drvdrv2[= 覆盖它78=].

这意味着您必须做出相应的计划。

======================= 这是对您的评论问题的一些额外解释。当前您具有以下类型继承:

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

您使用 agent_a 作为基指针:agent_a agent_a_h; 这允许您使用 agent_b 覆盖 agent_a =58=]agent_a_h。基本上,工厂创建一个 agent_b 类型的 object 并将其分配给其超级 class 类型 (agent_a) 的句柄。

这不能用 agent_c 来完成,因为 agent_a 不是它的基础 class .

要解决此问题,您应该注意到 uvm_agent 最终是所有这些 class 的基础 class。因此,它可以在覆盖中使用:

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

没有uvm可以表示如下

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

现在,问题是 uvm_agent class 是一个 third-party 库 class 并且没有任何你关心的成员,例如'display'

我建议的解决方案遵循以下方案:

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

其中 my_agent 是一个包含您需要的函数的虚拟 class:

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; ...

在这种情况下,您可以将 my_agent 作为基本句柄,并覆盖树中的任何 class 类型:

覆盖:

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