33 Object Hierarchy 35 Notifiers
Model Builder User's Guide  /  VI Simics API  / 

34 Port Objects

In Simics 6 there is a concept called Port Objects. A port object is a child object which is created automatically together with its parent object. The underlying idea is that a class should be able to specify a set of child objects, denoted port objects, which will be created automatically when the class is instantiated. The end user of the class does not need to explicitly create the port objects or even know about them.

Port objects are not intended as a replacement for components, but rather as a way to allow functionality to be factored out and put in separate objects residing in the namespace below the object. As the name implies, however, port objects are intended to function as a replacement for port interfaces.

34.1 Registering Port Objects

Below is an example of how a port object can be registered on a class:

// Define a signal reset function
static void
signal_raise_reset(conf_object_t *port_obj)
{
        conf_object_t *parent_obj = SIM_port_object_parent(port_obj);
        ...
}

// Create the class "myclass"
cls = SIM_create_class("myclass", &class_info);

// Register the port port.RESET
port_cls = SIM_register_simple_port(
        cls, "port.RESET", "Hardware Reset Port");

// Register an interface on the created port object class
static const signal_interface_t signal_iface = {
        .signal_raise = signal_raise_reset,
};
SIM_REGISTER_INTERFACE(port_cls, signal, &signal_iface);

In the example above, a port object is registered on myclass with the name port.RESET. When the class subsequently is instantiated as an object myobj, then the port object will be created as myobj.port.RESET. The port object will be an instance of the class myclass.RESET with a single interface registered on this class in this case. The port object class can be more complex than in the simple example above; it can be defined to have attributes, multiple interfaces or even port objects of its own.

34.2 Hierarchical Class Names

The preceding example defined a class with a hierarchical class name, myclass.RESET. The dot in the class name has the following meaning:

34.3 Using Existing Classes as Port Objects

It is possible to use pre-defined classes as well when port objects are defined, which is illustrated in the following example:

// Create the class "mydev"
cls = SIM_create_class("mydev", &class_methods);

// Register the port object 'bus_clock' as a 'cycle-counter' class
conf_class_t *cycle_counter_cls = SIM_get_class("cycle-counter");
SIM_register_port(cls, "bus_clock", cycle_counter_cls,
                  "Clock running at bus frequency");

When mydev is instantiated, then a cycle-counter instance will be created as mydev.bus_clock. The cycle-counter class, which is included in the Simics Base package, provides a cycle counter that runs at some user-defined frequency and allows for event posting. In this example, the counter would typically be used by mydev to model functionality that depends on some device specific frequency.

34.4 Setting Port Object State

For port objects that have attributes, it is often useful for the parent object to provide default values for certain attributes. Below are some examples when this is particularly useful:

The SIM_set_attribute_default function provides a way for the port object parent to set default values. These default values take effect only if the attribute in question is not set explicitly when the object is created. Default attributes values can only be set from the init method or from attribute setters of objects under construction. The later allows state to be propagated from a port object parent to its children.

Setting attribute values directly during object construction, rather than setting attribute defaults, will invariably break checkpointing or not have the intended effect.

Below is an example showing an init method which sets a default value for the frequency attribute of its bus_clock port object.

static lang_void *
init(conf_object_t *obj)
{
    // Configure the bus_clock frequency...
    conf_object_t *clock = SIM_object_descendant(obj, "bus_clock");
    attr_value_t freq = SIM_make_attr_floating(1E6);
    SIM_set_attribute_default(clock, "frequency", freq);

    // Do other initialization as needed...
    return obj;
}

The following is another example, where a bus object is propagated from the attribute setter of the parent to a port object child.

static set_error_t
attr_set_bus(conf_object_t *obj, attr_value_t *val)
{
    // Propagate our configured bus as an
    // attribute default for the "device" port object
    if (!SIM_object_is_configured(obj)) {
        conf_object_t *dev = SIM_object_descendant(obj, "device");
        SIM_set_attribute_default(dev, "bus", *val);
    }
    // Do other things here...
    return Sim_Set_Ok;
}

As a rule of thumb, it should be possible to instantiate a class without having to explicitly set attributes for any of its registered port objects.

34.5 Pre Conf Object Support

The port object support extends to the pre_conf_object, as is illustrated in the following example, which uses the 'myclass' Simics class defined previously:

simics> @myobj = pre_conf_object('myclass', 'myclass')
simics> @print(myobj.port.RESET)
pre conf object myclass.port.RESET of type myclass.RESET

That is, if a class defines port objects, then pre objects corresponding to the port objects will be created automatically.

34.6 Port Object Parent

A special function SIM_port_object_parent exists to retrieve the port object parent from a port object. The function returns NULL if the object is not a port object.

Use SIM_port_object_parent to retrieve the port object parent instead of relying on SIM_object_parent. The main reason for this is that the former will always return the correct object, whereas the later will return the hierarchical parent, which sometimes is not the desired object. As an example, if SIM_object_parent is applied to the objects myobj.port.RESET, myobj.port.signal[2] and myobj.bus_clock, then the return value will be myobj.port, myobj.port.signal and myobj respectively. The SIM_port_object_parent function, on the other hand, consistently returns the wanted myobj object in all three cases.

33 Object Hierarchy 35 Notifiers