Previous - Up - Next

6.8   Haps

6.8.1   Reacting to Haps

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:

hap
The name of the hap (string);
func
The callback function;
user_data
Any user data you require for your callback function. The value is passed as-is by simics.

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:
hap
The name of the hap
func
The callback function registered
user_data
User provided data

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);
}

6.8.2   Providing Haps

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.

Adding a new type

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:

hap
The name of the hap, which must be unique
params
A string specifying the number of parameters of the hap and their types. The return value and the first two parameters of the callback function are always the same and are not included in the list. A valid parameter description string contains only the following type description characters:

param_dessc
space separated list of descriptive parameter names (in the same order as params, so that the first word is the name of the first parameter. If param is the empty string, param_desc may be None.
index
A string describing the index value for the hap, or None if there is no index value. The meaning of indexes is up to you to define.
desc
A human readable description of the hap.
old_hap_obj
Always 0.

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 ×/
                ...
        }
}

Notifying subscribers

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:

hap
The handle to the hap type, as returned from SIM_hap_add_type().
obj
The object for which the condition is met.
value
Only meaningful if the hap is indexed. The meaning is defined by you.
list
In Python, the parameters to the hap callback as a Python list.

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)
        }
}

Previous - Up - Next