UVM Callback in uvm sequence

Callback in uvm_sequence

Callback hooks can be placed in uvm_sequnence. Different flavors of the sequence can be obtained by implementing custom callback methods.

In the previous example’s we have seen callback implementation in uvm_driver. In this section will see how to implement the callback in uvm_sequence.

Callback implementation in uvm_sequence

Callback implementation steps for uvm_sequence are the same as in uvm_driver. Before going through this section, it is required to refer to the UVM callback example.

Below are the testbench components.

callback in uvm_sequence
callback in uvm_sequence

Let’s implement the callback in uvm_sequence to modify the sequence_item before sending it to the driver.

Steps involved are,

  • Write callback class
  • Register the callback class
  • Place the callback hook
  • Implement the callback method
  • Create and register the callback object

Write Callback class

  • Callback class is written by extending the uvm_callback
class mem_callback extends uvm_callback;
   ...
endclass
  • Adding a virtual callback method
class mem_callback extends uvm_callback;
  virtual task update_pkt(ref mem_seq_item pkt); endtask
endclass
  • Complete callback class code
class mem_callback extends uvm_callback;
   
  `uvm_object_utils(mem_callback)
   
  function new(string name = "mem_callback");
    super.new(name);
  endfunction
   
  virtual task update_pkt(ref mem_seq_item pkt); endtask
endclass

Register the callback class

  • The callback class needs to be registered with the component. As the sequence is dynamic, the callback will be registered to a sequencer
  `uvm_register_cb(mem_sequencer,mem_callback)
  • Complete sequencer code
class mem_sequencer extends uvm_sequencer#(mem_seq_item);

  `uvm_component_utils(mem_sequencer) 
  `uvm_register_cb(mem_sequencer,mem_callback)
  
  //---------------------------------------
  //constructor
  //---------------------------------------
  function new(string name, uvm_component parent);
    super.new(name,parent);
  endfunction
  
endclass

Place the callback hook

  • Callback hook is a call to callback method, and in this example, it is required to be placed in the sequence
   `uvm_do_obj_callbacks(mem_sequencer,mem_callback,p_sequencer,update_pkt(req));
  • Complete sequence code
class mem_sequence extends uvm_sequence#(mem_seq_item);
  
  `uvm_object_utils(mem_sequence)

  //--------------------------------------- 
  //Constructor
  //---------------------------------------
  function new(string name = "mem_sequence");
    super.new(name);
  endfunction
  
  `uvm_declare_p_sequencer(mem_sequencer)
  
  //---------------------------------------
  // create, randomize and send the item to driver
  //---------------------------------------
  virtual task body();
    req = mem_seq_item::type_id::create("req");
    wait_for_grant();
    req.randomize();
    `uvm_do_obj_callbacks(mem_sequencer,mem_callback,p_sequencer,update_pkt(req));
    send_request(req);
    wait_for_item_done();
  endtask
endclass

Implement the callback method

The callback will be implemented in the extended callback class.

  • Write user_callback class by extending mem_callback
class user_callback extends mem_callback;
  
  `uvm_object_utils(user_callback)
  
  function new(string name = "user_callback");
    super.new(name);
  endfunction

endclass
  • Implement the update_pkt callback method
    • the update_pkt method is implemented to invert the value of the address.
class user_callback extends mem_callback;
  
  `uvm_object_utils(user_callback)
  
  function new(string name = "user_callback");
    super.new(name);
  endfunction
  
  task update_pkt(ref mem_seq_item pkt);
    `uvm_info("USER_CALLBACK","[update_pkt] before packet modification",UVM_LOW);
    pkt.print();
    pkt.addr = ~pkt.addr;
    `uvm_info("USER_CALLBACK","[update_pkt] after packet modification",UVM_LOW);
    pkt.print();
  endtask
endclass

Create and register the callback object

  • Declare and create the callback
  user_callback callback_1;
  callback_1 = user_callback::type_id::create("callback_1", this);
  • Register the callback object with the component in which callback class is registered
  uvm_callbacks#(mem_sequencer,mem_callback)::add(env.mem_agnt.sequencer,callback_1);
  • Complete user_callback_test code
class user_callback_test extends mem_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);
  endfunction
  
  function void end_of_elaboration();
    uvm_callbacks#(mem_sequencer,mem_callback)::add(env.mem_agnt.sequencer,callback_1);
  endfunction : end_of_elaboration
endclass

Simulator Output: (mem_test)

UVM_INFO mem_driver.sv(38) @ 0: uvm_test_top.env.mem_agnt.driver [mem_driver] Recived Drive packet
----------------------------------
Name     Type          Size  Value
----------------------------------
req      mem_seq_item  -     @575
addr   integral      4     'hb
wr_en  integral      1     'h0
rd_en  integral      1     'h1
wdata  integral      8     'h3f
----------------------------------
UVM_INFO /apps/vcsmx/etc/uvm-1.2/src/base/uvm_objection.svh(1270) @ 50: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
UVM_INFO /apps/vcsmx/etc/uvm-1.2/src/base/uvm_report_server.svh(847) @ 50: reporter [UVM/REPORT/SERVER]

Simulator Output: (user_callback_test)

UVM_INFO user_callback.sv(14) @ 0: reporter [USER_CALLBACK] [update_pkt] before packet modification
----------------------------------
Name     Type          Size  Value
----------------------------------
req      mem_seq_item  -     @577
addr   integral      4     'hb
wr_en  integral      1     'h0
rd_en  integral      1     'h1
wdata  integral      8     'h3f
----------------------------------
UVM_INFO user_callback.sv(17) @ 0: reporter [USER_CALLBACK] [update_pkt] after packet modification
----------------------------------
Name     Type          Size  Value
----------------------------------
req      mem_seq_item  -     @577
addr   integral      4     'h4
wr_en  integral      1     'h0
rd_en  integral      1     'h1
wdata  integral      8     'h3f
----------------------------------
UVM_INFO mem_driver.sv(38) @ 0: uvm_test_top.env.mem_agnt.driver [mem_driver] Recived Drive packet
----------------------------------
Name     Type          Size  Value
----------------------------------
req      mem_seq_item  -     @577
addr   integral      4     'h4
wr_en  integral      1     'h0
rd_en  integral      1     'h1
wdata  integral      8     'h3f
----------------------------------
UVM_INFO /apps/vcsmx/etc/uvm-1.2/src/base/uvm_objection.svh(1270) @ 50: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase

 Result Analysis 

From the above simulation result, we can make out that,
user_callback_test is enabling the implemented callback methods.

Click to execute on   

Note:
In Compile & Run Options Provide,
+UVM_TESTNAME=mem_test  to execute mem_test
+UVM_TESTNAME=user_callback_test  to execute user_callback_test
❮ Previous Next ❯