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:
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 void SIM_log_message(conf_object_t *obj, int level, int groups, log_type_t type, const char *msg);
with the parameters meaning:
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] else: 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] = SIM_make_attr_integer(mo->foo[i]); } return ret; } }