关于uvm_callback使用的小结

         在使用synopsys的VIP时,会经常使用到VIP自带的callback方法,对DUT进行不同方式的注错,就和注水牛肉一样,通过针管向牛肉里注水达到增重的目的,而callback是通过driver向DUT注入错误,达到测试DUT遇到异常激励时的行为的目的(当然你说在monitor中能不能这么干,当然也是可以的,问题的关键在于你要做什么)。下面是如何在环境中使用callback的一个小例子:

1,建立一个callback class基类

class xxx_base_callback extends uvm_callback;
    `uvm_object_utils(xxx_base_callback)
    function new (string name = "xxx_base_callback");
        super.new(name);
    endfunction
    virtual task print_item(xxx_item  item);
endclass

类似于抽象类,这个基类就相当于一个模板,我们所有要用到的callback类都扩展于此,通过重载print_item 这个函数来实现不同的callback内容。

2,扩展这个基类,制作第一个callback类

class xxx_print_callback extends xxx_base_callback;
    `uvm_object_utils(xxx_print_callback)
    function new (string name = "xxx_print_callback");
        super.new(name);
    endfunction
    virtual task print_item(xxx_item  item);
        item.print();
    endtask : print_item
endclass

上面这个 callback class中我们重载了 print_item 函数,在函数内用自带的print函数将 sequence_item 打印了出来。

3,在driver中注册这个callback方法

typedef class xxx_base_callback    
//注意这里很重要,相当于告诉driver,我这里有一个class类型的变量要用,你先记着,我后面告诉你什么,
//不然在这里会出现编译的问题,简单的说一下,有时候,我们会在callback类中的 task内做一些奇怪的事情,
//比如说把driver传进来,然后再用driver中的一些信号标志位,用来注入错误,为了避免编译driver时 
//callback还未定义的情况(callback肯定会在后面编译进来),所以这里提前编译了callback

class xxx_tx_driver extends uvm_driver#(xxx_item);

    `uvm_component_utils_begin(xxx_tx_driver)
        ...
        ...
        ...
    `uvm_component_utils_end

    `uvm_register_cb(xxx_tx_driver,xxx_base_callback)

virtual task main_phase(uvm_phase phase);
    seq_item_port.get_next_item(item);
    `uvm_do_callbacks(xxx_tx_driver,xxx_base_callback,print_item(item))
    seq_item_port.item_done();
endtask : main_phase

endclass

我们对比看一段源码中的例子:

//| virtual class mycb extends uvm_callback;
//|   virtual function void doit();
//| endclass
//|
//| class my_comp extends uvm_component;
//|   `uvm_register_cb(my_comp,mycb)
//|   ...
//|   task run_phase(uvm_phase phase);
//|     ...
//|     `uvm_do_callbacks(my_comp, mycb, doit())
//|   endtask
//| endclass
//-----------------------------------------------------------------------------

`define uvm_register_cb(T,CB) \
  static local bit m_register_cb_``CB = uvm_callbacks#(T,CB)::m_register_pair(`"T`",`"CB`");

这部分完全仿照源码中的例子去实现callback再driver中的注册和使用。有一点不懂的时,为什么这里要使用callback的基类?

4,在testcase中创建并登记callback

class xxx_testcase extends uvm_test

xxx_print_callback  xxx_print_callback_u;
`uvm_component_utils(xxx_testcase)

function new (string name = "xxx_testcase", uvm_component parent = null)
    super.new(name,parent);
endfunction : new


virtual function build_phase(uvm_phase phase);
    super.build_phase(phase);
    xxx_print_callback_u = xxx_print_callback::type_id::create("xxx_print_callbakc_u");
endfunction : build_phase

virtual function connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    uvm_callbacks#(xxx_tx_driver,xxx_print_callback)::add(env.agent.driver,xxx_print_callback_u);
endfunction : connect_phase
endclass xxx_testcase

至此,uvm_callback的简单的使用方法就介绍完了,但是在看源码时,还有很多关于callback的方法,像display , delete,等等的方法,仅仅一个非常小的功能,当你阅读源码时发现这仅仅时冰山一角,隐藏在整个UVM源码背后的东西何其多也!!!还有很多我没用到的东西需要我去探索。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值