Previous - Up - Next

4.2   Attributes

A Simics class can register attributes that will act as data members for all objects instantiated from this class. For Simics, an attribute is an abstraction, defined by its type and a pair of get()/set() functions. When an attribute is read (i.e., when the SIM_get_attribute() function is used on the object), the corresponding get() function is called. Likewise, when an attribute is written to, the set() function is executed. These functions can perform any kind of operation provided they return a value (for get()) or accept a value to be written (for set()).

Attributes have different types and properties. The Simics User Guide presents a high level description of attributes. Let us here have a closer look at their definition.

Definition

The C and DML definition of the structures representing an attribute are the following:

typedef enum {
        Sim_Val_Invalid  = 0,
        Sim_Val_String   = 1,
        Sim_Val_Integer  = 2,
        Sim_Val_Floating = 3,
        Sim_Val_List     = 4,
        Sim_Val_Data     = 5,
        Sim_Val_Nil      = 6,
        Sim_Val_Object   = 7,
        Sim_Val_Dict     = 8,
        Sim_Val_Boolean  = 9
} attr_kind_t;

typedef struct {
        integer_t          size;
        struct attr_value *vector;
} attr_list_t;

typedef struct {
        integer_t          size;
        uint8             *data;
} attr_data_t;

typedef struct {
        struct attr_value key;
        struct attr_value value;
} attr_dict_pair_t;

typedef struct {
        integer_t         size;
        attr_dict_pair_t *vector;
} attr_dict_t;

typedef struct attr_value {
        attr_kind_t kind;
        union {
                const char    *string;
                integer_t      integer;
                integer_t      boolean;
                double         floating;
                attr_list_t    list;
                attr_dict_t    data;
                attr_data_t    data;
                conf_object_t *object;
        } u;
} attr_value_t;

When using an attribute in C or DML, one should take care of only using the union member that corresponds to the attribute type in the attr_value_t structure. Here are some example of attribute manipulation in C and DML:

// create an integer attribute
attr_value_t a;
a.kind = Sim_Val_Integer;
a.u.integer = 4711;

// or better, using help functions
attr_value_t a;
a = SIM_make_attr_integer(4711);

// create a list attribute
attr_value_t l;
l = SIM_alloc_attr_list(2);

// writing to the first element
l.u.list.vector[0] = SIM_make_attr_integer(1)

// reading the second element of the list
integer_t other = l.u.list.vector[1].u.integer;

A complete documentation of attributes related functions is provided in the Simics Reference Manual.

In Python, attributes are automatically converted to or from the corresponding Python type, so manipulating attributes is completely transparent:

Attribute TypePython Equivalent
InvalidCast a SimExc_Attribute exception.
Stringstr (a Python string)
Integerint or long
Floatingfloat
Listlist
Datatuple
NilNone
ObjectAn object from the conf namespace.
Dictdict
Booleanbool

Type

When registering an attribute, a type definition should be provided for Simics to check that the attribute is always set properly. This type definition is a string defined by to the following rules:

As an example, the type for sim.simics_path is "s|[s*]", which means that it can either match a string or a (possibly empty) list of strings.

When writing complex attributes, you may notice that the type description strings don't cover all the possibilities offered by the attribute structure definition. If you need to register attributes that can not be described in a type string (like complex variable size lists), you will need to use the a type and perform the type checking by yourself in the set() function. You may also want to review your attribute and change its definition to match a possible type description, or divide your attribute into several simpler attributes.

For example, an attribute accepting a list composed of one object and one or more integers can not be described in a type string (list definition with variable size can only have one element). You may want to rewrite your attribute to use a sub-list for the integers: [o[i+]], or you can perform type checking yourself.

To learn more about attributes in DML, refer to section 5.2. For C and Python, refer to section 6.4.

Attribute Data Ownership

Attributes of the Sim_Val_String and Sim_Val_Data types contain references to data that does not fit in the attribute structure itself. In addition, the types Sim_Val_List and Sim_Val_Dict have an extended attribute structure allocated. To avoid memory leaks and corruption, it is important to keep track of ownership of this data.

When the attr_value_t type is used for function arguments, it is the caller that owns the data, and that is responsible for freeing it after the call. If the called function wants to keep a reference to the attribute value, it should make a copy of it.

When a function returns an attr_value_t, it may return a reference to a static data area, that will be reused in future calls. The caller has to use the returned data, or create a copy of it, before calling any other functions. If an attribute get function allocates new memory every time the attribute is read, it will leak memory.

When an attr_value_t is returned, the attribute structure used for lists and dictionaries should be freed by the caller using SIM_free_attribute(). This function will only free the attribute structure, not any string or data memory.


Note: Code written in Python does not have to handle attribute data ownership as described in this section.

Previous - Up - Next