SystemVerilog中的callback(回调)

11 篇文章 2 订阅

一直对callback不是很理解,看了很多资料,发现下面这篇写的很具体并容易理解。转载过来分享给大家。

原文:

SystemVerilog中的callback(回调)

1、什么是callback

callback是SystemVerilog学习者的主要困惑点之一。许多人在许多论坛上都提出了相同的问题,但答案似乎并不能尽如人意。

我们可以将数据成员传递给任何函数。现在考虑一种情况,将一个函数(例如func1)作为数据成员传递给另一个函数(例如func2),并且得到所谓的callback。之所以称为callback,是因为函数func2现在可以在其代码函数func1中的任何地方调用。

如下图所示:

【本文转载者补充:Systemverilog中的callback指定了一个被调用的callback method,和一个调用callback method的callback hook。callback method一般是dummy method,可以通过继承来覆盖。

在上面图中,temp()方法就是callback hook,callback_1()和callback_2()方法是callback method。在用戶调用temp()方法的时候,callback_1()和 callback_2()方法会自动调用,用戶也可以通过继承来覆盖callback method。】

这个是一个基类,其中:

  • temp是一个方法

  • 方法temp中的一些语句还调用了方法callback_1和callback_2,在这其中的两个方法都是虚方法,并不含有任何逻辑。

  • 用户可以在派生类中将所需逻辑添加到方法callback_1和callback_2,不需要更改方法temp。

例如,“randomize”是systemverilog中的一个带有callback的内建方法。randomize方法通过在randomize()前后分别调用pre_randomize()和post_randomize()去实现callback。

方法将按照下面提到的顺序执行,

  • pre_randomize();

  • randomize();

  • pre_randomize();

 2、如何实现callback

实现systemverilog中callback的一种方式如下:

  • 编写一个方法,并且其中调用了其他的虚方法

  • 编写被调用的虚方法,此方法中一般不含有任何逻辑


3、如何使用callback

方法如下:

  • 派生类并且实现callback方法,重写虚方法的内容

  • 通过派生类覆盖基类

4、使用范例

class abc_transactor;
virtual task pre_send(); endtask
virtual task post_send(); endtask

task xyz();
  // Some code here
  this.pre_send();
  // Some more code here
  this.post_send();
  // And some more code here
endtask : xyz
endclass : abc_transactor

class my_abc_transactor extend abc_transactor;
virtual task pre_send();
  ...     // This function is implemented here
endtask

virtual task post_send();
  ...     // This function is implemented here
endtask

endclass : my_abc_transactor

上述代码中,基类含有3个task,其中2个task声明为virtual并且没有任何逻辑,但是这2个task都被另外的task xyz()调用,而xyz()是已经有逻辑代码了的,在这其中,这2个virtual task就被称为callback class。

my_abc_transactor派生自abc_transactor类,并且实现了基类中没有添加任何逻辑的task,这样我们可以直接把需要执行的代码添加到virtual task中而不需要对其进行修改。


还是不懂?那么看个实例:

上图实现的是一个slaver driver,用来对master进行反馈。

其中包括以下组件:

  • slave_driver - Normal driver to drive response 

    • 响应类型为 OKAY, EXOKAY, SLVERR, DECERR

    • slave_driver 被限制始终发送OKAY响应以查看回调用法差异

  • slave_env -在其中创建了slave_driver的环境

  • basic_test - 发送正常响应

  • error_test  - 具有回调方法的测试用例,用于生成错误响应

  • err_inject  - 扩展的驱动程序类,用于实现回调方法


首先,编写slave_driver,并在其中添加空方法,放置挂钩以进行回调,在此示例中,由于需要在响应生成后立即对其进行更改,因此最好在调用randomize方法之后放置回调挂钩:

typedef enum {OKAY, EXOKAY, SLVERR, DECERR} resp_type;
 
class slave_driver;
  resp_type resp;
   
  //callback hook
  virtual task update_resp; 
  endtask
   
  //send response task
  task send_response;
    std::randomize(resp) with { resp == OKAY;};
    update_resp();//hook
  endtask
endclass

 实现callback,首先派生类,完善virtual task:

class err_inject extends slave_driver;
  virtual task update_resp;
    $display("Injecting SLVERR");
    resp = SLVERR;
  endtask
endclass

 使用callback,生成error_test:

program error_test;
  slave_env  env;
  err_inject err_driver;
   
  initial begin
    //Create env
    env = new();
    err_driver = new();
    //Overriding slave_driver by error_driver
    env.slv_driver = err_driver;
     
    //Calling run of env
    env.run();
  end
endprogram

其中slave_env如下:

class slave_env;
  slave_driver slv_driver;
  
  function new();
    slv_driver = new();
  endfunction
  
  //run task to call driver logic
  task run;
    
    repeat(2) begin //{
      slv_driver.send_response();
      $display("Slave generated response is %s",slv_driver.resp.name());
    end //}
  endtask
  
endclass

此外,还添加basic_test如下,以便进行比对:

program basic_test;
  slave_env env;
  
  initial begin
    //Create env
    env = new();
    
    //Calling run of env
    env.run();
  end
endprogram 

在Synopsys VCS 2019.06下进行仿真

  • 当执行basic_test时,输出如下:

  • 当执行error_test时,输出如下:

可见,我们通过调用改变派生类中的virtual task中的内容,可以实现我们特定的内容。可以在不改变现有环境的情况下就实现错误的注入,因此好处如下:

  • 易于向现有逻辑添加其他功能

  • 使组件可重用,扩展类的功能

SystemVerilog的听课学习笔记,包括讲义截取、知识点记录、注意事项等细节的标注。 目录如下: 第一章 SV环境构建常识 1 1.1 数据类型 1 四、二值逻辑 4 定宽数组 9 foreach 13 动态数组 16 队列 19 关联数组 21 枚举类型 23 字符串 25 1.2 过程块和方法 27 initial和always 30 function逻辑电路 33 task时序电路 35 动态 静态变量 39 1.3 设计例化和连接 45 第二章 验证的方法 393 动态仿真 395 静态检查 397 虚拟模型 403 硬件加速 405 效能验证 408 性能验证 410 第三章 SV组件实现 99 3.1 接口 100 什么是interface 101 接口的优势 108 3.2 采样和数据驱动 112 竞争问题 113 接口的时序块clocking 123 利于clocking的驱动 133 3.3 测试的开始和结束 136 仿真开始 139 program隐式结束 143 program显式结束 145 软件域program 147 3.4 调试方法 150 第四章 验证的计划 166 4.1 计划概述 166 4.2 计划的内容 173 4.3 计划的实现 185 4.4 计划的进程评估 194 第五章 验证的管理 277 6.1 验证的周期检查 277 6.2 管理三要素 291 6.3 验证的收敛 303 6.4 问题追踪 314 6.5 团队建设 321 6.6 验证的专业化 330 第六章 验证平台的结构 48 2.1 测试平台 49 2.2 硬件设计描述 55 MCDF接口描述 58 MCDF接口时序 62 MCDF寄存器描述 65 2.3 激励发生器 67 channel initiator 72 register initiator 73 2.4 监测器 74 2.5 比较器 81 2.6 验证结构 95 第七章 激励发生封装:类 209 5.1 概述 209 5.2 类的成员 233 5.3 类的继承 245 三种类型权限 protected/local/public 247 this super 253 成员覆盖 257 5.4 句柄的使用 263 5.5 包的使用 269 第八章 激励发生的随机化 340 7.1 随机约束和分布 340 权重分布 353 条件约束 355 7.2 约束块控制 358 7.3 随机函数 366 7.4 数组约束 373 7.5 随机控制 388 第九章 线程与通信 432 9.1 线程的使用 432 9.2 线程的控制 441 三个fork...join 443 等待衍生线程 451 停止线程disable 451 9.3 线程的通信 458 第十章 进程评估:覆盖率 495 10.1 覆盖率类型 495 10.2 功能覆盖策略 510 10.3 覆盖组 516 10.4 数据采样 524 10.5 覆盖选项 544 10.6 数据分析 550 第十一章 SV语言核心进阶 552 11.1 类型转换 552 11.2 虚方法 564 11.3 对象拷贝 575 11.4 回调函数 584 11.5 参数化的类 590 第十二章 UVM简介 392 8.2 UVM简介 414 8.3 UVM组件 420 8.4 UVM环境 425
在UVM(Universal Verification Methodology)callback回调函数是一种在特定事件发生时自动调用的函数。这些事件可以是UVM定义的一些特定动作,例如创建或删除一个对象,或者在测试用例的不同阶段执行某些操作。 UVM使用callback回调函数的目的是在特定事件发生时执行一些自定义的操作,而不需要修改UVM的源代码。这样可以提高代码的可重用性和灵活性。 在UVMcallback回调函数通常是通过使用UVM提供的`uvm_callback`类来实现的。这个类是一个基类,用户可以从这个基类派生出自己的回调类,并重载其的虚拟函数来实现自定义的操作。例如,用户可以派生一个自己的回调类,并重载`execute`函数来定义在某个特定事件发生时执行的操作。 以下是一个示例代码片段,展示了如何在UVM使用callback回调函数: ```systemverilog class my_callback extends uvm_callback; // 重载execute函数来定义回调函数的操作 virtual function void execute(uvm_object obj); // 在这里编写自定义的操作 $display("Callback function called!"); endfunction endclass // 在需要使用callback回调函数的地方创建一个回调对象 my_callback callback; // 注册回调对象到对应的事件上 my_object.add_callback(callback); // 当事件发生时,回调函数会被自动调用 ``` 在上述示例,我们创建了一个名为`my_callback`的回调类,并重载了`execute`函数。然后,我们创建了一个回调对象`callback`,并将其注册到一个特定的事件上(`my_object.add_callback(callback)`)。当该事件发生时,execute`函数会被自动调用,并执行自定义的操作。 请注意,使用callback回调函数需要遵循UVM的规范和最佳实践。在实际使用,可以根据具体需求来设计和实现自己的callback回调函数
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值