Callbacks in SystemVerilog
Table of Contents
For a detailed description of Callback refer to SystemVerilog Callback.
Callback example
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
- error_test – Testcase with callback method used to generate an error response
- err_inject – extended driver class to implement the callback method
By using a callback, will implement the testcase to drive the SLVERR response.
Will see through the below steps,
- Adding Callback Support
- Implementing Callback Method
- Using Callback
Adding Callback Support
In this step, will write the driver with a dummy method and callback hooks to it.
- Writing slave_driver class with enum variable resp
typedef enum {OKAY, EXOKAY, SLVERR, DECERR} resp_type; class slave_driver; resp_type resp; endclass
- Adding response driving task send_response with response randomize logic
typedef enum {OKAY, EXOKAY, SLVERR, DECERR} resp_type; class slave_driver; resp_type resp; //send response task task send_response; std::randomize(resp) with { resp == OKAY;}; endtask endclass
- Defining the callback method by declaring the virtual task update_resp
typedef enum {OKAY, EXOKAY, SLVERR, DECERR} resp_type; class slave_driver; resp_type resp; //callback hook virtual task update_resp; endtask //send response task task send_response; std::randomize(resp) with { resp == OKAY;}; endtask endclass
- Placing hook for a callback. In this example, as it is required to change the response once it is generated, so it is good to place callback hook after calling the randomize method
typedef enum {OKAY, EXOKAY, SLVERR, DECERR} resp_type; class slave_driver; resp_type resp; //callback hook virtual task update_resp; endtask //send response task task send_response; std::randomize(resp) with { resp == OKAY;}; update_resp(); endtask endclass
Implementing Callback Method
For the error response generation scenario, it is required to corrupt the response generated.
This can be achieved by adding the logic in update_resp() callback to overwrite the response generated.
Which involves below steps.
- extend the slave_driver and write new driver err_inject
class err_inject extends slave_driver; endclass
- Implement the callback method update_resp
class err_inject extends slave_driver; virtual task update_resp; $display("Injecting SLVERR"); resp = SLVERR; endtask endclass
Using Callback
A callback can be used by,
- Writing new error response testcase
program error_test; slave_env env; initial begin //Create env env = new(); //Calling run of env env.run(); end endprogram
- Declare and create an err_inject driver
program error_test; slave_env env; err_inject err_driver; initial begin //Create env env = new(); err_driver = new(); //Calling run of env env.run(); end endprogram
- Override the slave_driver by the new err_inject driver
program error_test; slave_env env; err_inject err_driver; initial begin //Create env env = new(); err_driver = new(); //Overriding slave_driver by error_driver env.slv_driver = err_driver; //Calling run of env env.run(); end endprogram
Simulator Output of basic_test
Slave generated response is OKAY Slave generated response is OKAY
Simulator of error_test
Injecting SLVERR Slave generated response is SLVERR Injecting SLVERR Slave generated response is SLVERR
Note:
- To execute basic_test comment error_test.sv
- To execute error_test comment basic_test.sv