Hi.
I’m trying to understand the feature of callback and why we use callback instead of task.
https://verificationacademy.com/verification-methodology-reference/uvm/docs_1.2/html/files/base/uvm_callback-svh.html
It’s say that
The uvm_callbacks class provides a base class for implementing callbacks, which are typically used to modify or augment component behavior without changing the component class. To work effectively, the developer of the component class defines a set of “hook” methods that enable users to customize certain behaviors of the component in a manner that is controlled by the component developer. The integrity of the component’s overall behavior is intact, while still allowing certain customizable actions by the user.
So I found one simple callback example.
`include "uvm_macros.svh"
import uvm_pkg::*;
typedef enum {OKAY, EXOKAY, SLVERR, DECERR} resp_type;
`include "driver_callback.sv"
`include "slave_driver.sv"
`include "slave_env.sv"
`include "basic_test.sv"
`include "slv_error_callback.sv"
`include "slv_err_test.sv"
program testbench_top;
//---------------------------------------
//calling test
//---------------------------------------
initial begin//{
run_test();
end //}
endprogram
class driver_callback extends uvm_callback;
`uvm_object_utils(driver_callback)
function new(string name = "driver_callback");
super.new(name);
endfunction
virtual task update_resp(ref resp_type resp); endtask
endclass
class slave_driver extends uvm_component;
resp_type resp;
`uvm_component_utils(slave_driver)
`uvm_register_cb(slave_driver,driver_callback)
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction
task run_phase(uvm_phase phase);
repeat(2) begin //{
std::randomize(resp) with { resp == OKAY;};
`uvm_do_callbacks(slave_driver,driver_callback,update_resp(resp));
`uvm_info("DRIVER",$sformatf("Generated response is %s",resp.name()),UVM_LOW);
end //}
endtask
endclass
class slave_env extends uvm_env;
slave_driver driver;
`uvm_component_utils(slave_env)
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
driver = slave_driver::type_id::create("driver", this);
endfunction
endclass
class basic_test extends uvm_test;
slave_env 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 = slave_env::type_id::create("env", this);
endfunction
endclass
class slv_error_callback extends driver_callback;
`uvm_object_utils(slv_error_callback)
function new(string name = "slv_error_callback");
super.new(name);
endfunction
task update_resp(ref resp_type resp);
resp = SLVERR;
endtask
endclass
class slv_err_test extends basic_test;
slv_error_callback err_callback;
`uvm_component_utils(slv_err_test)
function new(string name = "slv_err_test", uvm_component parent=null);
super.new(name,parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
err_callback = slv_error_callback::type_id::create("err_callback", this);
uvm_callbacks#(slave_driver,driver_callback)::add(env.driver,err_callback);
endfunction
endclass
But Basically we can replace it by task as the below
class base_class;
virtual task run();
before_main_task();
//Actual task
do_main_task(txn);
after_main_task();
endtask
virtual task before_main_task();
endtask
virtual task after_main_task();
endtask
task do_main_task();
...
...
endtask
endclass
My humble Idea is that I can use task/function instead callback and couldn’t find any specific benefits to use callback instead of using task/function yet. we just use task/function instead of using callback. Is there any reason for using callback instead task/function?