UVM Callback

Callbacks

What is Callback?

Callbacks are empty methods with a call to them.

UVM Callback
UVM Callback

Before Starting with UVM Callbacks, It is good to go through  SystemVerilog Callback.

Where callbacks can be implemented?

Callbacks can be implemented in an object or component.

What are the benefits of callback?

Different flavors of the component can be obtained by customizing the empty callback methods.

About UVM Callbacks

UVM provides a set of classes, methods, and macros to implement the callbacks.

Only the required callback methods are explained here.

Callback Example

With a simple driver example will see to UVM Callback.
Below are components of example,

  • Driver
  • Environment
  • Test
uvm testbench without callback
uvm testbench without callback

The driver has drive() task, which revives the seq_item and drives to DUT (Current example code doesn’t have any logic to receive and drive seq_item).

In this example,
With help of callback, will add pre_drive() and post_drive() callbacks.

uvm testbench with callback
uvm testbench with callback

TestBench without callbacks

Driver

class driver extends uvm_component;
  
  `uvm_component_utils(driver)
  
  function new(string name, uvm_component parent);
    super.new(name,parent);
  endfunction
  
  task run_phase(uvm_phase phase); 
      drive_pkt();
  endtask
  
  task drive_pkt();
    `uvm_info("DRIVER","Inside drive_pkt method",UVM_LOW);
  endtask
  
endclass

Environment

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

TestCase

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

Simulator Output:

UVM_INFO @ 0: reporter [RNTST] Running test basic_test...
UVM_INFO driver.sv(18) @ 0: uvm_test_top.env.driv [DRIVER] Inside drive_pkt method

Click to execute on   

TestBench with callbacks

For easy understanding will see through below steps,

  • Adding callback support
  • Implementing the callback methods
  • Using callback

Adding Callback Support

In order to have user-defined callbacks,

  • User has to write user-defined callback class by extending the uvm_callback class
class driver_callback extends uvm_callback;
  ...
endclass
  • Define callback methods in user-defined callback class
    • In this example pre_drive() and post_drive() are the callback methods.
  virtual task pre_drive; endtask
  virtual task post_drive; endtask

Complete user-defined class code

class driver_callback extends uvm_callback;
  
  `uvm_object_utils(driver_callback)
  
  function new(string name = "driver_callback");
    super.new(name);
  endfunction
  
  virtual task pre_drive; endtask
  virtual task post_drive; endtask
endclass

In order to use callbacks defined,

  • Callback class has to be registered with the object/component where callbacks are going to be used.
  • Callback class can be registered by using macro `uvm_register_cb
  `uvm_register_cb(driver,driver_callback)

In order to call the callback methods,

  • Need to place method call’s (callback hook) to methods defined in user-defined callback class (pre_drive() and post_drive())
  • Callback methods can be called by using macro `uvm_do_callbacks
  `uvm_do_callbacks(driver,driver_callback,pre_drive());
  `uvm_do_callbacks(driver,driver_callback,post_drive());

Complete driver code

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

Implementing Callback Method

We have looked into, how to define the callback methods (In user-defined callback class) and placing hook to callback methods (In driver class using `uvm_do_callbacks macro)

Here will see how to add logic to callback methods.

  • Need to extend the user-defined callback class and write one more callback class callback_1
class user_callback extends driver_callback;
  ...
endclass
  • Implement the methods with logic in it (this example we are adding only display’s)
  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

Complete callback class code

class user_callback extends driver_callback;
  
  `uvm_object_utils(user_callback)
  
  function new(string name = "user_callback");
    super.new(name);
  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

Using Callback

In the testcase where callbacks need to be applied,

  • Declare and create an object of callback class in which methods are implemented (callback_1).
  user_callback callback_1;
  callback_1 = user_callback::type_id::create("callback_1", this);
  • In order to execute the callback method, register the callback object to the driver using the ‘add’ method
  uvm_callbacks#(driver,driver_callback)::add(env.driv,callback_1);

Complete testcase code

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

callback_test is the test with callbacks added, and basic_test is without callbacks.
Simulator Output:

UVM_INFO @ 0: reporter [RNTST] Running test basic_test...
UVM_INFO driver.sv(23) @ 0: uvm_test_top.env.driv [DRIVER] Inside drive_pkt method

Click to execute on   

callback_test simulator output (With Callback)

UVM_INFO @ 0: reporter [RNTST] Running test user_callback_test...
UVM_INFO user_callback.sv(14) @ 0: reporter [USER_CALLBACK] Inside pre_drive method
UVM_INFO driver.sv(23) @ 0: uvm_test_top.env.driv [DRIVER] Inside drive_pkt method
UVM_INFO user_callback.sv(18) @ 0: reporter [USER_CALLBACK] Inside post_drive method

Click to execute on   

With the above result, we could see that displays added in callback methods are getting printed in callback_test.

The addition of logic to the callback methods will give more control on stimulus driving.

In the next example will see an example of how driving stimulus can be controlled using callbacks.

Callback Class and Macros

uvm_callback class

user-defined callback classes can be written by extending the uvm_callback class.
In it, the user defines one or more virtual methods.

These virtual methods are referred to as callback methods, these are empty methods with users have the option of overriding them.

  class CB extends uvm_callback;
    ...
  endclass

uvm_register_cb

`uvm_register_cb(T,CB)

This macro is used to register the Callback (CB) with the Object(T).

Where,
CB => user defined callback class.
T  => Object in which CB is used.

w.r.t above example:
CB => driver_callback class
T    => driver class

uvm_do_callbacks

`uvm_do_callbacks(T,CB,METHOD)

This macro calls the callback methods defined in the user-defined callback class.

CB     => user defined callback class.
T        => Object in which CB is used.
METHOD => callback method to be called

w.r.t above example:

CB => driver_callback class
T    => driver class
METHOD => pre_drive and post_drive

add method

uvm_callbacks#(T, CB)::add(t,cb);

Registers the callback object with the object in which callback is used.

CB   => user defined callback class type.
T      => Object type in which CB is used.
cb     => callback class object
t        => object in which callback is used

w.r.t above example:

CB => driver_callback class
T   => driver class
cb  => callback_1
t     => driver class (differs if multiple objects of same type present)
❮ Previous Next ❯