在 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_h
是 agent_a
类型,因此它不包含这样的字段。
首先,你不能用agent_c
覆盖agetn_a
。那些 classes 是不相关的,没有办法使用工厂覆盖来做到这一点。您将在此处收到 run-time 个错误。
在 object-oriented 编程中,为了通过基 class 指针对派生的 class object 执行某些操作,您应该使用虚函数。
我在下面的修改代码中演示了这两点。
- 创建了一个虚函数getField()
- 使用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,那么您可以使用 drv 或 drv2[= 覆盖它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);
我正在尝试了解 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_h
是 agent_a
类型,因此它不包含这样的字段。
首先,你不能用agent_c
覆盖agetn_a
。那些 classes 是不相关的,没有办法使用工厂覆盖来做到这一点。您将在此处收到 run-time 个错误。
在 object-oriented 编程中,为了通过基 class 指针对派生的 class object 执行某些操作,您应该使用虚函数。
我在下面的修改代码中演示了这两点。
- 创建了一个虚函数getField()
- 使用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,那么您可以使用 drv 或 drv2[= 覆盖它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);