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
