34 Port Objects 36 Extension Classes
Model Builder User's Guide  /  VI Simics API  / 

35 Notifiers

Notifiers is a light-weight publish-subscribe mechanism introduced in Simics 6. Unlike the hap system, which also follows a publish-subscribe pattern, notifiers are always tied to a specific object and they do not have any parameters.

35.1 Notifier Subscription

An object can subscribe to a notifier published by another object by using the SIM_add_notifier function. This is illustrated by the example below, where a subscriber class is defined which subscribes to frequency changed notifications produced by an object implementing the frequency interface.

class subscriber(pyobj.ConfObject):
    # Notifier invoked when the frequency has changed
    def notifier(self, obj, src, data):
        self.frequency = src.iface.frequency.get()
        print("New Frequency", self.frequency)

    class frequency_provider(pyobj.Attribute):
        "Object implementing the 'frequency' interface"
        attrtype = "o|n"

        def getter(self):
            return self.obj

        def setter(self, obj):
            # Delete any old notifier
            if self.handle:
                SIM_delete_notifier(self.obj, self.handle)
                self.handle = None

            # Subscribe to the new notifier
            self.obj = obj
            if not obj:
                return

            self.handle = SIM_add_notifier(
                obj, Sim_Notify_Frequency_Change, self._up.obj,
                self._up.notifier, None)

            # Get current frequency
            self._up.frequency = obj.iface.frequency.get()

        def _initialize(self):
            self.obj = None
            self.handle = None

The notifier callback function takes three parameters: the subscriber, the notifier and the data passed by the last argument of the SIM_add_notifier function. The function looks a bit different in different modeling languages. The Python notifier callback is shown in the above example. In DML, it is defined as:

method on_notify(conf_object_t *notifier, void *data) {
    ...
}

In C/C++, it is defined as:

void on_notify(conf_object_t *obj, conf_object_t *notifier, void *data) {
    ...
}

Some things should be noted in the example above:

35.2 Notifier Publication

Simics objects are only allowed to trigger notifiers of types which have been registered with the corresponding Simics class. The exception to this rule is certain notifiers triggered by Simics Core, like the Sim_Notify_Queue_Change notifier or the Sim_Notify_Cell_Change notifier, which can be triggered by any object.

The following example illustrates how a class implementing the frequency interface registers a Sim_Notify_Frequency_Change notifier with the class and triggers it when the frequency has changed:

class provider(pyobj.ConfObject):
    "Object implementing the 'frequency' interface"

    class frequency(pyobj.Interface):
        def get(self):
            return self._up.frequency

    class freq(pyobj.Attribute):
        "Frequency in Hz"
        attrtype = "f"

        def getter(self):
            return self._up.frequency

        def setter(self, val):
            self._up.frequency = val
            SIM_notify(self._up.obj, Sim_Notify_Frequency_Change)

    def _initialize(self):
        super()._initialize()
        self.frequency = 0

SIM_register_notifier(
    "provider", Sim_Notify_Frequency_Change,
    "Notifier that is triggered when frequency changes. New frequency can"
    " be read via the frequency interface of the object.")

35.3 Custom Notifier Types

It is possible to create custom notifier types. Both the producer and the consumer calls SIM_notifier_type to convert a string specifying the notifier to a notifier type:

notifier_type_t sample = SIM_notifier_type("sample-change");

By convention the string should be expressed as a noun, in all lowercase, with words separated by dash.

35.4 Global Notifiers

There are also global notifiers, which do not have a specific publisher object. The semantics is similar to notifiers with a publisher, but is not meant for low-latency communication between objects, so the API functions require Global Context. Global notifiers are manipulated using SIM_add_global_notifier, SIM_add_global_notifier_once and SIM_remove_global_notifier.

35.5 Sample Code

Additional code samples demonstrating notifiers usage can be found in the sample-notifier-dml and sample-notifier-c++ modules.

34 Port Objects 36 Extension Classes