From 107bfdd1f84801eb1f52f84393e1085e3c107b96 Mon Sep 17 00:00:00 2001 From: Yentl Van Tendeloo Date: Wed, 11 Jul 2018 17:55:47 +0200 Subject: [PATCH] Add documentation on custom tracers --- doc/tracers_all.rst | 91 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/doc/tracers_all.rst b/doc/tracers_all.rst index 3e96c39..8394003 100644 --- a/doc/tracers_all.rst +++ b/doc/tracers_all.rst @@ -157,3 +157,94 @@ Cell ---- The cell tracer is discussed separately, as it has very specific behaviour and is only applicable to a select number of models. + +Custom +------ + +Additionally, it might necessary to define your own custom tracer. +This can be done by defining a class similar to the following template. +For each trace method, an *aDEVS* parameter is passed, being a reference to the atomic DEVS model doing the transition. +On this *aDEVS* object, the following functions and attributes can be accessed: + + - *aDEVS.getModelFullName()*: full hierarchical name of the model + - *aDEVS.IPorts*: reference to all input ports + - *aDEVS.OPorts*: reference to all output ports + - *aDEVS.state*: state of model + - *aDEVS.time_last[0]*: Time of next transition + - *aDEVS.time_next[0]*: Time of next transition + - *aDEVS.my_output*: dictionary of output events + - *aDEVS.my_input*: dictionary of input events + - *aDEVS.elapsed*: elapsed time before transition + +A custom tracer can be defined as follows:: + + class TracerCustom(object): + def __init__(self, uid, server, filename): + """ + Both uid and server can be ignored, as these are only required for distributed simulation + filename contains the name of the file in which we should write the trace + """ + pass + + def startTracer(self, recover): + """ + Recover is a boolean representing whether or not this is a recovered call (e.g., should the file be overwritten or appended to?) + """ + pass + + def stopTracer(self): + """ + Stops the tracer (e.g., flush the file) + """ + pass + + def traceInternal(self, aDEVS): + """ + Called for each atomic DEVS model that does an internal transition. + """ + pass + + def traceExternal(self, aDEVS): + """ + Called for each atomic DEVS model that does an external transition. + """ + pass + + def traceConfluent(self, aDEVS): + """ + Called for each atomic DEVS model that does a confluent transition. + """ + pass + + def traceInit(self, aDEVS, t): + """ + Called upon initialization of a model. + The parameter *t* contains the time at which the model commences (likely 0). + """ + pass + + def traceUser(self, time, aDEVS, variable, value): + """ + Called upon so called *god events* during debuggin, where a user manually alters the state of an atomic DEVS instance. + """ + pass + +For some "example" tracers, have a look at the built-in tracers of PythonPDEVS, which can be found in *src/tracers*. + +Note that in optimistic synchronization the destructive parts of this operation should be separated. +This can be done using the *runTraceAtController* function:: + + runTraceAtController(server, uid, aDEVS, [time, trace_text]) + +Both the *server* and *uid* are those passed to the constructor of the tracer. + +Finally, after the tracer is defined, it needs to be registered for the simulator to use it. +This is done using the following call on the instantiated simulator:: + + sim.setCustomTracer(self, tracerfile, tracerclass, args): + +Where: + + - *tracerfile*: the Python class containing the implementation of the tracer, which is dynamically imported. + - *tracerclass*: the name of the class implementing the tracing functionality. + - *args*: the list of arguments that must additionally be passed to the tracer (e.g., filename)