|
楼主 |
发表于 2015-10-9 20:58:29
|
显示全部楼层
至于uvm中的callback核心机制,本身来说没有什么特别复杂的地方。
要使用uvm callback的功能,说实话我觉得操作起来并不是很爽,步骤也不算少,涉及的宏也不算少。
但是我们可以自己写一个简化版的callback来理解它的基本机制,如下:
typedef class callback ;
/////callbacks类可以看作是一个装类型T的callback的容器
class callbacks#(type T=callback) ;
static local callbacks#(T) _m_inst ; ////对一个类型T,只需要一个容器即可
static local T _next [$] = {}; ////容器的物理载体
local int index ; ////用来遍历容器,在uvm callback中有对应的类似机制,叫做iterator
static function callbacks#(T) get();
if(!_m_inst) _m_inst = new ;
return _m_inst ;
endfunction
local function new();
reset_index() ;
endfunction
/////提供给用户的接口,加入自己希望的callback,在testcase中使用
static function void add(T cb);
_next.push_back(cb);
endfunction
//////这两个方法用来遍历容器中的callback
function T get_next();
return _next[index++] ;
endfunction
function void reset_index();
index = 0 ;
endfunction
endclass
/////这个宏用来简化打算使用callback的class的一些申明
`define callback_registry(T) \
local callbacks#(T) hook = callbacks#(T)::get() ; \
local T each ;
/////这个宏用来简化callback的使用,在uvm中有类似的宏做类似的事情
`define do_callback(T,METHOD) \
each = hook.get_next() ;\
while(each)begin \
each.METHOD ; \
each = hook.get_next() ;\
end \
hook.reset_index();
//////打算使用callback的类
class driver ;
`callback_registry(callback)
function void run();
`do_callback(callback,pre_do)
$display("call driver's run()...");
`do_callback(callback,post_do)
endfunction
endclass
//////用户定义的callback类及其界面
class callback ;
virtual function void pre_do();
endfunction
virtual function void post_do();
endfunction
endclass
/////下面几个真正用来扩展功能的callback派生类
/////注意,有几个callback点就只需要几个派生类,而不再需要各种组合了!
class pre_callback extends callback;
function void pre_do();
$display("call pre_callback's pre_do()...");
endfunction
endclass
class post_callback extends callback;
function void post_do();
$display("call post_callback's post_do()...");
endfunction
endclass
/////testcase类
class testcase ;
driver drv ;
function new();
drv = new ;
endfunction
/////本testcase需要扩展pre_do和post_do
virtual function build();
pre_callback pre_cb = new() ;
post_callback post_cb = new() ;
callbacks#(callback)::add(pre_cb) ;
callbacks#(callback)::add(post_cb) ;
endfunction
function void run();
drv.run();
endfunction
endclass
////两外一个testcase类
class testcase2 extends testcase ;
/////本testcase只需要扩展post_do
virtual function build();
post_callback post_cb = new();
callbacks#(callback)::add(post_cb) ;
endfunction
endclass
个人结论:
callback点的设置需要个人的项目经验、项目需求、项目成熟度来决定,没有特定的公式可以套用;
在不是必须的情况下还是使用继承+factory overwrite比较容易和直观。 |
|