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