uvm_callback介绍
- 除了UVM提供新的类方便组件之间的同步之外,另外一种同步方式回调函数(callback)也方便了类的封装复用。
- 通常情况下得到了一个封闭的包,其中的类如果有些成员方法需要修改,或者需要扩展新的方法时,应该怎么做呢?如果这个包是外来的,那么维护方法不建议去修改这个类本身。
- 如果我们通过类的继承来满足这一要求,又无法在该包环境中用新的子类替换原来的父类,那么UVM的覆盖机制(override)可以帮忙。
- 除了覆盖机制,还有callback也可以为用户提供自定义的处理方法,这就使得如果用户不需要添加新方法,而是想延展之前的方法,就无需通过继承类的方式而只需要通过在后期定义callback方法来实现。
- 通过这个新添加的类,使得函数回调有了顺序和继承性。关于顺序和继承性的实现,UVM是通过两个相关类uvm_callback_iter和uvm_callbacks #(T, CB)来实现的。
cfass edata extends uvm_object;
int data;
'uvm_object_utils (edata)...
endclass
class cb1 extends uvm_callback;
'uvm_object_utils (cb1)
...
virtual function void do_trans (edata d) ;
d.data = 200 ;
' uvm_info("CB",$sformatf("cb1 executed with data 80d", d.data),UVM_LOW)
endfunction
endclass
class cb2 extends cb1;
'uvm_object_utils (cb2)
function void do _trans (edata d) ;
d.data = 300 ; .
'uvm _info("CB",$sformatf ("cb2 executed with data %0d" , d.data),UVM_LOW)
endfunction
endclass
class comp1 extends uvm_component;
'uvm_component_utils ( comp1)
`uvm_register_cb ( comp1,cb1) //对callback进行了注册
...
task run_phase (uvm _phase phase) ;
edata d = new ( ) ;
d.data = 100 ;
'uvm_info("RUN",$sformatf ( "proceeding data %0d", d.data),UVM_LOW)
`uvm_do_callbacks (comp1, cb1, do_trans (d) ) //插入callback
endtask
endclass
class env1 extends uvm_ env;
comp1 cl;
cb1 m_cb1;
cb2 m cb2;
’uvm_component_utils (env1)
function new (string name,uvm_component parent);
super.new (name, parent) ;
m_cb1 = new ( "m_cb1") ;
m_cb2 = new ( "m_cb2");
endfunction
function void build_phase (uvm_phase phase) ;super.build_phase (phase) ;
cl = compl : :type_id: : create ( "c1", this) ;
uvm_callbacks # ( comp1 ) : : add (c1,m_cb1) ;
uvm_callbacks # ( comp1 ) : : add (c1, m_cb2) ;
endfunction : build phase
endclass
- 第一步在组件中定义callback
- 第二步要绑定和插入callback
- 第三步添加callback
uvm_callback总结
uvm_callback类使得钩子属性变得更加容易控制和继承,有需要注意的地方:
- uvm_callback可以通过继承的方式来满足用户更多的定制,例如上面的cb2继承于cb1
- 为了保证调用uvm_callback的组件类型T与uvm_callback类型CB保持匹配,建议用户在T中声明T与CB的匹配,该声明可以通过宏`uvm_register_cb(T, CB)来实现。在用户养成注册的习惯之后,如果以后调用的T与CB不匹配,那么在检查完匹配注册表之后系统会打印warning信息,提示用户使用回调函数的潜在问题。
- uvm_callback建立了回调函数执行的层次性,因此在实现方面,不再是在T的方法中直接呼叫某一个回调方法,而是通过宏`uvm_do_callbacks(T, CB, METHOD)来实现。该宏最直观的作用在于会循环执行已经与该对象结对的uvm_callback类的方法。此外宏uvm_do_callbacks_exit_on(T,CB,METHOD,VAL)可以进一步控制执行回调函数的层次,简单来讲,回调函数会保持执行直到返回值与给入的VAL值相同才会返回,这一点使得回调方法在执行顺序上面有了更多的可控性。
- 有了`uvm_do_callbacks宏还不够,需要注意的是,在执行回调方法时,依赖的是已经例化的uvm_callback对象。所以最后一步需要例化uvm_callback对象,上面的例子中分别例化了cbl和cb2,通过“结对子”的方式,通过uvm_callbacks #(T,CB)类的静态方法add()来添加成对的uvm_object对象和uvm_callback对象。