Previous - Up - Next

6.6   Logging

Logging in C or Python is handled by the SIM_log_register_group() and SIM_log_message() functions.

A single call to SIM_log_register_groups() registers all groups for the class. The function is used as:

# In Python
SIM_log_register_groups(class, gnames)

// In C
SIM_log_register_groups(conf_class_t *cls, const char **gnames)

where the parameters are:

The name of the Simics class in Python, and the class structure in C.
A tuple of strings in Python, and a NULL-terminated array of strings in C.

An example:

# In Python
SIM_log_register_groups("sample-device", ("config", "request", "response"))

// In C
static char *groupnames[] = { "config", "request", "response", NULL };
SIM_log_register_groups(my_class, &groupnames);

The log group values will be defined by the order of the strings in the tuple as a power of 2 series, so in the example above "config" corresponds to 1, "request" corresponds to 2 and "response" corresponds to 4.

Log outputs is handled with the SIM_log_message() function. It takes the following parameters:

# In Python
SIM_log_message(obj, level, groups, type, msg)

// In C
SIM_log_message(conf_object_t *obj,
                int level,
                int groups,
                log_type_t type,
                const char *msg);

with the parameters meaning:

The log object instance.
An integer from 1 through 4, determining the lowest verbosity level at which the message will be logged.
The bitwise or:ed values of one or several log-groups. If no log groups have been registered, 1 is a good value to use.
One of:
The string to log.


A SIM_log_message() example:

def get_counter_array(arg, obj, idx):
    SIM_log_message(obj, 4, 1, Sim_Log_Info, "get_counter_array")
    if idx != None:
        if isinstance(idx, (int, long)):
            SIM_log_message(obj, 1, 1, Sim_Log_Error,
                            "index must be integer")
            return None
        return obj.object_data.vcounter[idx]
        return obj.object_data.vcounter


Logging from a Simics module written in C/C++ is made easier and clearer by the macros SIM_log_info(), SIM_log_error(), SIM_log_undefined(), SIM_log_spec_violation(), SIM_log_target_error() and SIM_log_unimplemented(). These macros use internally the function SIM_log_message(), and should always be used instead.

The usage is identical for all, except that SIM_log_error() does not have a level parameter. The prototypes are:

static void SIM_log_info(int lvl, log_object_t *dev, int grp, 
                         const char *str, ...);

static void
SIM_log_undefined(int lvl, log_object_t *dev, int grp,
                  const char *str, ...);

static void
SIM_log_spec_violation(int lvl, log_object_t *dev, int grp,
                       const char *str, ...);

static void
SIM_log_target_error(int lvl, log_object_t *dev, int grp,
                     const char *str, ...);

static void
SIM_log_unimplemented(int lvl, log_object_t *dev, int grp,
                      const char *str, ...);

static void
SIM_log_error(log_object_t *dev, int grp,
              const char *str, ...);

The parameters are identical to the SIM_log_message() function described above. Note that the macros take a variable number of arguments to allow you to write printf()-like strings.

A small example:

static attr_value_t
get_counter_array(void *arg, conf_object_t *obj, attr_value_t *idx)
        my_object_t *mo = (my_object_t *)obj;

        SIM_log_info(4, obj, 1, "get_counter_array");
        if (idx->kind != Sim_Val_Nil) {
                if (idx->kind != Sim_Val_Integer)
                        SIM_log_error(obj, 1,
                                      "Index must be integer");
                        return SIM_make_attr_invalid();

                return SIM_make_attr_integer(mo->foo[idx->u.integer]);
        else {
                attr_value_t ret = SIM_alloc_attr_list(10);
                int i;
                for (i = 0; i < 10; i++) {
                        ret.u.list.vector[i] =
                return ret;

Previous - Up - Next