Reputation: 71
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?
Upvotes: 2
Views: 965
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.
`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