An extension class is a Simics class which is never instantiated on its own, but instead is used in the construction of other classes to augment them with functionality defined by the extension class.
The following example defines the my_clock class, which functions just like
the standard clock, although with restricted configurability. The extension
class clock-extension provides most of the functionality that the my_clock
class needs:
import pyobj, simics
class my_clock(pyobj.ConfObject):
class execute(pyobj.Interface):
def run(self):
self.stop = False
while not simics.VT_async_events_pending() and not self.stop:
# advance time to the next pending event and dispatch it
self._up.obj.vtime.iface.event_handler.handle_event()
def stop(self):
self.stop = True
class frequency(pyobj.Interface):
def get(self):
return 1E6
simics.SIM_extend_class("my_clock", "clock-extension")
The clock-extension extension class basically provides the following: a port
object vtime which is used to dispatch pending events and drive the cycle
queues; port objects vtime.cycles and vtime.ps which contain the cycle queue
and the pico seconds queue respectively; a cycle interface which interfaces
the vtime.cycles object; and a cell attribute which determines which cell
the clock belongs to. In short, the clock-extension class defines the event
queues and other functionality needed by Simics for an object to be scheduled.
The my_clock class provides the frequency the cycle clock should use by
implementing the frequency interface; this interface is used by the vtime
object.
When the myclass object gets scheduled, then the run method of the execute
interface will be invoked, and in this simple example, the time is forwarded to
the next pending event by simply invoking the handle_event method.
An extension class is defined just like a regular class. The only difference is
that the class kind should be Sim_Class_Kind_Extension. The following example
defines an extension class which just extends classes with a single attribute
called test:
typedef struct {
int test;
} test_extension_t;
static conf_class_t *test_cls;
static void *
init(conf_object_t *obj)
{
return MM_ZALLOC(1, test_extension_t);
}
static void
dealloc(conf_object_t *obj)
{
test_extension_t *p = SIM_extension_data(obj, test_cls);
MM_FREE(p);
}
static set_error_t
set_test_attr(conf_object_t *obj, attr_value_t *v)
{
test_extension_t *p = SIM_extension_data(obj, test_cls);
p->test = SIM_attr_integer(*v);
return Sim_Set_OK;
}
static attr_value_t
get_test_attr(conf_object_t *obj)
{
test_extension_t *p = SIM_extension_data(obj, test_cls);
return SIM_make_attr_int64(p->test);
}
void
register_test_extension_class(void)
{
class_info_t class_info = {
.init = init,
.dealloc = dealloc,
.kind = Sim_Class_Kind_Extension,
};
cls = SIM_create_class("test_extension", &class_methods);
SIM_register_attribute(
cls, "test",
get_test_attr, set_test_attr,
"i", "sample test attribute");
test_cls = cls;
}
The main point to note is that the object data associated with the extension is
created by the init method and retrieved by calling SIM_extension_data with
the extension class itself as an argument besides the object.
The following example uses the pyobj framework to extend the class trivial
with the extension class test_extension which provides the attribute test:
import pyobj, simics
class test_extension(pyobj.ClassExtension):
class test(pyobj.SimpleAttribute(0, 'i')): pass
class trivial(pyobj.ConfObject):
pass
simics.SIM_extend_class("trivial", "test_extension")
An instance of the trivial class now has the test attribute defined by the
extension class:
simics> @SIM_create_object('trivial', 'trivial')
simics> trivial->test = 22