An object that wants to interacts with another through an interface uses the SIM_get_interface() functions to retrieve the interface structure. It can then call the other object using the functions defined in the structure.
# in Python ifc = SIM_get_interface(conf.phys_mem, "memory_space") val = ifc.read(conf.phys_mem, conf.cpu0, 0x1234, 4, 0) // In C conf_object_t *obj = SIM_get_object("phys_mem"); memory_space_interface_t *ifc; attr_value_t val; ifc = (memory_space_interface_t *) SIM_get_interface(obj, "memory_space"); val = ifc->read(obj, SIM_get_object("cpu0"), 0x1234, 4, 0);
In Python, you can use the iface attribute of the object to access the interface directly:
# In Python val = conf.phys_mem.iface.memory_space.read(conf.phys_mem, conf.cpu0, 0x1234, 4, 0)
When you are using interfaces inside an object, you will often need to define which object you want to talk to via an attribute. The classic way of doing that is to define an attribute with type o|n, and check if the object passed as argument implements the necessary interface:
// In C static attr_value_t get_an_object(void *arg, conf_object_t *obj, attr_value_t *idx) { my_object_t *mo = (my_object_t *)obj; return SIM_make_attr_object_or_nil(obj->an_object); } static set_error_t set_an_object(void *arg, conf_object_t *obj, attr_value_t *val, attr_value_t *idx) { my_object_t *mo = (my_object_t *)obj; if (val->u.kind == Sim_Val_Nil) { mo->an_object = NULL; } else { foo_interface_t *foo_ifc = (foo_interface_t *)SIM_get_interface(val->u.object, "foo"); if (SIM_clear_exception() != SimExc_No_Exception) return Sim_Set_Interface_Not_Found; mo->an_object = val->u.object; } return Sim_Set_Ok; } [...] SIM_register_typed_attribute(class_name, "an_object", get_an_object, NUL, set_an_object, NULL, Sim_Attr_Optional, "o|n", NULL, "An object implementing the 'foo' interface");
Implementing an existing interface consists in filling in the functions pointers that are listed in the interface definition with the functions that should be called. The interface should then be registered using the SIM_register_interface() function:
SIM_register_interface(conf_class_t *class, char *name, void *iface)
Where the parameters are:
This gives us the following code:
# In Python def my_operate(memhier, space, map, memop): print "my_operate() has been called!" ifc = timing_interface_t() ifc.operate = my_operate SIM_register_interface(my_class, "timing-model", ifc) // And in C static cycles_t my_operate(conf_object_t *mem_hier, conf_object_t *space, map_list_t *map, generic_transaction_t *mem_op) { // do something } static conf_class_t *my_class; static timing_model_interface_t ifc; void init_loca(void) { ... ifc.operate = my_operate; SIM_register_interface(my_class, "timing-model", (void *) &ifc); ... }
It is unfortunately not possible to implement new interfaces in Python since it would require additional type wrapping to exchange data between Python and the C layer that implements interfaces.
Implementing a new interface in C is pretty much the same as implementing an existing interface, except that you must declare the structure defining the interface first:
typedef struct { int (*my_function)(conf_object_t *o, int i); } myifc_interface_t; int my_function(conf_object_t *o, int i) { return i + 1; } ...
Note that:
If you plan to use the interface you are declaring in DML code, these two rules are mandatory. Refer to the section 5.3 to get more explanation about interfaces in DML.