1.处理同一种协议,做不同的事,封装成agent。所以,不同的agent代表了不同的协议。
`ifndef MY_AGENT__SV
`define MY_AGENT__SV
class my_agent extends uvm_agent ;
my_driver drv;
my_monitor mon;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
extern virtual function void build_phase(uvm_phase phase);
extern virtual function void connect_phase(uvm_phase phase);
`uvm_component_utils(my_agent)
endclass
function void my_agent::build_phase(uvm_phase phase);
super.build_phase(phase);
if (is_active == UVM_ACTIVE) begin
drv = my_driver::type_id::create("drv", this);
end
mon = my_monitor::type_id::create("mon", this);
endfunction
function void my_agent::connect_phase(uvm_phase phase);
super.connect_phase(phase);
endfunction
`endif
1)uvm_agent是component,要用uvm_component_utils宏注册。
2)用is_active决定是否创建driver。is_acitve是uvm_agent的成员变量。uvm_agent.svh源代码如下:
3)uvm_active_passive_enum是枚举类型:原型为:(注释说通常用在agent)
4)uvm_agent中,is_active默认是UVM_ACTIVE,例化driver的。其实可以在is_active 中做别的,只是这个例子例化了driver。
5)UVM_PASSIVE的情况,agent不需要驱动任何信号,只要检测信号。
2.把driver 和monitor 封装成 agent后,在env中只要例化agent,不需要例化driver和 monitor 了,因为这两个的例化是在agent完成的,如下:
`ifndef MY_ENV__SV
`define MY_ENV__SV
class my_env extends uvm_env;
my_agent i_agt;
my_agent o_agt;
function new(string name = "my_env", uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
i_agt = my_agent::type_id::create("i_agt", this);
o_agt = my_agent::type_id::create("o_agt", this);
i_agt.is_active = UVM_ACTIVE;
o_agt.is_active = UVM_PASSIVE;
endfunction
`uvm_component_utils(my_env)
endclass
`endif
1)例化后,要指定各自的工作模式 active or passive。
2)UVM树结构如下:
3.由于agent加入,driver和monitor的层次改变了,top_tb中config_db如下:
initial begin
uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.i_agt.drv", "vif", input_if);
uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.i_agt.mon", "vif", input_if);
uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.o_agt.mon", "vif", output_if);
end
4.UVM要求uvm树最晚在build_phase时完成,如果在build_phase后的某个phase例化一个component:
1)编译pass:仿真error:
5也不是只能在build_phase中例化。在之前可以,比如agent 的 new 中例化driver 和monitor,如下:
1)这样的问题是:无法通过直接赋值的方式向uvm_agent传递is_active的值。在my_env的build_phase中向i_agt 和 o_agt 的is_active赋值根本没效果。默认都是active。
2)原因(猜的):
2.1)正常情况下执行顺序:env的build_phase->create->赋值->agent的build_phase->判断赋值情况,ok。
2.2)错误情况下执行顺序:env的build_phase->create->这个create直接调用了agent的new(猜的)->agent的new 判断赋值情况->这个时候env还没有赋值呢,在后两行,默认创建。所以即使赋值也没用。
仿真报错:
它说o_agt 的drv 怎么怎么样,说明确实例化了,我们设置的值无效。
6.解决:在my_agent 例化之前用config_db 语句传递is_active的值:(因为提前赋值好了,在判断也有了)
再在agent里取数:
结果:
uvm约定俗成在build_phase做。只要在agent 创建driver 和 monitor之前做,就行!!!