Callback

SV中的回调(callback)明确了定义方法的规则,并且指定了一个方法用来回调已经定义的该方法;简而言之就是,被调用的方法就是回调方法(callback method),调用回调方法的方法称为回调勾(callback hook),回调方法一般是虚方法(dummy method),一般通过继承来进行覆盖重写.

我们来看回调方法是如何工作的:

 

在上面的图中,temp()方法就是回调勾,callback_1()和callback_2()方法是回调方法,也就是在用户调用temp()方法的时候,callback_1()和 callback_2()会自动调用;当然,用户也可以通过继承来覆盖回调方法;

在SV中最长用到的回调勾就是randomize()方法,它带有两个回调方法pre_randomize()和post_randomize(),这两个方法分别会在randomize()方法的前后执行.

UVM callback 

在UVM中,我们通过uvm_callback来派生出回调方法类,在这个类中可以定义多个回调方法,这些方法都是虚方法.如下:

class driver_callback extends uvm_callback;
   
  `uvm_component_utils(driver_callback)
   
  function new(string name, uvm_component parent);
    super.new(name);
  endfunction
   
  virtual task pre_drive; endtask//定义了两个虚方法作为回调方法
  virtual task post_drive; endtask
endclass

在上面的回调类driver_callback中定义了两个回调方法pre_drive和post_drive.

为了使用定义的回调类中的回调方法,首先要通过宏`uvm_register_cb在相应的组件中注册,然后再使用宏`uvm_do_callbacks 在组件的方法中调用回调方法,如下所示:

class driver extends uvm_component;
   
  `uvm_component_utils(driver)
  `uvm_register_cb(driver,driver_callback)//注册回调类
   
  function new(string name, uvm_component parent);
    super.new(name,parent);
  endfunction
   
  task run_phase(uvm_phase phase);
      `uvm_do_callbacks(driver,driver_callback,pre_drive());//调用类中的回调方法
       
      drive_pkt();
       
      `uvm_do_callbacks(driver,driver_callback,post_drive());
  endtask
   
  task drive_pkt();
    `uvm_info("DRIVER","Inside drive_pkt method",UVM_LOW);
  endtask
   
endclass

所以简单的test如下:

 

class environment extends uvm_env;
  driver driv;
  
  `uvm_component_utils(environment)
  
  function new(string name, uvm_component parent);
    super.new(name,parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    driv = driver::type_id::create("driv", this);
  endfunction
  
endclass

class basic_test extends uvm_test;
  environment env;
  
  `uvm_component_utils(basic_test)
  
  function new(string name = "basic_test", uvm_component parent=null);
    super.new(name,parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    env = environment::type_id::create("env", this);
  endfunction
endclass

//testbench
`include "driver_callback.sv"
`include "driver.sv"
`include "environment.sv"
`include "basic_test.sv"


program testbench_top;
  
  //---------------------------------------
  //calling test
  //---------------------------------------
  initial begin//{
    run_test();
  end //}
  
endprogram

这样我们就将回调方法加入到整个testbench中了,只不过上面的回调方法为空方法,什么操作也没有; 

还可以通过继承,覆盖上面定义的回调类中的回调方法,如下:

class user_callback extends driver_callback;
   
  `uvm_component_utils(user_callback)
   
  function new(string name, uvm_component parent);
    super.new(name,parent);
  endfunction
   
  task pre_drive;
    `uvm_info("USER_CALLBACK","Inside pre_drive method",UVM_LOW);
  endtask
   
  task post_drive;
    `uvm_info("USER_CALLBACK","Inside post_drive method",UVM_LOW);
  endtask
endclass

对于派生的回调类以及其中覆盖的回调方法,只需要通过调用add()方法将回调类添加到test中即可,如下:

 

class user_callback_test extends basic_test;
  user_callback callback_1;
   
  `uvm_component_utils(user_callback_test)
   
  function new(string name = "user_callback_test", uvm_component parent=null);
    super.new(name,parent);
  endfunction
   
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    callback_1 = user_callback::type_id::create("callback_1", this);
     
    uvm_callbacks#(driver,driver_callback)::add(env.driv,callback_1);
  endfunction
endclass

对于uvm_callbacks#(T, CB)::add(t,cb)方法,其几个参数的含义如下:

T:表示回调类所在的组件名;

CB:表示回调类的类名;

t:表示回调类所在的组件的实例名,也就是组件的对象名;

cb:表示回调类的实例名,也就是对象名;

 导入上面的模块,如下:

`include "driver_callback.sv"
`include "driver.sv"
`include "environment.sv"
`include "basic_test.sv"

`include "user_callback.sv"
`include "user_callback_test.sv"

program testbench_top;
  
  //---------------------------------------
  //calling test
  //---------------------------------------
  initial begin//{
    run_test();
  end //}
  
endprogram

运行结果为:

总结上面在UVM中使用回调的方法步骤:

(1) 由uvm_callback派生出一个回调类A,这个类中包含若干个回调方法,且这些方法都是空的;

(2)将回调类A在对应的组件中通过宏`uvm_register_cb在相应的组件中注册,然后再使用宏`uvm_do_callbacks 在组件的方法中调用回调方法;

(3)由A派生出回调类的子类B,在该类中对回调方法进行覆盖重写,可以用户自定义回调方法的操作;

(4)在test中将B实例化,并将实例化后的对象通过uvm_callbacks#(T, CB)::add(t,cb)方法添加到组件中,这就实现了回调方法的具体操作;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值