tracers_all.rst 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. Tracers
  2. =======
  3. PythonPDEVS provides several features that allow you to trace the execution of your model.
  4. Here, we present four built-in tracers, and present the interface used to create your own tracer.
  5. For all tracers, providing the *None* object as the filename causes the trace to be printed to stdout, instead of writing it to a file.
  6. In the context of distributed simulation, tracing is a *destructive event*, meaning that it can only occur after the GVT.
  7. As such, tracing happens in blocks as soon as fossil collection occurs.
  8. Verbose
  9. -------
  10. The first tracer is the verbose tracer, which generates a purely textual trace of your model execution.
  11. It has already been presented before, and was used by invoking the following configuration option::
  12. sim.setVerbose(None)
  13. Note that this is the only built-in tracer that works without additional configuration of the model.
  14. An example snippet is shown below::
  15. __ Current Time: 0.00 __________________________________________
  16. INITIAL CONDITIONS in model <trafficSystem.trafficLight>
  17. Initial State: red
  18. Next scheduled internal transition at time 58.50
  19. INITIAL CONDITIONS in model <trafficSystem.policeman>
  20. Initial State: idle
  21. Next scheduled internal transition at time 200.00
  22. __ Current Time: 58.50 __________________________________________
  23. INTERNAL TRANSITION in model <trafficSystem.trafficLight>
  24. New State: green
  25. Output Port Configuration:
  26. port <OBSERVED>:
  27. grey
  28. Next scheduled internal transition at time 108.50
  29. __ Current Time: 108.50 __________________________________________
  30. INTERNAL TRANSITION in model <trafficSystem.trafficLight>
  31. New State: yellow
  32. Output Port Configuration:
  33. port <OBSERVED>:
  34. yellow
  35. Next scheduled internal transition at time 118.50
  36. ...
  37. __ Current Time: 200.00 __________________________________________
  38. EXTERNAL TRANSITION in model <trafficSystem.trafficLight>
  39. Input Port Configuration:
  40. port <INTERRUPT>:
  41. toManual
  42. New State: manual
  43. Next scheduled internal transition at time inf
  44. INTERNAL TRANSITION in model <trafficSystem.policeman>
  45. New State: working
  46. Output Port Configuration:
  47. port <OUT>:
  48. toManual
  49. Next scheduled internal transition at time 300.00
  50. XML
  51. ---
  52. The second tracer is the XML tracer, which generates an XML-structured trace of your model execution, compliant to the notation presented in `Bill Song's thesis <http://msdl.cs.mcgill.ca/people/bill/thesis/latexthesis.pdf>`_.
  53. It can also simply be enabled by setting the following configuration option::
  54. sim.setXML(None)
  55. To enable this XML tracing, the model has to be augmented with facilities to dump the current state in the form of an XML notation.
  56. This is done with the *toXML()* method, which has to be defined for all complex states, and must return a string to be embedded in the XML.
  57. This string is pasted as-is in the trace file, and should therefore not contain forbidden characters (e.g., <).
  58. For example, a *toXML* method for the traffic light can look as follows::
  59. class TrafficLightMode:
  60. ...
  61. def toXML(self):
  62. return "<mode>%s</mode>" % self.__colour
  63. An example snippet is shown below::
  64. <trace>
  65. <event>
  66. <model>trafficSystem.trafficLight</model>
  67. <time>0.0</time>
  68. <kind>EX</kind>
  69. <state>
  70. <mode>red</mode><![CDATA[red]]>
  71. </state>
  72. </event>
  73. <event>
  74. <model>trafficSystem.policeman</model>
  75. <time>0.0</time>
  76. <kind>EX</kind>
  77. <state>
  78. <mode>idle</mode><![CDATA[idle]]>
  79. </state>
  80. </event>
  81. <event>
  82. <model>trafficSystem.trafficLight</model>
  83. <time>58.5</time>
  84. <kind>IN</kind>
  85. <port name="OBSERVED" category="O">
  86. <message>grey</message>
  87. </port>
  88. <state>
  89. <mode>green</mode><![CDATA[green]]>
  90. </state>
  91. </event>
  92. ...
  93. <event>
  94. <model>trafficSystem.policeman</model>
  95. <time>200.0</time>
  96. <kind>IN</kind>
  97. <port name="OUT" category="O">
  98. <message>toManual</message>
  99. </port>
  100. <state>
  101. <mode>working</mode><![CDATA[working]]>
  102. </state>
  103. </event>
  104. <event>
  105. <model>trafficSystem.trafficLight</model>
  106. <time>200.0</time>
  107. <kind>EX</kind>
  108. <port name="INTERRUPT" category="I">
  109. <message>toManual</message>
  110. </port>
  111. <state>
  112. <mode>manual</mode><![CDATA[manual]]>
  113. </state>
  114. </event>
  115. </trace>
  116. VCD
  117. ---
  118. TODO
  119. Cell
  120. ----
  121. The cell tracer is discussed separately, as it has very specific behaviour and is only applicable to a select number of models.
  122. Custom
  123. ------
  124. Additionally, it might necessary to define your own custom tracer.
  125. This can be done by defining a class similar to the following template.
  126. For each trace method, an *aDEVS* parameter is passed, being a reference to the atomic DEVS model doing the transition.
  127. On this *aDEVS* object, the following functions and attributes can be accessed:
  128. - *aDEVS.getModelFullName()*: full hierarchical name of the model
  129. - *aDEVS.IPorts*: reference to all input ports
  130. - *aDEVS.OPorts*: reference to all output ports
  131. - *aDEVS.state*: state of model
  132. - *aDEVS.time_last[0]*: Time of next transition
  133. - *aDEVS.time_next[0]*: Time of next transition
  134. - *aDEVS.my_output*: dictionary of output events
  135. - *aDEVS.my_input*: dictionary of input events
  136. - *aDEVS.elapsed*: elapsed time before transition
  137. A custom tracer can be defined as follows::
  138. class TracerCustom(object):
  139. def __init__(self, uid, server, filename):
  140. """
  141. Both uid and server can be ignored, as these are only required for distributed simulation
  142. filename contains the name of the file in which we should write the trace
  143. """
  144. pass
  145. def startTracer(self, recover):
  146. """
  147. Recover is a boolean representing whether or not this is a recovered call (e.g., should the file be overwritten or appended to?)
  148. """
  149. pass
  150. def stopTracer(self):
  151. """
  152. Stops the tracer (e.g., flush the file)
  153. """
  154. pass
  155. def traceInternal(self, aDEVS):
  156. """
  157. Called for each atomic DEVS model that does an internal transition.
  158. """
  159. pass
  160. def traceExternal(self, aDEVS):
  161. """
  162. Called for each atomic DEVS model that does an external transition.
  163. """
  164. pass
  165. def traceConfluent(self, aDEVS):
  166. """
  167. Called for each atomic DEVS model that does a confluent transition.
  168. """
  169. pass
  170. def traceInit(self, aDEVS, t):
  171. """
  172. Called upon initialization of a model.
  173. The parameter *t* contains the time at which the model commences (likely 0).
  174. """
  175. pass
  176. def traceUser(self, time, aDEVS, variable, value):
  177. """
  178. Called upon so called *god events* during debuggin, where a user manually alters the state of an atomic DEVS instance.
  179. """
  180. pass
  181. For some "example" tracers, have a look at the built-in tracers of PythonPDEVS, which can be found in *src/tracers*.
  182. Note that in optimistic synchronization the destructive parts of this operation should be separated.
  183. This can be done using the *runTraceAtController* function::
  184. runTraceAtController(server, uid, aDEVS, [time, trace_text])
  185. Both the *server* and *uid* are those passed to the constructor of the tracer.
  186. Finally, after the tracer is defined, it needs to be registered for the simulator to use it.
  187. This is done using the following call on the instantiated simulator::
  188. sim.setCustomTracer(self, tracerfile, tracerclass, args):
  189. Where:
  190. - *tracerfile*: the Python class containing the implementation of the tracer, which is dynamically imported.
  191. - *tracerclass*: the name of the class implementing the tracing functionality.
  192. - *args*: the list of arguments that must additionally be passed to the tracer (e.g., filename)