When you want your module to record or react to a hap, you can register a callback function with the specific hap. The signature for the callback function differs between the different haps.
Registering a callback is made with any of the functions SIM_hap_add_callback(), SIM_hap_add_callback_index(), SIM_hap_add_callback_range(), SIM_hap_add_callback_obj(), SIM_hap_add_callback_obj_index() or SIM_hap_add_callback_obj_range(). See the Reference Manual for information about the differences.
# In Python SIM_hap_add_callback(hap, func, user_data) // In C hap_handle_t SIM_hap_add_callback_obj(const char *hap, obj_hap_func_t func, typed_lang_void *user_data);
The parameters of SIM_hap_add_callback_obj() are:
The function returns a handle which can be used to manipulate the hap callback later on.
A list of all haps can be found in the Simics Reference Manual, including the signatures for the callback functions.
A small example:
# In Python def stopped(user_data, obj, exception, errstr): print "Stopped" def started(user_data, obj): print "Started" handle1 = SIM_hap_add_callback("Core_Continuation", started, None); handle2 = SIM_hap_add_callback("Core_Simulation_Stopped", stopped, (2, "str")) ... // In C static void stopped(void *user_data, conf_object_t *obj, integer_t exception, char *errstr) { // do something } static void started(void *user_data, conf_object_t *obj) { // do something } static hap_handle_t h1, h2; void init_local() { ... h1 = SIM_hap_add_callback("Core_Continuation", started, NULL); h2 = SIM_hap_add_callback("Core_Simulation_Stopped", stopped, NULL); ... }
Should you no longer want to subscribe to a hap, the notification callbacks can be canceled using one of the functions SIM_hap_delete_callback(), SIM_hap_delete_callback_obj(), SIM_hap_delete_callback_id() and SIM_hap_delete_callback_obj_id(). See the Reference Manual for the differences. The signature for SIM_hap_delete_callback() is:
SIM_hap_delete_callback(hap, func, user_data)The parameters are:
A callback must have been registered with the exact same parameter values. To continue the above example:
# In Python def at_end(): # using the callback parameters SIM_hap_delete_callback("Core_Simulation_Stopped", stopped, NULL); # using the hap handle SIM_hap_delete_callback_id(handle2) // In C fini_local() { // Using the callback parameters SIM_hap_delete_callback("Core_Simulation_Stopped", stopped, NULL); // Using the hap handle SIM_hap_delete_callback_id(h2); }
It might be that some things happening in your module are worth notifying others of, for example for automation with scripts. To do this, you can provide your own haps to which interested parties can subscribe.
Before subscribers can be notified of a new hap, the hap must be known. A new hap type is made known through registration. Registering a new hap type is done with the function SIM_hap_add_type(). The signature is:
# In Python SIM_hap_add_type(hap, params, param_desc, index, desc, old_hap_obj) // In C hap_type_t SIM_hap_add_type(const char *hap, const char *params, const char *param_desc, const char *index, const char *desc, int old_hap_obj);
where the parameters are:
The return value is a handle that must be saved for operations on the hap.
Example:
# In Python hap_handle = SIM_hap_add_type("My_Special_Hap", "ii", "val1 val2", None, "Called when something special " " happens in my module.", 0); if hap_handle <= 0: # error handling ... static hap_type_t hap_handle; // In C void init_local() { ... hap_handle = SIM_hap_add_type("My_Special_Hap", "ii", "val1 val2", NULL, "Called when something special " " happens in my module.", 0); if (hap_handle <= 0) { /× error handling ×/ ... } }
Whenever the special condition for the hap is met, the subscribers to the hap should be notified. Since the call itself incurs some overhead, it is good practice to use SIM_hap_is_active() to check if there are any subscribers before calling the notification function.
# In Python SIM_hap_is_active(hap) // In C int SIM_hap_is_active(hap_type_t hap)
where the parameter hap is the value returned from SIM_hap_add_type(). SIM_hap_is_active() returns 1 if there are callbacks registered for the hap type, and 0 otherwise.
The notification of subscribers is normally done with one of SIM_hap_occurred(), SIM_hap_occurred_vararg(), SIM_hap_occurred_always(), and SIM_hap_occurred_always_vararg(). See the Reference Manual for information about the differences.
# In Python SIM_hap_occurred(hap, obj, value, list) // In C int SIM_c_hap_occurred(hap_type_t hap, conf_object_t *obj, integer_t value, ...);
The parameters are:
In C, hap parameters will be provided as additional parameters to the function. A short example:
# In Python def some_func(obj, v1, v2): if some_condition: if SIM_hap_is_active(hap_handle): SIM_hap_occurred(hap_handle, obj, 0, [v1, v2]) // In C static void some_func(conf_object_t *obj, int v1, int v2) { if (some_condition) { if (SIM_hap_is_active(hap_handle)) SIM_c_hap_occurred(hap_handle, obj, 0, v1, v2) } }