UVM Callback add method

Callback add method

Add method implementation

static function void add(
T obj,
uvm_callback cb,
uvm_apprepend ordering = UVM_APPEND
)
  • Registers the callback object with the object in which callback is used
  • It is allowed to register multiple callbacks derived from the same callback
  • If ordering is UVM_APPEND (default), the callback will be executed after previously added callbacks, else the callback will be executed ahead of previously added callbacks

Using add method

The previous example shows the usage of the add method.

In order to execute the callback method, the Callback object needs to be registered to the object/component.

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

Multiple add for the same method

To the single callback hook, it is possible to have call to multiple flavors of the same method.
i.e if the same method is implemented in multiple extended classes, then it is possible to register all the methods to the same callback hook.

On calling of `uvm_do_callbacks macro all the callback methods executed in the order which methods are registered.

Example for Multiple flavors of the same method

uvm testbench with callback
uvm testbench with callback

Let’s consider the previous example and implement multiple flavors of the same method.

In the previous example, pre_drive() and post_drive() are callback methods and implemented them in user_callback class.

Now lets implement callback methods in user_callback_1 and user_callback_2 classes by extending driver_callback class.

user_callback_1

Below is user_callback_1 class implemented with displays USER_CALLBACK-1

class user_callback_1 extends driver_callback;
  
  `uvm_object_utils(user_callback_1)
  
  function new(string name = "user_callback_1");
    super.new(name);
  endfunction
  
  task pre_drive;
    `uvm_info("USER_CALLBACK-1","Inside pre_drive method",UVM_LOW);
  endtask
  
  task post_drive;
    `uvm_info("USER_CALLBACK-1","Inside post_drive method",UVM_LOW);
  endtask
endclass

user_callback_2

Below is user_callback_2 class implemented with displays USER_CALLBACK-2

class user_callback_2 extends driver_callback;
  
  `uvm_object_utils(user_callback_2)
  
  function new(string name = "user_callback_2");
    super.new(name);
  endfunction
  
  task pre_drive;
    `uvm_info("USER_CALLBACK-2","Inside pre_drive method",UVM_LOW);
  endtask
  
  task post_drive;
    `uvm_info("USER_CALLBACK-2","Inside post_drive method",UVM_LOW);
  endtask
endclass

Testcase

In the below test case’s user_callback_1 and user_callback_2 are registered using the add method.

user_callback_test

user_callback_1 is registered first and then user_callback_2.

class user_callback_test extends basic_test;
  user_callback_1 callback_1;
  user_callback_2 callback_2;
  
  `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_1::type_id::create("callback_1", this);
    callback_2 = user_callback_2::type_id::create("callback_2", this);
    
    uvm_callbacks#(driver,driver_callback)::add(env.driv,callback_1);
    uvm_callbacks#(driver,driver_callback)::add(env.driv,callback_2);
  endfunction
endclass

user_callback_2_test

Lets write one more testcase user_callback_2_test, with user_callback_2 is registered first and then user_callback_1.

class user_callback_2_test extends basic_test;
  user_callback_1 callback_1;
  user_callback_2 callback_2;
  
  `uvm_component_utils(user_callback_2_test)
  
  function new(string name = "user_callback_2_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_1::type_id::create("callback_1", this);
    callback_2 = user_callback_2::type_id::create("callback_2", this);
    
    uvm_callbacks#(driver,driver_callback)::add(env.driv,callback_2);
    uvm_callbacks#(driver,driver_callback)::add(env.driv,callback_1);
  endfunction
endclass

Simulator Output: (user_callback_test)

UVM_INFO @ 0: reporter [RNTST] Running test user_callback_test...
UVM_INFO user_callback.sv(18) @ 0: reporter [USER_CALLBACK-1] Inside pre_drive method
UVM_INFO user_callback.sv(39) @ 0: reporter [USER_CALLBACK-2] Inside pre_drive method
UVM_INFO slave_driver.sv(23) @ 0: uvm_test_top.env.driver [DRIVER] Inside drive_pkt method
UVM_INFO user_callback.sv(22) @ 0: reporter [USER_CALLBACK-1] Inside post_drive method
UVM_INFO user_callback.sv(43) @ 0: reporter [USER_CALLBACK-2] Inside post_drive method

Simulator Output: (user_callback_2_test)

UVM_INFO @ 0: reporter [RNTST] Running test user_callback_2_test...
UVM_INFO user_callback.sv(39) @ 0: reporter [USER_CALLBACK-2] Inside pre_drive method
UVM_INFO user_callback.sv(18) @ 0: reporter [USER_CALLBACK-1] Inside pre_drive method
UVM_INFO slave_driver.sv(23) @ 0: uvm_test_top.env.driver [DRIVER] Inside drive_pkt method
UVM_INFO user_callback.sv(43) @ 0: reporter [USER_CALLBACK-2] Inside post_drive method
UVM_INFO user_callback.sv(22) @ 0: reporter [USER_CALLBACK-1] Inside post_drive method

Click to execute on   

Form the above simulator output we could see the order of execution of callback methods,

In user_callback_test user_callback_1 method executed first and then user_callback_2 method.
In user_callback_2_test user_callback_2 method executed first and then user_callback_1 method.
❮ Previous Next ❯