在UVM验证过程中,callback机制最大的用处
- 提高验证平台的可重用性。
- 构建异常的测试用例(test_case)。
call_back机制的使用
- 首先定义一个类A,A类一定要从uvm_callback派生,另外还需要定义一个pre_tran的任务,这个任务的类型一定是个virtual类型的,因为A派生的类需要重载这个任务。
class A extends uvm_callback;
virtual task pre_tran(my_driver drv,ref my_transaction tr);
endtask
endclass
- 接下声明一个A_pool类,A_pool的声明只需要一个typedef语句,在这个声明中除了要指明这是一个A类型的池子外,还要指明这个池子,将会被那个类(my_driver)使用。
typedef uvm_callbacks #(my_driver,A) A_pool;
- 然后需要在my_driver中做声明,与A_pool类似,要指明my_driver和A。
typedef class A;
class my_driver extends uvm_driver#(my_transaction);
`uvm_component_utils(my_driver)
`uvm_register_cb(my_driver,A)
endclass
- 在my_driver的main_phase中调用pre_tran,这里用到uvm_do_callback宏。uvm_do_callback宏的第一个参数是需要使用pre_trans的类的名字,第二个参数是具有pre_trans任务的类名字,第三个参数是调用任务pre_trans以及其任务定义的参数。
task my_driver::main_phase(uvm_phase phase);
while(1)begin
seq_item_port.get_next_item(req);
`uvm_do_callbacks (my_driver,A,pre_trans(this,req));
drive_noe_ptk(req);
seq_item_port.item_done();
end
endtask
//---------------------------------------------callback定义之后----------------------------------------//
- 接下来从A类派生出一个类
class my_callback extends A;
virtual task pre_tran(my_driver drv,ref my_transaction tr);
`uvm_info("my_callback","this is pre_tran task",UVM_MEDIUM)
endtask
`uvm_object_utils(my_callback)
endclass
- 最后在测试用例中将my_callback实例化,并将其加入到A_pool中,这里需要注意的是,my_callback是在connect中完成的,实例化完成后需要将my_cb加入到A_pool中,同时在加入时需要指定是给哪一个my_driver使用的。
function void my_case0::connect_phase(uvm_phase phase);
my_callback my_cb;
super.connect_phase(phase);
my_cb=my_callback::type_id::create("my_cb");
A_pool::add(env.i_agt.drv,my_cb);
endfunction
子类继承父类的callback机制
- 当我们需要通过my_driver派生出新的new_driver时,需要用到子类继承父类的callback机制,具体实现非常简单。可见我们只需要引入一个宏即可。
class new_driver extends my_driver;
`uvm_component_utils(new_driver)
`uvm_set_super_type(new_driver,my_driver)
//这里需要用到宏,第一个参数为子类,第二个参数为父类,他将子类和父类联系在一起。
task new_driver::main_phase(uvm_phase phase);
while(1) begin
seq_item_port.get_next_item(req);
`uvm_info();
`uvm_do_callbacks(my_driver,A,pre_tran(this,req));
driver_one_pkt(req);
seq_item_port.item_done();
end
endtask
- 然后我们只需要在new_driver的顶层例化new_driver即可。
function void buile_phase(uvm_phase phase)
super.build_phase(phase);
drv = new_driver::type_id::create("drv",this);
endfunction