How to call the user_defined callback class from a sequence?

Hi,

I have used the example in the link https://verificationguide.com/uvm/uvm-callback-in-uvm-sequence/
and tried to implement the same but using a virtual sequencer.
I have created a axi_mm_callback class extending from uvm_callback class. Another class axi_user_callback class extends from axi_mm_callback class that implements a task wherein the addr value is 'h101010.

But when I call this axi_user_callback class from my test, only the parent class is executed and I can see the message “ENTERED AXI_MM_CALLBACK” in the sim.log. The callback is registered with the virtual seqeuncer that ultimately starts the actual sequencer. The task update_pkt in the axi_user_callback class is never executed.

I don’t understand what is missing.
Any help would be much appreciated.
Thank you.

----------------------CODE----------------------------

class axi_mm_callback extends uvm_callback;
    
  `uvm_object_utils(axi_mm_callback)
    
  function new(string name = "axi_mm_callback");
    super.new(name);
    `uvm_info(get_full_name(),$psprintf("ENTERED AXI_MM_CALLBACK\n"),UVM_DEBUG);

  endfunction
    
  virtual task update_pkt(ref axi_mm_uvc_pkg::axi_mm_transaction pkt);
   endtask
endclass

---------------------------------------------------------
class axi_user_callback extends axi_mm_callback;
   
  `uvm_object_utils(axi_user_callback)
   
  function new(string name = "axi_user_callback");
    super.new(name);
  endfunction
   
  task update_pkt(ref axi_mm_uvc_pkg::axi_mm_transaction pkt);
    `uvm_info("USER_CALLBACK","[update_pkt] before packet modification",UVM_HIGH);
    pkt.print();
        pkt.awaddr = 'h10101010;
    `uvm_info("USER_CALLBACK","[update_pkt] after packet modification",UVM_HIGH);
    pkt.print();
  endtask
endclass

//  Class: axi_mm_virtual_sequencer
//------------------------------------------------------------------------------
class axi_mm_virtual_sequencer extends uvm_sequencer#(axi_mm_uvc_pkg::axi_mm_transaction);
    `uvm_component_utils(axi_mm_virtual_sequencer)
	`uvm_register_cb(axi_mm_virtual_sequencer,axi_mm_callback)


//the test from where I call the uvm_callbacks in the end of elaboration phase

function axi4_mem_intf_error_inject_callback_test::new(string name = "", uvm_component parent = null);
    super.new(name, parent);
    
endfunction : new
//------------------------------------------------------------------------------
// function : build_phase
// creating object for all the sequences
//------------------------------------------------------------------------------
function void axi4_mem_intf_error_inject_callback_test::build_phase(uvm_phase phase);
    super.build_phase(phase);
    callback_1 = axi_user_callback::type_id::create("callback_1", this);
    axi_seq= axi4_mem_intf_error_inject_callback_seq::type_id::create("axi_seq",this);
endfunction : build_phase


function void axi4_mem_intf_error_inject_callback_test::end_of_elaboration();
    
    uvm_callbacks#(axi_mm_uvc_pkg::axi_mm_sequencer,axi_mm_callback)::add(intr_top_env.mm_env.axi_mm_uvc_h.seqr.callback_1);
  endfunction : end_of_elaboration

//------------------------------------------------------------------------------
// task : run_phase
// randomizing each sequences with some value
// then starting the sequences inside respective sequencer with .start method
//------------------------------------------------------------------------------
task axi4_mem_intf_error_inject_callback_test::run_phase (uvm_phase phase);
    phase.raise_objection(this);

    axi_seq= axi4_mem_intf_error_inject_callback_seq::type_id::create("axi_seq");
    initial_bringup_seq= axi4_mem_intf_initial_bringup_sequence::type_id::create("initial_bringup_seq");
    `uvm_info( get_type_name(), "Starting AXI Write Read sequence...", UVM_DEBUG)
    initial_bringup_seq.start(intr_top_env.vseqr);
    create_axi_lite_reg_traffic('h424,'h00800010,'h1,axi_mm_enum_defines_pkg::AXI4_MM_VIP_INITIATOR_EN);
    create_axi_lite_reg_traffic('h72C,'h00800010,'h1,axi_mm_enum_defines_pkg::AXI4_MM_VIP_RESPONDER_EN);
    axi_seq.start(intr_top_env.vseqr);
    phase.drop_objection(this);



    phase.phase_done.set_drain_time (this, 100);
endtask : run_phase

The seqeunce where the uvm_do_callbacks macro is used

function axi_mm_write_seq::new(string name = "axi_mm_write_seq");
    super.new(name);
        `uvm_info(get_full_name(),$sformatf("\n Sequence Info : NAME=%0s", get_full_name()),UVM_DEBUG)
endfunction : new
//------------------------------------------------------------------------------
//  task: body
//  
//------------------------------------------------------------------------------
task axi_mm_write_seq::body();
  
    axi_mm_uvc_pkg::axi_mm_transaction axi_wr_trans;
    axi_mm_uvc_pkg::axi_mm_transaction rsp_item;
    axi_wr_trans = axi_mm_uvc_pkg::axi_mm_transaction::type_id::create("axi_wr_trans");
	 
    port_cfg = p_sequencer.get_config();
    axi_wr_trans.set_config(port_cfg);
    `uvm_info(get_full_name(),$psprintf("debug axi_mm DATA WIDTH %0d \n",axi_wr_trans.data_width),UVM_DEBUG);
    repeat(NUM_LOOP) begin 
        start_item(axi_wr_trans);
        axi_wr_trans.ruser_enable = 0;
        axi_wr_trans.aruser_enable = 0;
	axi_wr_trans.randomize() with {read_or_write_direction == axi_mm_enum_defines_pkg::AXI4_TRANS_WRITE;
				       awaddr                  == addr;
	     			       awid                    == awid_mm;
				       awlen                   == burst_len; 
	
			       	};
				`uvm_do_obj_callbacks(axi_mm_uvc_pkg::axi_mm_sequencer,axi_mm_callback,p_sequencer,update_pkt(axi_wr_trans));
        `uvm_info(get_full_name(),$psprintf("axi_mm_WRITE_INIT_transaction object \n %s \n",axi_wr_trans.sprint()),UVM_DEBUG);
        finish_item(axi_wr_trans);
	get_response(rsp_item);  
    end
	 
endtask : body