UVM Callback example

Callback Example

Callback to corrupt the stimulus

Let’s consider an example of a Slave Driver (Slave Driver: drives response to the master).

For simplicity, one callback hook is implemented and only response generation logic is captured in the code.

Components of slave_driver example are,

  • slave_driver – Normal driver to drive response
    • response types are OKAY, EXOKAY, SLVERR, DECERR
    • slave_driver is constrained to send OKAY response always to see to the callback usage difference
  • slave_env – Environment which has a slave driver created in it
  • basic_test – Which sends the normal response
  • driver_callback – Callback class
  • slv_err_test  – Testcase with callback used to generate an error response
  • err_error_callback  – extended callback class to implement callback method

By using a callback, will write the testcase to drive the SLVERR response.

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 the callback method in user-defined callback class
    • In this example update_resp() is the callback method.
  virtual task update_resp(ref resp_type resp); 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 update_resp(ref resp_type resp); 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(slave_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 (update_resp())
  • Callback methods can be called by using macro `uvm_do_callbacks
  `uvm_do_callbacks(slave_driver,driver_callback,update_resp(resp));

Complete driver code

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

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 slv_error_callback
class slv_error_callback extends driver_callback;
  ...
endclass
  • Implement the methods with logic in it (this example we are adding only display’s)
  task update_resp(ref resp_type resp);
    resp = SLVERR;
  endtask

Complete callback class code

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

Using Callback

In the testcase where callbacks need to be applied,

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

Complete test case code

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

slv_err_test is the test with callbacks added, and basic_test is without callbacks.
basic_test simulator output (Without Callback)

UVM_INFO @ 0: reporter [RNTST] Running test basic_test...
UVM_INFO slave_driver.sv(19) @ 0: uvm_test_top.env.driver [DRIVER] Generated response is OKAY
UVM_INFO slave_driver.sv(19) @ 0: uvm_test_top.env.driver [DRIVER] Generated response is OKAY
UVM_INFO /apps/vcsmx/etc/uvm-1.2/src/base/uvm_report_server.svh(847) @ 0: reporter [UVM/REPORT/SERVER]

Click to execute on   

callback_test simulator output (With Callback)

UVM_INFO @ 0: reporter [RNTST] Running test slv_err_test...
UVM_INFO slave_driver.sv(19) @ 0: uvm_test_top.env.driver [DRIVER] Generated response is SLVERR
UVM_INFO slave_driver.sv(19) @ 0: uvm_test_top.env.driver [DRIVER] Generated response is SLVERR
UVM_INFO /apps/vcsmx/etc/uvm-1.2/src/base/uvm_report_server.svh(847) @ 0: reporter [UVM/REPORT/SERVER]

Click to execute on   
In order to execute the particular testcase, change the inline argument.

  • +UVM_TESTNAME=basic_test
  • +UVM_TESTNAME=slv_err_test

❮ Previous Next ❯