【问题标题】:How to get property of class handle after override in UVM?在UVM中覆盖后如何获取类句柄的属性?
【发布时间】:2021-09-17 06:22:47
【问题描述】:

我正在尝试了解 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 类代替 agent_a

然后agent_a agent_a_h;变成agent_c agent_a_h;

那么就可以正常显示agent_a_h.field了。

但为什么它说“字段”不是类项?

#更新派生类覆盖的问题

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个类扩展uvm_agent怎么办, ################################################# ################

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

【问题讨论】:

    标签: system-verilog uvm


    【解决方案1】:

    agent_a_h 的类型为agent_a,因此它不包含此类字段。

    首先,您不能用agent_c 覆盖agetn_a。这些类是不相关的,没有办法使用工厂覆盖来做到这一点。您将在此处收到运行时错误。

    在面向对象编程中,为了通过基类指针对派生类对象做某事,你应该使用虚函数。

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

    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
    

    回答您的更新:无法用不相关的类 drv2 覆盖 基类 drv。覆盖的类必须具有父/子类型关系才能做到这一点。

    但在您的情况下,它们有一个共同的 uvm_agent 类父级。如果您使用 it 作为基类,则可以使用 drvdrv2 覆盖它。

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

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

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

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

    这不能用 agent_c 完成,因为 agent_a 不是它的基类。

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

       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 类是第三方库类,没有您关心的任何成员,例如'显示'

    我建议的解决方案是遵循这个方案:

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

    其中 my_agent 是一个包含您需要的功能的虚拟类:

    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 作为基本句柄并覆盖树中的任何类类型:

    覆盖:

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

    【讨论】:

    • 我发现1.必须使用Virtual,2.必须在它们之间派生关系才能覆盖。
    • 我有一个关于2的简单问题相对回复。我已经更新了问题。
    • 我更新了答案。
    • 我做了edaplayground.com/x/AztA 的例子。但仍然错误。我是否错过了一些东西(但在你的情况下,它们有一个共同的 uvm_agent 类父类。如果你将它用作基类,那么你可以使用 drv 或 drv2 来覆盖它。)?
    • 是的,基类必须是 uvm_agent,而不是 agent_a。但是 uvm_agent 没有 display 功能。所以,它不会起作用。您要么需要创建自己的从 uvm_agent 派生的基类,例如'my_uvm_agent' 并在其中定义所有虚拟功能。然后您必须将您的代理类设计为派生自 my_uvm_agent。您将其用作覆盖的基类引用。这些都是通用的面向对象编程中使用的技术。
    猜你喜欢
    • 2011-11-06
    • 1970-01-01
    • 2014-01-17
    • 2015-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多