cbdsim_debugging.py.xml 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. <?xml version="1.0" ?>
  2. <diagram name="CBDSimulator" author="Sadaf Mustafiz and Claudio Gomes and Simon Van Mierlo">
  3. <description>
  4. SCCD HUTN model of a CBD simulator
  5. </description>
  6. <inport name="user_input" />
  7. <inport name="user_output" />
  8. <top>
  9. from sccd.runtime.libs.ui import *
  10. from sccd.runtime.libs.utils import *
  11. from CBD_Controller import CBDController
  12. import Options
  13. import sccd.runtime.accurate_time as accurate_time
  14. class Breakpoint:
  15. def __init__(self, name, function, enabled, disable_on_trigger):
  16. self.name = name
  17. self.function = function
  18. self.enabled = enabled
  19. self.disable_on_trigger = disable_on_trigger
  20. </top>
  21. <class name="CBDSimulator" default="True">
  22. <attribute name="iteration"/>
  23. <attribute name="cbdController"/>
  24. <attribute name="delta"/>
  25. <attribute name="clock"/>
  26. <attribute name="model"/>
  27. <attribute name="depGraph"/>
  28. <attribute name="strongComponentList"/>
  29. <attribute name="currentCompIdx"/>
  30. <method name="CBDSimulator">
  31. <parameter name="options"/>
  32. <parameter name="model"/>
  33. <body>
  34. <![CDATA[
  35. self.options = options
  36. self.delta = self.options.getDeltaT() * 1000.0
  37. self.model = model
  38. ]]>
  39. </body>
  40. </method>
  41. <method name="initialize">
  42. <body>
  43. <![CDATA[
  44. self.iteration = 0
  45. self.clock = 0
  46. self.time_next = self.delta
  47. self.cbdController = CBDController(self.model, self.delta)
  48. self.cbdController.initSimulation()
  49. self.state = {b.getBlockName(): b.getSignal() for b in self.model.getBlocks()}
  50. self.breakpoints = []
  51. self.triggered_bp = None
  52. ]]>
  53. </body>
  54. </method>
  55. <method name="endCondition">
  56. <body>
  57. <![CDATA[
  58. return self.iteration >= self.options.getMaxIterations()
  59. ]]>
  60. </body>
  61. </method>
  62. <method name="advanceTime">
  63. <body>
  64. <![CDATA[
  65. self.iteration = self.iteration + 1
  66. self.clock = self.time_next
  67. self.cbdController.advanceTimeStep()
  68. self.time_next = self.clock + self.delta
  69. ]]>
  70. </body>
  71. </method>
  72. <method name="currentComponentIsCycle">
  73. <body>
  74. <![CDATA[
  75. return self.cbdController.componentIsCycle(self.strongComponentList[self.currentCompIdx], self.depGraph)
  76. ]]>
  77. </body>
  78. </method>
  79. <method name="hasNextStrongComponent">
  80. <body>
  81. <![CDATA[
  82. return (self.currentCompIdx + 1) < len(self.strongComponentList)
  83. ]]>
  84. </body>
  85. </method>
  86. <method name="finalize">
  87. <body>
  88. <![CDATA[
  89. from bokeh.plotting import figure, output_file, show
  90. times = []
  91. values = []
  92. for timeValuePair in self.model.getSignal("neg"):
  93. times.append(timeValuePair.time)
  94. values.append(timeValuePair.value)
  95. output_file("./plot.html", title="Plot")
  96. p = figure(title="Something vs Otherthing", x_axis_label="Time", y_axis_label="Values")
  97. p.line(times, values, legend="Something", line_width=1, line_color="red")
  98. show(p)
  99. ]]>
  100. </body>
  101. </method>
  102. <method name="waitTime">
  103. <body>
  104. <![CDATA[
  105. # First, we convert from wall-clock time to simulated time.
  106. # This means the elapsed time in wall-clock time needs to be scaled according to the realtime scale (for example, if the realtime scale is 2, an elapsed time of 1 second in wall-clock time is equal to an elapsed time of 2 seconds in simulated time).
  107. simulated_diff = (accurate_time.time() - self.realtime_start_time) * self.realtime_scale
  108. # time_next and simulated_diff are both in simulated time: so now scale back to wall-clock time by dividing.
  109. # This function returns an amount of miliseconds.
  110. return ((self.time_next - simulated_diff) / self.realtime_scale)
  111. ]]>
  112. </body>
  113. </method>
  114. <method name="addBreakpoint">
  115. <parameter name="name" />
  116. <parameter name="function" />
  117. <parameter name="enabled" default="true" />
  118. <parameter name="disable_on_trigger" default="true" />
  119. <body>
  120. <![CDATA[
  121. if len([bp for bp in self.breakpoints if bp.name == name]) > 0:
  122. return -1
  123. self.breakpoints.append(Breakpoint(name, function, enabled, disable_on_trigger))
  124. return 0
  125. ]]>
  126. </body>
  127. </method>
  128. <method name="delBreakpoint">
  129. <parameter name="name" />
  130. <body>
  131. <![CDATA[
  132. if len([bp for bp in self.breakpoints if bp.name == name]) == 0:
  133. return -1
  134. self.breakpoints = [bp for bp in self.breakpoints if bp.name != name]
  135. return 0
  136. ]]>
  137. </body>
  138. </method>
  139. <method name="toggleBreakpoint">
  140. <parameter name="name" />
  141. <body>
  142. <![CDATA[
  143. if len([bp for bp in self.breakpoints if bp.name == name]) == 0:
  144. return -1
  145. for bp in self.breakpoints:
  146. if bp.name == name:
  147. bp.enabled = enabled
  148. break
  149. return 0
  150. ]]>
  151. </body>
  152. </method>
  153. <method name="breakpointTriggers">
  154. <parameter name="is_realtime_simulation" />
  155. <body>
  156. <![CDATA[
  157. self.triggered_bp = None
  158. for bp in self.breakpoints:
  159. if not bp.enabled:
  160. continue
  161. # include the function in the scope...
  162. exec(bp.function)
  163. # ... and execute it, note that the breakpoint thus has to start with "def breakpoint("
  164. # note that we pass self.time_next instead of self.simulated_time in the case of as-fast-as-possible simulation (or stepping)
  165. # this is to make sure that the simulation is stopped BEFORE the specified time is reached, and not AFTER (because we don't necessarily implement 'step back')
  166. # in case of realtime simulation, we do pass the current simulated time, since we can stop at (more or less) exactly the right time
  167. if breakpoint({'clock': (self.clock if is_realtime_simulation else self.time_next) / 1000.0, 'state': self.state}):
  168. # triggered!
  169. self.triggered_bp = bp.name
  170. if bp.disable_on_trigger:
  171. bp.enabled = False
  172. return True
  173. else:
  174. # not triggered, so continue
  175. continue
  176. return False
  177. ]]>
  178. </body>
  179. </method>
  180. <method name="godEvent">
  181. <parameter name="block_name" />
  182. <parameter name="new_val" />
  183. <body>
  184. <![CDATA[
  185. if block_name not in self.state:
  186. return -1
  187. for b in self.model.getBlocks():
  188. if b.getBlockName() == block_name:
  189. b.setSignal(new_val)
  190. self.state = {b.getBlockName(): b.getSignal() for b in self.model.getBlocks()}
  191. return 0
  192. ]]>
  193. </body>
  194. </method>
  195. <scxml initial="Main" internal_event_lifeline="next_combo_step">
  196. <parallel id="Main">
  197. <state id="SimulationState" initial="Paused">
  198. <state id="Paused">
  199. <onentry><script>print 'entering SimulationState/Paused'</script></onentry>
  200. <onexit><script>print 'exiting SimulationState/Paused'</script></onexit>
  201. <transition target="../Running/Continuous" event="continuous" port="user_input" />
  202. <transition target="../Running/Realtime" event="realtime" port="user_input">
  203. <parameter name="realtime_scale" default="1.0" />
  204. <script>
  205. self.realtime_scale = float(realtime_scale)
  206. </script>
  207. </transition>
  208. <transition target="../Running/BigStep" event="big_step" port="user_input" />
  209. </state>
  210. <state id="PrePaused">
  211. <transition target="../Paused" after="self.sccd_yield()">
  212. <raise event="paused" />
  213. </transition>
  214. </state>
  215. <state id="PreBreakpointTriggered">
  216. <transition target="../Paused" after="self.sccd_yield()">
  217. <raise event="breakpoint_triggered" />
  218. </transition>
  219. </state>
  220. <state id="Running" initial="Continuous">
  221. <onentry><script>print 'entering SimulationState/Running'</script></onentry>
  222. <onexit><script>print 'exiting SimulationState/Running'</script></onexit>
  223. <transition target="../Stopped" cond="self.endCondition()">
  224. <raise event="termination_condition" />
  225. </transition>
  226. <transition target="../PrePaused" event="pause" port="user_input" />
  227. <transition target="../PreBreakpointTriggered" cond="self.breakpointTriggers(INSTATE('./Realtime'))" />
  228. <state id="Continuous" />
  229. <state id="BigStep">
  230. <!-- We go to a special 'BigStepDone' state because in the 'user_output' state, we need to check whether we are currently executing a big step. -->
  231. <transition target="../BigStepDone" event="big_step_done" />
  232. </state>
  233. <state id="BigStepDone">
  234. <!-- We go back to the 'paused' state once the big step has finished. -->
  235. <transition target="../../Paused" after="self.sccd_yield()" />
  236. </state>
  237. <state id="Realtime">
  238. <onentry>
  239. <script>
  240. # If the simulation was paused, we need to reset the start time of the simulation.
  241. # The start time of the simulation is equal to the point in wall-clock time where simulated time is 0.
  242. # If the simulation was paused, we have to recompute this point in time: it is the difference of the wall-clock time and the simulated time.
  243. # If the scale was changed after the pause, this point of course moves backwards (for scales smaller than 1) or forwards (for scales larger than 1)
  244. self.realtime_start_time = accurate_time.time() - (self.clock / self.realtime_scale)
  245. </script>
  246. </onentry>
  247. </state>
  248. </state>
  249. <state id="Stopped">
  250. <onentry><script>print 'entering SimulationState/Stopped'</script></onentry>
  251. <onexit><script>print 'exiting SimulationState/Stopped'</script></onexit>
  252. </state>
  253. </state>
  254. <state id="SimulationFlow" initial="Initialize">
  255. <state id="Initialize">
  256. <onentry>
  257. <script>
  258. <![CDATA[
  259. self.initialize()
  260. ]]>
  261. </script>
  262. </onentry>
  263. <transition target="../CheckTerminationCondition" />
  264. </state>
  265. <state id="CheckTerminationCondition">
  266. <transition target="../CreateDependencyGraph" cond="INSTATE('/Main/SimulationState/Running/Continuous') or INSTATE('/Main/SimulationState/Running/BigStep')" />
  267. <transition target="../Waiting" cond="INSTATE('/Main/SimulationState/Running/Realtime')" />
  268. <transition target="../Stopped" cond="INSTATE('/Main/SimulationState/Stopped')" after="self.sccd_yield()" />
  269. </state>
  270. <state id="Waiting">
  271. <!-- We schedule to go back to the check_termination state after the smallest possible delay (to accomodate for pauses). -->
  272. <transition target="../CheckTerminationCondition" after="self.sccd_yield()" />
  273. <!-- We execute a step when the wait time is smaller than the smallest possible delay. -->
  274. <transition target="../CreateDependencyGraph" cond="self.waitTime() / 1000.0 &lt;= self.sccd_yield()" />
  275. <!-- We set the simulation time to the correct value. -->
  276. <onexit>
  277. <script>
  278. diff = accurate_time.time() - self.realtime_start_time
  279. self.clock = diff * self.realtime_scale
  280. </script>
  281. </onexit>
  282. </state>
  283. <state id="CreateDependencyGraph">
  284. <onentry>
  285. <script>
  286. <![CDATA[
  287. self.depGraph = self.cbdController.createDepGraph(self.iteration)
  288. ]]>
  289. </script>
  290. </onentry>
  291. <transition target="../IsolateStrongComponents" />
  292. </state>
  293. <state id="IsolateStrongComponents">
  294. <onentry>
  295. <script>
  296. <![CDATA[
  297. self.strongComponentList = self.cbdController.createStrongComponents(self.depGraph, self.iteration)
  298. ]]>
  299. </script>
  300. </onentry>
  301. <transition target="../ExecuteSimulationStep">
  302. <script>
  303. <![CDATA[
  304. self.currentCompIdx = -1
  305. ]]>
  306. </script>
  307. </transition>
  308. </state>
  309. <state id="ExecuteSimulationStep" initial="CheckNextComponent">
  310. <state id="CheckNextComponent">
  311. <transition target="../CheckCycle" cond="self.hasNextStrongComponent()">
  312. <script>
  313. <![CDATA[
  314. self.currentCompIdx = self.currentCompIdx + 1
  315. ]]>
  316. </script>
  317. </transition>
  318. <!-- We wait a minimum amount of time to allow pause requests to be processed. -->
  319. <transition target="../../CheckTerminationCondition" cond="not self.hasNextStrongComponent()" after="self.sccd_yield()">
  320. <script>
  321. <![CDATA[
  322. self.advanceTime()
  323. self.state = {b.getBlockName(): b.getSignal() for b in self.model.getBlocks()}
  324. ]]>
  325. </script>
  326. <raise event="big_step_done" />
  327. </transition>
  328. </state>
  329. <state id="CheckCycle">
  330. <transition target="../CheckNextComponent" cond="not self.currentComponentIsCycle()">
  331. <script>
  332. <![CDATA[
  333. self.cbdController.computeNextBlock(self.strongComponentList[self.currentCompIdx], self.iteration)
  334. ]]>
  335. </script>
  336. </transition>
  337. <transition target="../CheckNextComponent" cond="self.currentComponentIsCycle()">
  338. <script>
  339. <![CDATA[
  340. self.cbdController.computeNextAlgebraicLoop(self.strongComponentList[self.currentCompIdx], self.iteration)
  341. ]]>
  342. </script>
  343. </transition>
  344. </state>
  345. </state>
  346. <state id="Stopped" />
  347. </state>
  348. <state id="BreakpointManager" initial="Listening">
  349. <state id="Listening">
  350. <transition target="." event="add_breakpoint" port="user_input">
  351. <parameter name="name"/>
  352. <parameter name="function"/>
  353. <parameter name="enabled"/>
  354. <parameter name="disable_on_trigger"/>
  355. <script>
  356. result = self.addBreakpoint(name, function, bool(enabled), bool(disable_on_trigger))
  357. </script>
  358. <raise event="add_breakpoint_result" port="user_output">
  359. <parameter expr="result" />
  360. </raise>
  361. </transition>
  362. <transition target="." event="del_breakpoint" port="user_input">
  363. <parameter name="name"/>
  364. <script>
  365. result = self.delBreakpoint(name)
  366. </script>
  367. <raise event="del_breakpoint_result" port="user_output">
  368. <parameter expr="result" />
  369. </raise>
  370. </transition>
  371. <transition target="." event="toggle_breakpoint" port="user_input">
  372. <parameter name="name"/>
  373. <script>
  374. result = self.toggleBreakpoint(name)
  375. </script>
  376. <raise event="toggle_breakpoint_result" port="user_output">
  377. <parameter expr="result" />
  378. </raise>
  379. </transition>
  380. <transition target="." event="list_breakpoints" port="user_input">
  381. <raise event="list_breakpoints_result" port="user_output">
  382. <parameter expr="[bp.name for bp in self.breakpoints]" />
  383. </raise>
  384. </transition>
  385. </state>
  386. </state>
  387. <state id="GodEventManager" initial="Listening">
  388. <state id="Listening">
  389. <transition target="." event="god_event" port="user_input" cond="INSTATE('/Main/SimulationState/Paused')">
  390. <parameter name="block_name" />
  391. <parameter name="new_val" />
  392. <script>
  393. result = self.godEvent(block_name, new_val)
  394. </script>
  395. <raise event="god_event_result" port="user_output">
  396. <parameter expr="result" />
  397. </raise>
  398. </transition>
  399. </state>
  400. </state>
  401. <state id="UserOutput" initial="Waiting">
  402. <state id="Waiting">
  403. <transition target="." event="termination_condition">
  404. <raise event="terminated" port="user_output"/>
  405. <raise event="current_state" port="user_output">
  406. <parameter expr="self.clock / 1000.0" />
  407. <parameter expr="self.state" />
  408. </raise>
  409. </transition>
  410. <transition target="." event="paused">
  411. <raise event="paused" port="user_output" />
  412. <raise event="current_state" port="user_output">
  413. <parameter expr="self.clock / 1000.0" />
  414. <parameter expr="self.state" />
  415. </raise>
  416. </transition>
  417. <transition target="." event="big_step_done" cond="INSTATE('/Main/SimulationState/Running/Realtime') or INSTATE('/Main/SimulationState/Running/BigStep') or INSTATE('/Main/SimulationState/Running/BigStepDone')">
  418. <raise event="stepped" port="user_output" />
  419. <raise event="current_state" port="user_output">
  420. <parameter expr="self.clock / 1000.0" />
  421. <parameter expr="self.state" />
  422. </raise>
  423. </transition>
  424. <transition target="." event="breakpoint_triggered">
  425. <raise event="breakpoint_triggered" port="user_output">
  426. <parameter expr="self.triggered_bp" />
  427. </raise>
  428. <raise event="current_state" port="user_output">
  429. <parameter expr="self.clock / 1000.0" />
  430. <parameter expr="self.state" />
  431. </raise>
  432. </transition>
  433. </state>
  434. </state>
  435. <transition target="../SimulationComplete" cond="INSTATE('./SimulationState/Stopped') and INSTATE('./SimulationFlow/Stopped')">
  436. <script>
  437. self.finalize()
  438. </script>
  439. </transition>
  440. </parallel>
  441. <state id="SimulationComplete" />
  442. </scxml>
  443. </class>
  444. </diagram>