Tutorials

Learn More

The callbacks are used to alter the behavior of the component without modifying its code. The verification engineer provides a set of hook methods that helps to customize the behavior depending on the requirement. A simple example of callbacks can be the pre_randomize and post_randomize methods before and after the built-in randomize method call.

Callback usage

  1. Allows plug-and-play mechanism to establish a reusable verification environment.
  2. Based on the hook method call, the user-defined code is executed instead of the empty callback method.

Simply, callbacks are the empty methods that can be implemented in the derived class to tweak the component behavior. These empty methods are called callback methods and calls to these methods are known as callback hooks.

Callback Example

In the below example, modify_pkt is a callback method and it is being called in the pkt_sender task known as callback hook.

The driver class drives a GOOD packet. The err_driver is a derived class of the driver class and it sends a corrupted packet of type BAD_ERR1 or BAD_ERR2 depending on the inject_err bit.

If the inject_err bit is set, then a corrupted packet will be generated otherwise a GOOD packet will be generated.

Driver code:

typedef enum {GOOD, BAD_ERR1, BAD_ERR2} pkt_type;

class driver;
  pkt_type pkt;
  
  task pkt_sender;
    std::randomize(pkt) with {pkt == GOOD;};
    modify_pkt;
  endtask
  
  virtual task modify_pkt; // callback method
  endtask
endclass

// Error introduction via err_driver class where callback method modify_pkt is implemented.
class err_driver extends driver;
  task modify_pkt;
    $display("Injecting error pkt");
    std::randomize(pkt) with {pkt inside {BAD_ERR1, BAD_ERR2};};
  endtask
endclass

Environment code:

`include "driver.sv"

class env;
  bit inject_err;
  driver drv;
  err_driver drv_err;
  
  function new();
    drv = new();
    drv_err = new();
  endfunction
  
  task execute;
    if(inject_err) drv = drv_err;
    // Sending a packet
    drv.pkt_sender();
    $display("Sending packet = %s", drv.pkt.name());
  endtask
endclass

Output:

Sending packet = GOOD
Sending packet = GOOD
Sending packet = GOOD
Injecting error pkt
Sending packet = BAD_ERR1
Injecting error pkt
Sending packet = BAD_ERR1
Injecting error pkt
Sending packet = BAD_ERR1
Sending packet = GOOD
Sending packet = GOOD
Sending packet = GOOD

System Verilog Tutorials