前言
在我们的验证环境中,某个component 需要接多路tlm的需求很常见,比如uvm书上介绍的,SCB需要接两路tlm,一路来自monitor,一路来自refmodel。除此之外,在稍微复杂一点,或者有多路输入输出的环境,我们的refmodel需要接收来自多个agent.mon的trans,然后经过ref之后送到SCB,本文介绍这两种场景的两种实现方法。
方法一:`uvm_analysis_imp_decl(*)
这种方法也是uvm白皮书上介绍的方法,大概流程如下:
(1)通过宏uvm_analysis_imp_decl声明两个后缀_monitor和_model; UVM会根据这两个后缀定义两个新的IMP类-uvm_analysis_imp_monitor和uvm_analysis_imp_model;
(2)在my_scoreboard中声明并实例化uvm_analysis_imp_monitor与uvm_analysis_imp_model, 句柄分别为monitor_imp和model_imp;
(3)当与monitor_imp相连接的analysis_port执行write函数时,会自动调用write_monitor函数; 而与model_imp相连接的analysis_port执行write函数时,会自动调用write_model函数.
`uvm_analysis_imp_decl(_monitor)
`uvm_analysis_imp_decl(_model)
class my_scoreboard extends uvm_scoreboard;
my_transaction tr;
uvm_analysis_imp_monitor#(my_transaction ,my_scoreboard) monitor_imp;
uvm_analysis_imp_model#(my_transaction ,my_scoreboard) model_imp;
extern function void write_monitor(my_transaction tr);
extern function void write_model(my_transaction tr);
endclass
function void my_scoreboard::write_monitor(my_transaction tr);
endfunction
function void my_scoreboard::write_model(my_transaction tr);
endfunction
方法二:uvm_subscriber
uvm_subscriber通常用来收集coverage使用,不过稍微拓展一下就能解决refmodel内多路通信但是只有一个write函数的问题。大致流程如下:
(1)例化一个自己的subscriber:my_subscriber,继承自uvm_subscriber
(2)每路都申明并实例化一个my_subscriber,并且将对应的monitor内的uvm_analsys_port connect到subscriber的export
(3)在my_subscriber内部实现write函数,因为一个write函数只有一个,但是对应多路来源,所以需要在内部根据实例名字来判断。
my_subscriber 代码大致如下:
class my_subscriber #(type Trans = uvm_sequence_item , type Tref = uvm_component) extends uvm_subcriber #(Trans);
`uvm_component_param_utils(my_subscriber #(Trans,Tref));
Tref _ref;
function new(string name = "my_subscriber",uvm_component parent);
super.new(name,parent);
endfunction
function void write(Trans trans);
if(get_name() == "subs_a") begin
_ref.do_write_a();
end
if(get_name() == "subs_b") begin
_ref.do_write_b();
end
endfunction
endclass
refmodel 代码大致如下:
class my_ref extends uvm_component;
`uvm_compnent_utils(my_ref)
my_subscriber #(Trans_a ,my_ref) subs_a;
my_subscriber #(Trans_b ,my_ref) subs_b;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
subs_a = my_subscriber #(Trans_a, my_ref)::type_id::creat("subs_a",this);
subs_a._ref = this;
subs_b = my_subscriber #(Trans_b, my_ref)::type_id::creat("subs_b",this);
subs_b._ref = this;
endfunction
function do_write_a();
endfunction
function do_write_b();
endfunction
endclass