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